From 5047c4d083d0cb939200f29b5554dce697847998 Mon Sep 17 00:00:00 2001
From: GaryOderNichts <12049776+GaryOderNichts@users.noreply.github.com>
Date: Mon, 27 Nov 2023 12:21:52 +0100
Subject: [PATCH 001/319] GDBStub: Fix checkSum string to int conversion
(#1029)
---
src/Cafe/HW/Espresso/Debugger/GDBStub.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp b/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp
index e934e55d..c8308594 100644
--- a/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp
+++ b/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp
@@ -356,7 +356,7 @@ void GDBServer::ThreadFunc()
}
char checkSumStr[2];
receiveMessage(checkSumStr, 2);
- uint32_t checkSum = std::stoi(checkSumStr, nullptr, 16);
+ uint32_t checkSum = std::stoi(std::string(checkSumStr, sizeof(checkSumStr)), nullptr, 16);
assert((checkedSum & 0xFF) == checkSum);
HandleCommand(message);
From 09409a51089db5432c0bdd7ec8f2e3907a8b2669 Mon Sep 17 00:00:00 2001
From: shinra-electric <50119606+shinra-electric@users.noreply.github.com>
Date: Mon, 27 Nov 2023 12:24:26 +0100
Subject: [PATCH 002/319] Set macOS min version to 12.0 Monterey (#1025)
---
src/CMakeLists.txt | 1 +
src/resource/MacOSXBundleInfo.plist.in | 8 +++++---
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 00a43a80..8ab07e7a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -81,6 +81,7 @@ if (MACOS_BUNDLE)
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2023 Cemu Project")
set(MACOSX_BUNDLE_CATEGORY "public.app-category.games")
+ set(MACOSX_MINIMUM_SYSTEM_VERSION "12.0")
set_target_properties(CemuBin PROPERTIES
MACOSX_BUNDLE true
diff --git a/src/resource/MacOSXBundleInfo.plist.in b/src/resource/MacOSXBundleInfo.plist.in
index c181b388..74dc0d59 100644
--- a/src/resource/MacOSXBundleInfo.plist.in
+++ b/src/resource/MacOSXBundleInfo.plist.in
@@ -26,7 +26,9 @@
NSHumanReadableCopyright
${MACOSX_BUNDLE_COPYRIGHT}
- LSApplicationCategoryType
- ${MACOSX_BUNDLE_CATEGORY}
+ LSApplicationCategoryType
+ ${MACOSX_BUNDLE_CATEGORY}
+ LSMinimumSystemVersion
+ ${MACOSX_MINIMUM_SYSTEM_VERSION}
-
\ No newline at end of file
+
From 18490830738c61b1b35fa11a9207bcf3fc4edd3e Mon Sep 17 00:00:00 2001
From: capitalistspz
Date: Wed, 6 Dec 2023 01:33:29 +0000
Subject: [PATCH 003/319] Use hidapi for Wiimotes on Windows (#1033)
---
CMakeLists.txt | 5 +-
src/input/CMakeLists.txt | 11 +-
.../api/Wiimote/WiimoteControllerProvider.cpp | 4 -
.../api/Wiimote/windows/WinWiimoteDevice.cpp | 130 ------------------
.../api/Wiimote/windows/WinWiimoteDevice.h | 24 ----
vcpkg.json | 5 +-
6 files changed, 4 insertions(+), 175 deletions(-)
delete mode 100644 src/input/api/Wiimote/windows/WinWiimoteDevice.cpp
delete mode 100644 src/input/api/Wiimote/windows/WinWiimoteDevice.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9dc1a6f2..c988508c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -89,10 +89,9 @@ if (WIN32)
option(ENABLE_XINPUT "Enables the usage of XInput" ON)
option(ENABLE_DIRECTINPUT "Enables the usage of DirectInput" ON)
add_compile_definitions(HAS_DIRECTINPUT)
- set(ENABLE_WIIMOTE ON)
-elseif (UNIX)
- option(ENABLE_HIDAPI "Build with HIDAPI" ON)
endif()
+
+option(ENABLE_HIDAPI "Build with HIDAPI" ON)
option(ENABLE_SDL "Enables the SDLController backend" ON)
# audio backends
diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt
index 53b4dc3b..9f7873a1 100644
--- a/src/input/CMakeLists.txt
+++ b/src/input/CMakeLists.txt
@@ -70,18 +70,9 @@ if (ENABLE_WIIMOTE)
api/Wiimote/NativeWiimoteController.h
api/Wiimote/NativeWiimoteController.cpp
api/Wiimote/WiimoteDevice.h
- )
- if (ENABLE_HIDAPI)
- target_sources(CemuInput PRIVATE
api/Wiimote/hidapi/HidapiWiimote.cpp
api/Wiimote/hidapi/HidapiWiimote.h
- )
- elseif (WIN32)
- target_sources(CemuInput PRIVATE
- api/Wiimote/windows/WinWiimoteDevice.cpp
- api/Wiimote/windows/WinWiimoteDevice.h
- )
- endif()
+ )
endif ()
diff --git a/src/input/api/Wiimote/WiimoteControllerProvider.cpp b/src/input/api/Wiimote/WiimoteControllerProvider.cpp
index 0ca00a1a..55f28c01 100644
--- a/src/input/api/Wiimote/WiimoteControllerProvider.cpp
+++ b/src/input/api/Wiimote/WiimoteControllerProvider.cpp
@@ -2,11 +2,7 @@
#include "input/api/Wiimote/NativeWiimoteController.h"
#include "input/api/Wiimote/WiimoteMessages.h"
-#ifdef HAS_HIDAPI
#include "input/api/Wiimote/hidapi/HidapiWiimote.h"
-#elif BOOST_OS_WINDOWS
-#include "input/api/Wiimote/windows/WinWiimoteDevice.h"
-#endif
#include
#include
diff --git a/src/input/api/Wiimote/windows/WinWiimoteDevice.cpp b/src/input/api/Wiimote/windows/WinWiimoteDevice.cpp
deleted file mode 100644
index 09d73013..00000000
--- a/src/input/api/Wiimote/windows/WinWiimoteDevice.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-#include "input/api/Wiimote/windows/WinWiimoteDevice.h"
-
-#include
-#include
-
-#pragma comment(lib, "Setupapi.lib")
-#pragma comment(lib, "hid.lib")
-
-WinWiimoteDevice::WinWiimoteDevice(HANDLE handle, std::vector identifier)
- : m_handle(handle), m_identifier(std::move(identifier))
-{
- m_overlapped.hEvent = CreateEvent(nullptr, TRUE, TRUE, nullptr);
-}
-
-WinWiimoteDevice::~WinWiimoteDevice()
-{
- CancelIo(m_handle);
- ResetEvent(m_overlapped.hEvent);
- CloseHandle(m_handle);
-}
-
-bool WinWiimoteDevice::write_data(const std::vector& data)
-{
- return HidD_SetOutputReport(m_handle, (void*)data.data(), (ULONG)data.size());
-}
-
-std::optional> WinWiimoteDevice::read_data()
-{
- DWORD read = 0;
- std::array buffer{};
-
- if (!ReadFile(m_handle, buffer.data(), (DWORD)buffer.size(), &read, &m_overlapped))
- {
- const auto error = GetLastError();
- if (error == ERROR_DEVICE_NOT_CONNECTED)
- return {};
- else if (error == ERROR_IO_PENDING)
- {
- const auto wait_result = WaitForSingleObject(m_overlapped.hEvent, 100);
- if (wait_result == WAIT_TIMEOUT)
- {
- CancelIo(m_handle);
- ResetEvent(m_overlapped.hEvent);
- return {};
- }
- else if (wait_result == WAIT_FAILED)
- return {};
-
- if (GetOverlappedResult(m_handle, &m_overlapped, &read, FALSE) == FALSE)
- return {};
- }
- else if (error == ERROR_INVALID_HANDLE)
- {
- ResetEvent(m_overlapped.hEvent);
- return {};
- }
- else
- {
- cemu_assert_debug(false);
- }
- }
-
- ResetEvent(m_overlapped.hEvent);
- if (read == 0)
- return {};
-
- return {{buffer.cbegin(), buffer.cbegin() + read}};
-}
-
-std::vector WinWiimoteDevice::get_devices()
-{
- std::vector result;
-
- GUID hid_guid;
- HidD_GetHidGuid(&hid_guid);
-
- const auto device_info = SetupDiGetClassDevs(&hid_guid, nullptr, nullptr, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
-
- for (DWORD index = 0; ; ++index)
- {
- SP_DEVICE_INTERFACE_DATA device_data{};
- device_data.cbSize = sizeof(device_data);
- if (SetupDiEnumDeviceInterfaces(device_info, nullptr, &hid_guid, index, &device_data) == FALSE)
- break;
-
- DWORD device_data_len;
- if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, nullptr, 0, &device_data_len, nullptr) == FALSE
- && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
- continue;
-
- std::vector detail_data_buffer;
- detail_data_buffer.resize(device_data_len);
-
- const auto detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)detail_data_buffer.data();
- detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
-
- if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, device_data_len, nullptr, nullptr)
- == FALSE)
- continue;
-
- HANDLE device_handle = CreateFile(detail_data->DevicePath, (GENERIC_READ | GENERIC_WRITE),
- (FILE_SHARE_READ | FILE_SHARE_WRITE), nullptr, OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED, nullptr);
- if (device_handle == INVALID_HANDLE_VALUE)
- continue;
-
- HIDD_ATTRIBUTES attributes{};
- attributes.Size = sizeof(attributes);
- if (HidD_GetAttributes(device_handle, &attributes) == FALSE)
- {
- CloseHandle(device_handle);
- continue;
- }
-
- if (attributes.VendorID != 0x057e || (attributes.ProductID != 0x0306 && attributes.ProductID != 0x0330))
- {
- CloseHandle(device_handle);
- continue;
- }
-
- result.emplace_back(std::make_shared(device_handle, detail_data_buffer));
- }
-
- return result;
-}
-
-bool WinWiimoteDevice::operator==(WiimoteDevice& o) const
-{
- return m_identifier == static_cast(o).m_identifier;
-}
diff --git a/src/input/api/Wiimote/windows/WinWiimoteDevice.h b/src/input/api/Wiimote/windows/WinWiimoteDevice.h
deleted file mode 100644
index 077882db..00000000
--- a/src/input/api/Wiimote/windows/WinWiimoteDevice.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#include "input/api/Wiimote/WiimoteDevice.h"
-
-class WinWiimoteDevice : public WiimoteDevice
-{
-public:
- WinWiimoteDevice(HANDLE handle, std::vector identifier);
- ~WinWiimoteDevice();
-
- bool write_data(const std::vector& data) override;
- std::optional> read_data() override;
-
- static std::vector get_devices();
-
- bool operator==(WiimoteDevice& o) const override;
-
-private:
- HANDLE m_handle;
- OVERLAPPED m_overlapped{};
- std::vector m_identifier;
-};
-
-using WiimoteDevice_t = WinWiimoteDevice;
diff --git a/vcpkg.json b/vcpkg.json
index 7ea8058e..d14a1a8a 100644
--- a/vcpkg.json
+++ b/vcpkg.json
@@ -26,10 +26,7 @@
"boost-static-string",
"boost-random",
"fmt",
- {
- "name": "hidapi",
- "platform": "!windows"
- },
+ "hidapi",
"libpng",
"glm",
{
From b6aaf6633063be47d89a8216e269e32aec5a4b49 Mon Sep 17 00:00:00 2001
From: qurious-pixel <62252937+qurious-pixel@users.noreply.github.com>
Date: Wed, 6 Dec 2023 17:07:50 -0800
Subject: [PATCH 004/319] [AppImage] Bundle libstdc++ (#1038)
---
dist/linux/appimage.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/dist/linux/appimage.sh b/dist/linux/appimage.sh
index 7043a759..60a50329 100755
--- a/dist/linux/appimage.sh
+++ b/dist/linux/appimage.sh
@@ -46,6 +46,7 @@ fi
echo "Cemu Version Cemu-${GITVERSION}"
rm AppDir/usr/lib/libwayland-client.so.0
+cp /lib/x86_64-linux-gnu/libstdc++.so.6 AppDir/usr/lib/
echo -e "export LC_ALL=C\nexport FONTCONFIG_PATH=/etc/fonts" >> AppDir/apprun-hooks/linuxdeploy-plugin-gtk.sh
VERSION="${GITVERSION}" ./mkappimage.AppImage --appimage-extract-and-run "${GITHUB_WORKSPACE}"/AppDir
From f6bb666abf9a34bab705b53bf8fb913696bb4b31 Mon Sep 17 00:00:00 2001
From: shinra-electric <50119606+shinra-electric@users.noreply.github.com>
Date: Sun, 10 Dec 2023 08:30:08 +0100
Subject: [PATCH 005/319] Mac: Add wua filetype to info.plist (#1039)
---
src/CMakeLists.txt | 1 +
src/resource/MacOSXBundleInfo.plist.in | 13 +++++++++++++
2 files changed, 14 insertions(+)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8ab07e7a..de9a6600 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -82,6 +82,7 @@ if (MACOS_BUNDLE)
set(MACOSX_BUNDLE_CATEGORY "public.app-category.games")
set(MACOSX_MINIMUM_SYSTEM_VERSION "12.0")
+ set(MACOSX_BUNDLE_TYPE_EXTENSION "wua")
set_target_properties(CemuBin PROPERTIES
MACOSX_BUNDLE true
diff --git a/src/resource/MacOSXBundleInfo.plist.in b/src/resource/MacOSXBundleInfo.plist.in
index 74dc0d59..98064735 100644
--- a/src/resource/MacOSXBundleInfo.plist.in
+++ b/src/resource/MacOSXBundleInfo.plist.in
@@ -30,5 +30,18 @@
${MACOSX_BUNDLE_CATEGORY}
LSMinimumSystemVersion
${MACOSX_MINIMUM_SYSTEM_VERSION}
+ CFBundleDocumentTypes
+
+
+ CFBundleTypeExtensions
+
+ ${MACOSX_BUNDLE_TYPE_EXTENSION}
+
+ CFBundleTypeName
+ Wii U File
+ CFBundleTypeRole
+ Viewer
+
+
From 9398c0ca6b142ec92e297dd099bbcba7f22749b1 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Mon, 20 Nov 2023 22:18:17 +0100
Subject: [PATCH 006/319] Latte: Simplify and fix texture copy
---
src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp | 26 +++------------------
src/Cafe/HW/Latte/Core/LatteTexture.cpp | 18 ++++++++++++--
2 files changed, 19 insertions(+), 25 deletions(-)
diff --git a/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp b/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp
index df99307c..4f5b24ad 100644
--- a/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp
@@ -46,9 +46,7 @@ void LatteSurfaceCopy_copySurfaceNew(MPTR srcPhysAddr, MPTR srcMipAddr, uint32 s
// mark source and destination texture as still in use
LatteTC_MarkTextureStillInUse(destinationTexture);
LatteTC_MarkTextureStillInUse(sourceTexture);
- // determine GL slice indices
sint32 realSrcSlice = srcSlice;
- sint32 realDstSlice = dstSlice;
if (LatteTexture_doesEffectiveRescaleRatioMatch(sourceTexture, sourceView->firstMip, destinationTexture, destinationView->firstMip))
{
// adjust copy size
@@ -62,29 +60,11 @@ void LatteSurfaceCopy_copySurfaceNew(MPTR srcPhysAddr, MPTR srcMipAddr, uint32 s
LatteTexture_scaleToEffectiveSize(sourceTexture, &effectiveCopyWidth, &effectiveCopyHeight, 0);
// copy slice
if (sourceView->baseTexture->isDepth != destinationView->baseTexture->isDepth)
- {
g_renderer->surfaceCopy_copySurfaceWithFormatConversion(sourceTexture, sourceView->firstMip, sourceView->firstSlice, destinationTexture, destinationView->firstMip, destinationView->firstSlice, copyWidth, copyHeight);
- uint64 eventCounter = LatteTexture_getNextUpdateEventCounter();
- LatteTexture_MarkDynamicTextureAsChanged(destinationTexture->baseView, destinationView->firstSlice, destinationView->firstMip, eventCounter);
- }
else
- {
- // calculate mip levels relative to texture base
- sint32 texDstMipLevel;
- if (destinationTexture->physAddress == dstPhysAddr)
- {
- texDstMipLevel = dstLevel;
- }
- else
- {
- // todo - handle mip addresses properly
- texDstMipLevel = dstLevel - destinationView->firstMip;
- }
-
- g_renderer->texture_copyImageSubData(sourceTexture, sourceView->firstMip, 0, 0, realSrcSlice, destinationTexture, texDstMipLevel, 0, 0, realDstSlice, effectiveCopyWidth, effectiveCopyHeight, 1);
- uint64 eventCounter = LatteTexture_getNextUpdateEventCounter();
- LatteTexture_MarkDynamicTextureAsChanged(destinationTexture->baseView, destinationView->firstSlice, texDstMipLevel, eventCounter);
- }
+ g_renderer->texture_copyImageSubData(sourceTexture, sourceView->firstMip, 0, 0, realSrcSlice, destinationTexture, destinationView->firstMip, 0, 0, destinationView->firstSlice, effectiveCopyWidth, effectiveCopyHeight, 1);
+ const uint64 eventCounter = LatteTexture_getNextUpdateEventCounter();
+ LatteTexture_MarkDynamicTextureAsChanged(destinationTexture->baseView, destinationView->firstSlice, destinationView->firstMip, eventCounter);
}
else
{
diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.cpp b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
index 19162e04..42a9d8c6 100644
--- a/src/Cafe/HW/Latte/Core/LatteTexture.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
@@ -836,6 +836,11 @@ bool IsDimensionCompatibleForView(Latte::E_DIM baseDim, Latte::E_DIM viewDim)
// not compatible
incompatibleDim = true;
}
+ else if (baseDim == Latte::E_DIM::DIM_3D && viewDim == Latte::E_DIM::DIM_3D)
+ {
+ // incompatible by default, but may be compatible if the view matches the depth of the base texture and starts at mip/slice 0
+ incompatibleDim = true;
+ }
else if ((baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_CUBEMAP) ||
(baseDim == Latte::E_DIM::DIM_CUBEMAP && viewDim == Latte::E_DIM::DIM_2D))
{
@@ -872,7 +877,9 @@ VIEWCOMPATIBILITY LatteTexture_CanTextureBeRepresentedAsView(LatteTexture* baseT
return VIEW_NOT_COMPATIBLE; // depth and non-depth formats are never compatible (on OpenGL)
if (!LatteTexture_IsTexelSizeCompatibleFormat(baseTexture->format, format) || baseTexture->width != width || baseTexture->height != height)
return VIEW_NOT_COMPATIBLE;
- if (!IsDimensionCompatibleForView(baseTexture->dim, dimView))
+ // 3D views are only compatible on Vulkan if they match the base texture in regards to mip and slice count
+ bool isCompatible3DView = dimView == Latte::E_DIM::DIM_3D && baseTexture->dim == dimView && firstSlice == 0 && firstMip == 0 && baseTexture->mipLevels == numMip && baseTexture->depth == numSlice;
+ if (!isCompatible3DView && !IsDimensionCompatibleForView(baseTexture->dim, dimView))
return VIEW_NOT_COMPATIBLE;
if (baseTexture->isDepth && baseTexture->format != format)
{
@@ -999,6 +1006,7 @@ void LatteTexture_RecreateTextureWithDifferentMipSliceCount(LatteTexture* textur
// create new texture representation
// if allowCreateNewDataTexture is true, a new texture will be created if necessary. If it is false, only existing textures may be used, except if a data-compatible version of the requested texture already exists and it's not view compatible
+// the returned view will map to the provided mip and slice range within the created texture, this is to match the behavior of lookupSliceEx
LatteTextureView* LatteTexture_CreateMapping(MPTR physAddr, MPTR physMipAddr, sint32 width, sint32 height, sint32 depth, sint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, Latte::E_GX2SURFFMT format, Latte::E_DIM dimBase, Latte::E_DIM dimView, bool isDepth, bool allowCreateNewDataTexture)
{
if (format == Latte::E_GX2SURFFMT::INVALID_FORMAT)
@@ -1105,11 +1113,17 @@ LatteTextureView* LatteTexture_CreateMapping(MPTR physAddr, MPTR physMipAddr, si
if (allowCreateNewDataTexture == false)
return nullptr;
LatteTextureView* view = LatteTexture_CreateTexture(0, dimBase, physAddr, physMipAddr, format, width, height, depth, pitch, firstMip + numMip, swizzle, tileMode, isDepth);
+ LatteTexture* newTexture = view->baseTexture;
LatteTexture_GatherTextureRelations(view->baseTexture);
LatteTexture_UpdateTextureFromDynamicChanges(view->baseTexture);
// delete any individual smaller slices/mips that have become redundant
LatteTexture_DeleteAbsorbedSubtextures(view->baseTexture);
- return view;
+ // create view
+ sint32 relativeMipIndex;
+ sint32 relativeSliceIndex;
+ VIEWCOMPATIBILITY viewCompatibility = LatteTexture_CanTextureBeRepresentedAsView(newTexture, physAddr, width, height, pitch, dimView, format, isDepth, firstMip, numMip, firstSlice, numSlice, relativeMipIndex, relativeSliceIndex);
+ cemu_assert(viewCompatibility == VIEW_COMPATIBLE);
+ return view->baseTexture->GetOrCreateView(dimView, format, relativeMipIndex + firstMip, numMip, relativeSliceIndex + firstSlice, numSlice);
}
LatteTextureView* LatteTC_LookupTextureByData(MPTR physAddr, sint32 width, sint32 height, sint32 pitch, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, sint32* searchIndex)
From 67f7ce815c0b97c5ff0f19e9c3ad9a6d64d756a7 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Tue, 21 Nov 2023 16:39:55 +0100
Subject: [PATCH 007/319] nn_pdm: Refactor code to use new module structure
---
src/Cafe/CafeSystem.cpp | 7 +-
src/Cafe/IOSU/PDM/iosu_pdm.cpp | 135 +++++++++++++++++++++++++++------
src/Cafe/IOSU/PDM/iosu_pdm.h | 7 +-
3 files changed, 117 insertions(+), 32 deletions(-)
diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp
index 3d06281e..30dab1d4 100644
--- a/src/Cafe/CafeSystem.cpp
+++ b/src/Cafe/CafeSystem.cpp
@@ -530,7 +530,8 @@ namespace CafeSystem
{
// entries in this list are ordered by initialization order. Shutdown in reverse order
iosu::kernel::GetModule(),
- iosu::fpd::GetModule()
+ iosu::fpd::GetModule(),
+ iosu::pdm::GetModule(),
};
// initialize all subsystems which are persistent and don't depend on a game running
@@ -571,7 +572,6 @@ namespace CafeSystem
iosu::iosuAcp_init();
iosu::boss_init();
iosu::nim::Initialize();
- iosu::pdm::Initialize();
iosu::odm::Initialize();
// init Cafe OS
avm::Initialize();
@@ -840,7 +840,6 @@ namespace CafeSystem
coreinit::OSSchedulerBegin(3);
else
coreinit::OSSchedulerBegin(1);
- iosu::pdm::StartTrackingTime(GetForegroundTitleId());
}
void LaunchForegroundTitle()
@@ -970,8 +969,6 @@ namespace CafeSystem
RPLLoader_ResetState();
for(auto it = s_iosuModules.rbegin(); it != s_iosuModules.rend(); ++it)
(*it)->TitleStop();
- // stop time tracking
- iosu::pdm::Stop();
// reset Cemu subsystems
PPCRecompiler_Shutdown();
GraphicPack2::Reset();
diff --git a/src/Cafe/IOSU/PDM/iosu_pdm.cpp b/src/Cafe/IOSU/PDM/iosu_pdm.cpp
index 45b4a1d8..e54529a9 100644
--- a/src/Cafe/IOSU/PDM/iosu_pdm.cpp
+++ b/src/Cafe/IOSU/PDM/iosu_pdm.cpp
@@ -1,4 +1,5 @@
#include "iosu_pdm.h"
+#include "Cafe/CafeSystem.h"
#include "config/ActiveSettings.h"
#include "Common/FileStream.h"
#include "util/helpers/Semaphore.h"
@@ -17,7 +18,8 @@ namespace iosu
{
namespace pdm
{
- std::mutex sDiaryLock;
+ std::recursive_mutex sPlaystatsLock;
+ std::recursive_mutex sDiaryLock;
fs::path GetPDFile(const char* filename)
{
@@ -80,14 +82,16 @@ namespace iosu
static_assert((NUM_PLAY_STATS_ENTRIES * sizeof(PlayStatsEntry)) == 0x1400);
}
- void LoadPlaystats()
+ void OpenPlaystats()
{
+ std::unique_lock _l(sPlaystatsLock);
PlayStats.numEntries = 0;
for (size_t i = 0; i < NUM_PLAY_STATS_ENTRIES; i++)
{
auto& e = PlayStats.entry[i];
memset(&e, 0, sizeof(PlayStatsEntry));
}
+ cemu_assert_debug(!PlayStats.fs);
PlayStats.fs = FileStream::openFile2(GetPDFile("PlayStats.dat"), true);
if (!PlayStats.fs)
{
@@ -98,18 +102,39 @@ namespace iosu
{
delete PlayStats.fs;
PlayStats.fs = nullptr;
- cemuLog_log(LogType::Force, "PlayStats.dat malformed");
+ cemuLog_log(LogType::Force, "PlayStats.dat malformed. Time tracking wont be used");
// dont delete the existing file in case it could still be salvaged (todo) and instead just dont track play time
return;
}
+ PlayStats.numEntries = 0;
PlayStats.fs->readData(&PlayStats.numEntries, sizeof(uint32be));
if (PlayStats.numEntries > NUM_PLAY_STATS_ENTRIES)
PlayStats.numEntries = NUM_PLAY_STATS_ENTRIES;
PlayStats.fs->readData(PlayStats.entry, NUM_PLAY_STATS_ENTRIES * 20);
}
+ void ClosePlaystats()
+ {
+ std::unique_lock _l(sPlaystatsLock);
+ if (PlayStats.fs)
+ {
+ delete PlayStats.fs;
+ PlayStats.fs = nullptr;
+ }
+ }
+
+ void UnloadPlaystats()
+ {
+ std::unique_lock _l(sPlaystatsLock);
+ cemu_assert_debug(!PlayStats.fs); // unloading expects that file is closed
+ PlayStats.numEntries = 0;
+ for(auto& it : PlayStats.entry)
+ it = PlayStatsEntry{};
+ }
+
PlayStatsEntry* PlayStats_GetEntry(uint64 titleId)
{
+ std::unique_lock _l(sPlaystatsLock);
uint32be titleIdHigh = (uint32)(titleId>>32);
uint32be titleIdLow = (uint32)(titleId & 0xFFFFFFFF);
size_t numEntries = PlayStats.numEntries;
@@ -121,7 +146,7 @@ namespace iosu
return nullptr;
}
- void PlayStats_WriteEntry(PlayStatsEntry* entry, bool writeEntryCount = false)
+ void PlayStats_WriteEntryNoLock(PlayStatsEntry* entry, bool writeEntryCount = false)
{
if (!PlayStats.fs)
return;
@@ -141,8 +166,15 @@ namespace iosu
}
}
+ void PlayStats_WriteEntry(PlayStatsEntry* entry, bool writeEntryCount = false)
+ {
+ std::unique_lock _l(sPlaystatsLock);
+ PlayStats_WriteEntryNoLock(entry, writeEntryCount);
+ }
+
PlayStatsEntry* PlayStats_CreateEntry(uint64 titleId)
{
+ std::unique_lock _l(sPlaystatsLock);
bool entryCountChanged = false;
PlayStatsEntry* newEntry;
if(PlayStats.numEntries < NUM_PLAY_STATS_ENTRIES)
@@ -168,7 +200,7 @@ namespace iosu
newEntry->numTimesLaunched = 1;
newEntry->totalMinutesPlayed = 0;
newEntry->ukn12 = 0;
- PlayStats_WriteEntry(newEntry, entryCountChanged);
+ PlayStats_WriteEntryNoLock(newEntry, entryCountChanged);
return newEntry;
}
@@ -176,6 +208,7 @@ namespace iosu
// if it does not exist it creates a new entry with first and last played set to today
PlayStatsEntry* PlayStats_BeginNewTracking(uint64 titleId)
{
+ std::unique_lock _l(sPlaystatsLock);
PlayStatsEntry* entry = PlayStats_GetEntry(titleId);
if (entry)
{
@@ -189,11 +222,12 @@ namespace iosu
void PlayStats_CountAdditionalMinutes(PlayStatsEntry* entry, uint32 additionalMinutes)
{
+ std::unique_lock _l(sPlaystatsLock);
if (additionalMinutes == 0)
return;
entry->totalMinutesPlayed += additionalMinutes;
entry->mostRecentDayIndex = GetTodaysDayIndex();
- PlayStats_WriteEntry(entry);
+ PlayStats_WriteEntryNoLock(entry);
}
struct PlayDiaryHeader
@@ -218,6 +252,7 @@ namespace iosu
void CreatePlayDiary()
{
MakeDirectory();
+ cemu_assert_debug(!PlayDiaryData.fs);
PlayDiaryData.fs = FileStream::createFile2(GetPDFile("PlayDiary.dat"));
if (!PlayDiaryData.fs)
{
@@ -230,7 +265,7 @@ namespace iosu
PlayDiaryData.fs->writeData(&PlayDiaryData.header, sizeof(PlayDiaryHeader));
}
- void LoadPlayDiary()
+ void OpenPlayDiary()
{
std::unique_lock _lock(sDiaryLock);
cemu_assert_debug(!PlayDiaryData.fs);
@@ -268,6 +303,26 @@ namespace iosu
}
}
+ void ClosePlayDiary()
+ {
+ std::unique_lock _lock(sDiaryLock);
+ if (PlayDiaryData.fs)
+ {
+ delete PlayDiaryData.fs;
+ PlayDiaryData.fs = nullptr;
+ }
+ }
+
+ void UnloadDiaryData()
+ {
+ std::unique_lock _lock(sDiaryLock);
+ cemu_assert_debug(!PlayDiaryData.fs); // unloading expects that file is closed
+ PlayDiaryData.header.readIndex = 0;
+ PlayDiaryData.header.writeIndex = 0;
+ for (auto& it : PlayDiaryData.entry)
+ it = PlayDiaryEntry{};
+ }
+
uint32 GetDiaryEntries(uint8 accountSlot, PlayDiaryEntry* diaryEntries, uint32 maxEntries)
{
std::unique_lock _lock(sDiaryLock);
@@ -352,25 +407,59 @@ namespace iosu
}
}
- void Initialize()
+ class : public ::IOSUModule
{
- // todo - add support for per-account handling
- LoadPlaystats();
- LoadPlayDiary();
- }
-
- void StartTrackingTime(uint64 titleId)
- {
- sPDMRequestExitThread = false;
- sPDMTimeTrackingThread = std::thread(TimeTrackingThread, titleId);
- }
+ void PDMLoadAll()
+ {
+ OpenPlaystats();
+ OpenPlayDiary();
+ }
- void Stop()
+ void PDMUnloadAll()
+ {
+ UnloadPlaystats();
+ UnloadDiaryData();
+ }
+
+ void PDMCloseAll()
+ {
+ ClosePlaystats();
+ ClosePlayDiary();
+ }
+
+ void SystemLaunch() override
+ {
+ // todo - add support for per-account handling
+ PDMLoadAll();
+ PDMCloseAll(); // close the files again, user may mess with MLC files or change MLC path while no game is running
+ }
+ void SystemExit() override
+ {
+ PDMCloseAll();
+ PDMUnloadAll();
+ }
+ void TitleStart() override
+ {
+ // reload data and keep files open
+ PDMUnloadAll();
+ PDMLoadAll();
+ auto titleId = CafeSystem::GetForegroundTitleId();
+ sPDMRequestExitThread = false;
+ sPDMTimeTrackingThread = std::thread(TimeTrackingThread, titleId);
+ }
+ void TitleStop() override
+ {
+ sPDMRequestExitThread.store(true);
+ sPDMSem.increment();
+ if(sPDMTimeTrackingThread.joinable())
+ sPDMTimeTrackingThread.join();
+ PDMCloseAll();
+ }
+ }sIOSUModuleNNPDM;
+
+ IOSUModule* GetModule()
{
- sPDMRequestExitThread.store(true);
- sPDMSem.increment();
- if(sPDMTimeTrackingThread.joinable())
- sPDMTimeTrackingThread.join();
+ return static_cast(&sIOSUModuleNNPDM);
}
};
diff --git a/src/Cafe/IOSU/PDM/iosu_pdm.h b/src/Cafe/IOSU/PDM/iosu_pdm.h
index fbafbc02..0dd8a39d 100644
--- a/src/Cafe/IOSU/PDM/iosu_pdm.h
+++ b/src/Cafe/IOSU/PDM/iosu_pdm.h
@@ -1,13 +1,10 @@
#pragma once
+#include "Cafe/IOSU/iosu_types_common.h"
namespace iosu
{
namespace pdm
{
- void Initialize();
- void StartTrackingTime(uint64 titleId);
- void Stop();
-
inline constexpr size_t NUM_PLAY_STATS_ENTRIES = 256;
inline constexpr size_t NUM_PLAY_DIARY_ENTRIES_MAX = 18250; // 0x474A
@@ -34,5 +31,7 @@ namespace iosu
};
bool GetStatForGamelist(uint64 titleId, GameListStat& stat);
+
+ IOSUModule* GetModule();
};
};
\ No newline at end of file
From bffeb818d1e2770c3f47e7290deffdc5136c6b90 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Wed, 22 Nov 2023 17:57:20 +0100
Subject: [PATCH 008/319] GfxPack: Refactor + better unicode support
---
src/Cafe/GameProfile/GameProfile.cpp | 2 +-
src/Cafe/GraphicPack/GraphicPack2.cpp | 63 +++++++++----------
src/Cafe/GraphicPack/GraphicPack2.h | 18 +++---
src/Cafe/GraphicPack/GraphicPack2Patches.cpp | 15 +----
.../GraphicPack/GraphicPack2PatchesParser.cpp | 2 +-
src/gui/GraphicPacksWindow2.cpp | 45 ++++++-------
6 files changed, 64 insertions(+), 81 deletions(-)
diff --git a/src/Cafe/GameProfile/GameProfile.cpp b/src/Cafe/GameProfile/GameProfile.cpp
index d068237e..ee92107a 100644
--- a/src/Cafe/GameProfile/GameProfile.cpp
+++ b/src/Cafe/GameProfile/GameProfile.cpp
@@ -209,7 +209,7 @@ bool GameProfile::Load(uint64_t title_id)
m_gameName = std::string(game_name.begin(), game_name.end());
trim(m_gameName.value());
}
- IniParser iniParser(*profileContents, gameProfilePath.string());
+ IniParser iniParser(*profileContents, _pathToUtf8(gameProfilePath));
// parse ini
while (iniParser.NextSection())
{
diff --git a/src/Cafe/GraphicPack/GraphicPack2.cpp b/src/Cafe/GraphicPack/GraphicPack2.cpp
index 72e301c4..365e6e3e 100644
--- a/src/Cafe/GraphicPack/GraphicPack2.cpp
+++ b/src/Cafe/GraphicPack/GraphicPack2.cpp
@@ -28,7 +28,7 @@ void GraphicPack2::LoadGraphicPack(fs::path graphicPackPath)
return;
std::vector rulesData;
fs_rules->extract(rulesData);
- IniParser iniParser(rulesData, rulesPath.string());
+ IniParser iniParser(rulesData, _pathToUtf8(rulesPath));
if (!iniParser.NextSection())
{
@@ -51,10 +51,9 @@ void GraphicPack2::LoadGraphicPack(fs::path graphicPackPath)
cemuLog_log(LogType::Force, "{}: Unable to parse version", _pathToUtf8(rulesPath));
return;
}
-
if (versionNum > GP_LEGACY_VERSION)
{
- GraphicPack2::LoadGraphicPack(_pathToUtf8(rulesPath), iniParser);
+ GraphicPack2::LoadGraphicPack(rulesPath, iniParser);
return;
}
}
@@ -79,22 +78,22 @@ void GraphicPack2::LoadAll()
}
}
-bool GraphicPack2::LoadGraphicPack(const std::string& filename, IniParser& rules)
+bool GraphicPack2::LoadGraphicPack(const fs::path& rulesPath, IniParser& rules)
{
try
{
- auto gp = std::make_shared(filename, rules);
+ auto gp = std::make_shared(rulesPath, rules);
// check if enabled and preset set
const auto& config_entries = g_config.data().graphic_pack_entries;
// legacy absolute path checking for not breaking compatibility
- auto file = gp->GetFilename2();
+ auto file = gp->GetRulesPath();
auto it = config_entries.find(file.lexically_normal());
if (it == config_entries.cend())
{
// check for relative path
- it = config_entries.find(MakeRelativePath(ActiveSettings::GetUserDataPath(), gp->GetFilename2()).lexically_normal());
+ it = config_entries.find(_utf8ToPath(gp->GetNormalizedPathString()));
}
if (it != config_entries.cend())
@@ -145,7 +144,7 @@ bool GraphicPack2::DeactivateGraphicPack(const std::shared_ptr& gr
const auto it = std::find_if(s_active_graphic_packs.begin(), s_active_graphic_packs.end(),
[graphic_pack](const GraphicPackPtr& gp)
{
- return gp->GetFilename() == graphic_pack->GetFilename();
+ return gp->GetNormalizedPathString() == graphic_pack->GetNormalizedPathString();
}
);
@@ -173,12 +172,12 @@ void GraphicPack2::ActivateForCurrentTitle()
{
if (gp->GetPresets().empty())
{
- cemuLog_log(LogType::Force, "Activate graphic pack: {}", gp->GetPath());
+ cemuLog_log(LogType::Force, "Activate graphic pack: {}", gp->GetVirtualPath());
}
else
{
std::string logLine;
- logLine.assign(fmt::format("Activate graphic pack: {} [Presets: ", gp->GetPath()));
+ logLine.assign(fmt::format("Activate graphic pack: {} [Presets: ", gp->GetVirtualPath()));
bool isFirst = true;
for (auto& itr : gp->GetPresets())
{
@@ -249,8 +248,8 @@ std::unordered_map GraphicPack2::ParsePres
return vars;
}
-GraphicPack2::GraphicPack2(std::string filename, IniParser& rules)
- : m_filename(std::move(filename))
+GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
+ : m_rulesPath(std::move(rulesPath))
{
// we're already in [Definition]
auto option_version = rules.FindOption("version");
@@ -259,7 +258,7 @@ GraphicPack2::GraphicPack2(std::string filename, IniParser& rules)
m_version = StringHelpers::ToInt(*option_version, -1);
if (m_version < 0)
{
- cemuLog_log(LogType::Force, "{}: Invalid version", m_filename);
+ cemuLog_log(LogType::Force, "{}: Invalid version", _pathToUtf8(m_rulesPath));
throw std::exception();
}
@@ -305,7 +304,7 @@ GraphicPack2::GraphicPack2(std::string filename, IniParser& rules)
cemuLog_log(LogType::Force, "[Definition] section from '{}' graphic pack must contain option: path", gp_name_log.has_value() ? *gp_name_log : "Unknown");
throw std::exception();
}
- m_path = *option_path;
+ m_virtualPath = *option_path;
auto option_gp_name = rules.FindOption("name");
if (option_gp_name)
@@ -508,6 +507,11 @@ bool GraphicPack2::Reload()
return Activate();
}
+std::string GraphicPack2::GetNormalizedPathString() const
+{
+ return _pathToUtf8(MakeRelativePath(ActiveSettings::GetUserDataPath(), GetRulesPath()).lexically_normal());
+}
+
bool GraphicPack2::ContainsTitleId(uint64_t title_id) const
{
const auto it = std::find_if(m_title_ids.begin(), m_title_ids.end(), [title_id](uint64 id) { return id == title_id; });
@@ -650,7 +654,7 @@ bool GraphicPack2::SetActivePreset(std::string_view category, std::string_view n
void GraphicPack2::LoadShaders()
{
- fs::path path(m_filename);
+ fs::path path = GetRulesPath();
for (auto& it : fs::directory_iterator(path.remove_filename()))
{
if (!is_regular_file(it))
@@ -676,7 +680,7 @@ void GraphicPack2::LoadShaders()
{
std::ifstream file(p);
if (!file.is_open())
- throw std::runtime_error(fmt::format("can't open graphic pack file: {}", p.filename().string()).c_str());
+ throw std::runtime_error(fmt::format("can't open graphic pack file: {}", _pathToUtf8(p.filename())));
file.seekg(0, std::ios::end);
m_output_shader_source.reserve(file.tellg());
@@ -689,7 +693,7 @@ void GraphicPack2::LoadShaders()
{
std::ifstream file(p);
if (!file.is_open())
- throw std::runtime_error(fmt::format("can't open graphic pack file: {}", p.filename().string()).c_str());
+ throw std::runtime_error(fmt::format("can't open graphic pack file: {}", _pathToUtf8(p.filename())));
file.seekg(0, std::ios::end);
m_upscaling_shader_source.reserve(file.tellg());
@@ -702,7 +706,7 @@ void GraphicPack2::LoadShaders()
{
std::ifstream file(p);
if (!file.is_open())
- throw std::runtime_error(fmt::format("can't open graphic pack file: {}", p.filename().string()).c_str());
+ throw std::runtime_error(fmt::format("can't open graphic pack file: {}", _pathToUtf8(p.filename())));
file.seekg(0, std::ios::end);
m_downscaling_shader_source.reserve(file.tellg());
@@ -805,7 +809,7 @@ void GraphicPack2::AddConstantsForCurrentPreset(ExpressionParser& ep)
}
}
-void GraphicPack2::_iterateReplacedFiles(const fs::path& currentPath, std::wstring& internalPath, bool isAOC)
+void GraphicPack2::_iterateReplacedFiles(const fs::path& currentPath, bool isAOC)
{
uint64 currentTitleId = CafeSystem::GetForegroundTitleId();
uint64 aocTitleId = (currentTitleId & 0xFFFFFFFFull) | 0x0005000c00000000ull;
@@ -833,7 +837,7 @@ void GraphicPack2::LoadReplacedFiles()
return;
m_patchedFilesLoaded = true;
- fs::path gfxPackPath = _utf8ToPath(m_filename);
+ fs::path gfxPackPath = GetRulesPath();
gfxPackPath = gfxPackPath.remove_filename();
// /content/
@@ -843,10 +847,9 @@ void GraphicPack2::LoadReplacedFiles()
std::error_code ec;
if (fs::exists(contentPath, ec))
{
- std::wstring internalPath(L"/vol/content/");
// setup redirections
fscDeviceRedirect_map();
- _iterateReplacedFiles(contentPath, internalPath, false);
+ _iterateReplacedFiles(contentPath, false);
}
// /aoc/
fs::path aocPath(gfxPackPath);
@@ -857,13 +860,9 @@ void GraphicPack2::LoadReplacedFiles()
uint64 aocTitleId = CafeSystem::GetForegroundTitleId();
aocTitleId = aocTitleId & 0xFFFFFFFFULL;
aocTitleId |= 0x0005000c00000000ULL;
- wchar_t internalAocPath[128];
- swprintf(internalAocPath, sizeof(internalAocPath)/sizeof(wchar_t), L"/aoc/%016llx/", aocTitleId);
-
- std::wstring internalPath(internalAocPath);
// setup redirections
fscDeviceRedirect_map();
- _iterateReplacedFiles(aocPath, internalPath, true);
+ _iterateReplacedFiles(aocPath, true);
}
}
@@ -886,14 +885,14 @@ bool GraphicPack2::Activate()
return false;
}
- FileStream* fs_rules = FileStream::openFile2(_utf8ToPath(m_filename));
+ FileStream* fs_rules = FileStream::openFile2(m_rulesPath);
if (!fs_rules)
return false;
std::vector rulesData;
fs_rules->extract(rulesData);
delete fs_rules;
- IniParser rules({ (char*)rulesData.data(), rulesData.size()}, m_filename);
+ IniParser rules({ (char*)rulesData.data(), rulesData.size()}, GetNormalizedPathString());
// load rules
try
@@ -947,7 +946,7 @@ bool GraphicPack2::Activate()
else if (anisotropyValue == 16)
rule.overwrite_settings.anistropic_value = 4;
else
- cemuLog_log(LogType::Force, "Invalid value {} for overwriteAnisotropy in graphic pack {}. Only the values 1, 2, 4, 8 or 16 are allowed.", anisotropyValue, m_filename);
+ cemuLog_log(LogType::Force, "Invalid value {} for overwriteAnisotropy in graphic pack {}. Only the values 1, 2, 4, 8 or 16 are allowed.", anisotropyValue, GetNormalizedPathString());
}
m_texture_rules.emplace_back(rule);
}
@@ -992,11 +991,11 @@ bool GraphicPack2::Activate()
if (LatteTiming_getCustomVsyncFrequency(globalCustomVsyncFreq))
{
if (customVsyncFreq != globalCustomVsyncFreq)
- cemuLog_log(LogType::Force, "rules.txt error: Mismatching vsync frequency {} in graphic pack \'{}\'", customVsyncFreq, GetPath());
+ cemuLog_log(LogType::Force, "rules.txt error: Mismatching vsync frequency {} in graphic pack \'{}\'", customVsyncFreq, GetVirtualPath());
}
else
{
- cemuLog_log(LogType::Force, "Set vsync frequency to {} (graphic pack {})", customVsyncFreq, GetPath());
+ cemuLog_log(LogType::Force, "Set vsync frequency to {} (graphic pack {})", customVsyncFreq, GetVirtualPath());
LatteTiming_setCustomVsyncFrequency(customVsyncFreq);
}
}
diff --git a/src/Cafe/GraphicPack/GraphicPack2.h b/src/Cafe/GraphicPack/GraphicPack2.h
index 6396ecc7..6b07cce9 100644
--- a/src/Cafe/GraphicPack/GraphicPack2.h
+++ b/src/Cafe/GraphicPack/GraphicPack2.h
@@ -97,20 +97,20 @@ public:
};
using PresetPtr = std::shared_ptr;
- GraphicPack2(std::string filename, IniParser& rules);
+ GraphicPack2(fs::path rulesPath, IniParser& rules);
bool IsEnabled() const { return m_enabled; }
bool IsActivated() const { return m_activated; }
sint32 GetVersion() const { return m_version; }
- const std::string& GetFilename() const { return m_filename; }
- const fs::path GetFilename2() const { return fs::path(m_filename); }
+ const fs::path GetRulesPath() const { return m_rulesPath; }
+ std::string GetNormalizedPathString() const;
bool RequiresRestart(bool changeEnableState, bool changePreset);
bool Reload();
bool HasName() const { return !m_name.empty(); }
- const std::string& GetName() const { return m_name.empty() ? m_path : m_name; }
- const std::string& GetPath() const { return m_path; }
+ const std::string& GetName() const { return m_name.empty() ? m_virtualPath : m_name; }
+ const std::string& GetVirtualPath() const { return m_virtualPath; } // returns the path in the gfx tree hierarchy
const std::string& GetDescription() const { return m_description; }
bool IsDefaultEnabled() const { return m_default_enabled; }
@@ -164,7 +164,7 @@ public:
static const std::vector>& GetGraphicPacks() { return s_graphic_packs; }
static const std::vector>& GetActiveGraphicPacks() { return s_active_graphic_packs; }
static void LoadGraphicPack(fs::path graphicPackPath);
- static bool LoadGraphicPack(const std::string& filename, class IniParser& rules);
+ static bool LoadGraphicPack(const fs::path& rulesPath, class IniParser& rules);
static bool ActivateGraphicPack(const std::shared_ptr& graphic_pack);
static bool DeactivateGraphicPack(const std::shared_ptr& graphic_pack);
static void ClearGraphicPacks();
@@ -208,11 +208,11 @@ private:
parser.TryAddConstant(var.first, (TType)var.second.second);
}
- std::string m_filename;
+ fs::path m_rulesPath;
sint32 m_version;
std::string m_name;
- std::string m_path;
+ std::string m_virtualPath;
std::string m_description;
bool m_default_enabled = false;
@@ -257,7 +257,7 @@ private:
CustomShader LoadShader(const fs::path& path, uint64 shader_base_hash, uint64 shader_aux_hash, GP_SHADER_TYPE shader_type) const;
void ApplyShaderPresets(std::string& shader_source) const;
void LoadReplacedFiles();
- void _iterateReplacedFiles(const fs::path& currentPath, std::wstring& internalPath, bool isAOC);
+ void _iterateReplacedFiles(const fs::path& currentPath, bool isAOC);
// ram mappings
std::vector> m_ramMappings;
diff --git a/src/Cafe/GraphicPack/GraphicPack2Patches.cpp b/src/Cafe/GraphicPack/GraphicPack2Patches.cpp
index 5c79630c..2c067484 100644
--- a/src/Cafe/GraphicPack/GraphicPack2Patches.cpp
+++ b/src/Cafe/GraphicPack/GraphicPack2Patches.cpp
@@ -71,19 +71,8 @@ void PatchErrorHandler::showStageErrorMessageBox()
// returns true if at least one file was found even if it could not be successfully parsed
bool GraphicPack2::LoadCemuPatches()
{
- // todo - once we have updated to C++20 we can replace these with the new std::string functions
- auto startsWith = [](const std::wstring& str, const std::wstring& prefix)
- {
- return str.size() >= prefix.size() && 0 == str.compare(0, prefix.size(), prefix);
- };
-
- auto endsWith = [](const std::wstring& str, const std::wstring& suffix)
- {
- return str.size() >= suffix.size() && 0 == str.compare(str.size() - suffix.size(), suffix.size(), suffix);
- };
-
bool foundPatches = false;
- fs::path path(_utf8ToPath(m_filename));
+ fs::path path(m_rulesPath);
path.remove_filename();
for (auto& p : fs::directory_iterator(path))
{
@@ -129,7 +118,7 @@ void GraphicPack2::LoadPatchFiles()
if (LoadCemuPatches())
return; // exit if at least one Cemu style patch file was found
// fall back to Cemuhook patches.txt to guarantee backward compatibility
- fs::path path(_utf8ToPath(m_filename));
+ fs::path path(m_rulesPath);
path.remove_filename();
path.append("patches.txt");
FileStream* patchFile = FileStream::openFile2(path);
diff --git a/src/Cafe/GraphicPack/GraphicPack2PatchesParser.cpp b/src/Cafe/GraphicPack/GraphicPack2PatchesParser.cpp
index d011a10b..05f8c696 100644
--- a/src/Cafe/GraphicPack/GraphicPack2PatchesParser.cpp
+++ b/src/Cafe/GraphicPack/GraphicPack2PatchesParser.cpp
@@ -25,7 +25,7 @@ sint32 GraphicPack2::GetLengthWithoutComment(const char* str, size_t length)
void GraphicPack2::LogPatchesSyntaxError(sint32 lineNumber, std::string_view errorMsg)
{
- cemuLog_log(LogType::Force, "Syntax error while parsing patch for graphic pack '{}':", this->GetFilename());
+ cemuLog_log(LogType::Force, "Syntax error while parsing patch for graphic pack '{}':", _pathToUtf8(this->GetRulesPath()));
if(lineNumber >= 0)
cemuLog_log(LogType::Force, fmt::format("Line {0}: {1}", lineNumber, errorMsg));
else
diff --git a/src/gui/GraphicPacksWindow2.cpp b/src/gui/GraphicPacksWindow2.cpp
index 13fec49a..78b344d5 100644
--- a/src/gui/GraphicPacksWindow2.cpp
+++ b/src/gui/GraphicPacksWindow2.cpp
@@ -64,7 +64,7 @@ void GraphicPacksWindow2::FillGraphicPackList() const
{
bool found = false;
- if (boost::icontains(p->GetPath(), m_filter))
+ if (boost::icontains(p->GetVirtualPath(), m_filter))
found = true;
else
{
@@ -82,7 +82,7 @@ void GraphicPacksWindow2::FillGraphicPackList() const
continue;
}
- const auto& path = p->GetPath();
+ const auto& path = p->GetVirtualPath();
auto tokens = TokenizeView(path, '/');
auto node = root;
for(size_t i=0; iGetFilename())).lexically_normal();
+ auto filename = _utf8ToPath(gp->GetNormalizedPathString());
if (gp->IsEnabled())
{
data.graphic_pack_entries.try_emplace(filename);
@@ -603,34 +603,29 @@ void GraphicPacksWindow2::OnCheckForUpdates(wxCommandEvent& event)
{
if (!CafeSystem::IsTitleRunning())
{
- std::vector old_packs = GraphicPack2::GetGraphicPacks();
+ // remember virtual paths of all the enabled packs
+ std::map previouslyEnabledPacks;
+ for(auto& it : GraphicPack2::GetGraphicPacks())
+ {
+ if(it->IsEnabled())
+ previouslyEnabledPacks.emplace(it->GetNormalizedPathString(), it->GetVirtualPath());
+ }
+ // reload graphic packs
RefreshGraphicPacks();
FillGraphicPackList();
-
- // check if enabled graphic packs are lost:
- const auto& new_packs = GraphicPack2::GetGraphicPacks();
- std::stringstream lost_packs;
- for(const auto& p : old_packs)
+ // remove packs which are still present
+ for(auto& it : GraphicPack2::GetGraphicPacks())
+ previouslyEnabledPacks.erase(it->GetNormalizedPathString());
+ if(!previouslyEnabledPacks.empty())
{
- if (!p->IsEnabled())
- continue;
-
- const auto it = std::find_if(new_packs.cbegin(), new_packs.cend(), [&p](const auto& gp)
- {
- return gp->GetFilename() == p->GetFilename();
- });
-
- if(it == new_packs.cend())
+ std::string lost_packs;
+ for(auto& it : previouslyEnabledPacks)
{
- lost_packs << p->GetPath() << "\n";
+ lost_packs.append(it.second);
+ lost_packs.push_back('\n');
}
- }
-
- const auto lost_packs_str = lost_packs.str();
- if (!lost_packs_str.empty())
- {
wxString message = _("This update removed or renamed the following graphic packs:");
- message << "\n \n" << lost_packs_str << " \n" << _("You may need to set them up again.");
+ message << "\n \n" << wxString::FromUTF8(lost_packs) << " \n" << _("You may need to set them up again.");
wxMessageBox(message, _("Warning"), wxOK | wxCENTRE | wxICON_INFORMATION, this);
}
}
From e7fa8ec0c63f37a93fbcb0c7b372d5fb8640091e Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Wed, 6 Dec 2023 02:16:17 +0100
Subject: [PATCH 009/319] Vulkan: Properly shut down compilation threads
---
.../Renderer/Vulkan/RendererShaderVk.cpp | 23 ++++++++++++++++---
.../Latte/Renderer/Vulkan/RendererShaderVk.h | 3 +++
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 5 ++++
3 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
index e4c87d62..8460c8b5 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
@@ -139,7 +139,7 @@ public:
}
}
- ~_ShaderVkThreadPool()
+ void StopThreads()
{
m_shutdownThread.store(true);
for (uint32 i = 0; i < s_threads.size(); ++i)
@@ -149,6 +149,11 @@ public:
s_threads.clear();
}
+ ~_ShaderVkThreadPool()
+ {
+ StopThreads();
+ }
+
void CompilerThreadFunc()
{
while (!m_shutdownThread.load(std::memory_order::relaxed))
@@ -176,6 +181,8 @@ public:
}
}
+ bool HasThreadsRunning() const { return !m_shutdownThread; }
+
public:
std::vector s_threads;
@@ -195,8 +202,8 @@ RendererShaderVk::RendererShaderVk(ShaderType type, uint64 baseHash, uint64 auxH
m_compilationState.setValue(COMPILATION_STATE::QUEUED);
ShaderVkThreadPool.s_compilationQueue.push_back(this);
ShaderVkThreadPool.s_compilationQueueCount.increment();
- ShaderVkThreadPool.StartThreads();
ShaderVkThreadPool.s_compilationQueueMutex.unlock();
+ cemu_assert_debug(ShaderVkThreadPool.HasThreadsRunning()); // make sure .StartThreads() was called
}
RendererShaderVk::~RendererShaderVk()
@@ -204,6 +211,16 @@ RendererShaderVk::~RendererShaderVk()
VulkanRenderer::GetInstance()->destroyShader(this);
}
+void RendererShaderVk::Init()
+{
+ ShaderVkThreadPool.StartThreads();
+}
+
+void RendererShaderVk::Shutdown()
+{
+ ShaderVkThreadPool.StopThreads();
+}
+
sint32 RendererShaderVk::GetUniformLocation(const char* name)
{
cemu_assert_suspicious();
@@ -457,4 +474,4 @@ void RendererShaderVk::ShaderCacheLoading_Close()
{
delete s_spirvCache;
s_spirvCache = nullptr;
-}
\ No newline at end of file
+}
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h
index 561145f9..207ea3ea 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h
@@ -28,6 +28,9 @@ public:
RendererShaderVk(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& glslCode);
virtual ~RendererShaderVk();
+ static void Init();
+ static void Shutdown();
+
sint32 GetUniformLocation(const char* name) override;
void SetUniform1iv(sint32 location, void* data, sint32 count) override;
void SetUniform2fv(sint32 location, void* data, sint32 count) override;
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index 052ca21a..5b4dd739 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -591,6 +591,9 @@ VulkanRenderer::VulkanRenderer()
{
//cemuLog_log(LogType::Force, "Disable surface copies via buffer (Requires 2GB. Has only {}MB available)", availableSurfaceCopyBufferMem / 1024ull / 1024ull);
}
+
+ // start compilation threads
+ RendererShaderVk::Init();
}
VulkanRenderer::~VulkanRenderer()
@@ -598,6 +601,8 @@ VulkanRenderer::~VulkanRenderer()
SubmitCommandBuffer();
WaitDeviceIdle();
WaitCommandBufferFinished(GetCurrentCommandBufferId());
+ // shut down compilation threads
+ RendererShaderVk::Shutdown();
// shut down pipeline save thread
m_destructionRequested = true;
m_pipeline_cache_semaphore.notify();
From dee764473db26462a898aae8ea73c65a9cbafda1 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Wed, 6 Dec 2023 02:29:56 +0100
Subject: [PATCH 010/319] Latte: Small refactor for GLSL texture coord handling
Also adds support for 2D textures coordinates with source as 0.0 or 1.0 literals instead of GPRs. Seen in shaders generated by CafeGLSL
---
.../LatteDecompilerEmitGLSL.cpp | 108 ++++++++----------
1 file changed, 46 insertions(+), 62 deletions(-)
diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp
index 334b4855..a37ba011 100644
--- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp
+++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp
@@ -507,7 +507,7 @@ void _emitRegisterAccessCode(LatteDecompilerShaderContext* shaderContext, sint32
{
_emitTypeConversionPrefix(shaderContext, registerElementDataType, dataType);
}
- if(shaderContext->typeTracker.useArrayGPRs )
+ if (shaderContext->typeTracker.useArrayGPRs)
src->add("R");
else
src->addFmt("R{}", gprIndex);
@@ -540,6 +540,26 @@ void _emitRegisterAccessCode(LatteDecompilerShaderContext* shaderContext, sint32
_emitTypeConversionSuffix(shaderContext, registerElementDataType, dataType);
}
+// optimized variant of _emitRegisterAccessCode for raw one channel reads
+void _emitRegisterChannelAccessCode(LatteDecompilerShaderContext* shaderContext, sint32 gprIndex, sint32 channel, sint32 dataType)
+{
+ cemu_assert_debug(gprIndex >= 0 && gprIndex <= 127);
+ cemu_assert_debug(channel >= 0 && channel < 4);
+ StringBuf* src = shaderContext->shaderSource;
+ sint32 registerElementDataType = shaderContext->typeTracker.defaultDataType;
+ _emitTypeConversionPrefix(shaderContext, registerElementDataType, dataType);
+ if (shaderContext->typeTracker.useArrayGPRs)
+ src->add("R");
+ else
+ src->addFmt("R{}", gprIndex);
+ _appendRegisterTypeSuffix(src, registerElementDataType);
+ if (shaderContext->typeTracker.useArrayGPRs)
+ src->addFmt("[{}]", gprIndex);
+ src->add(".");
+ src->add(_getElementStrByIndex(channel));
+ _emitTypeConversionSuffix(shaderContext, registerElementDataType, dataType);
+}
+
void _emitALURegisterInputAccessCode(LatteDecompilerShaderContext* shaderContext, LatteDecompilerALUInstruction* aluInstruction, sint32 operandIndex)
{
StringBuf* src = shaderContext->shaderSource;
@@ -2129,63 +2149,31 @@ void _emitALUClauseCode(LatteDecompilerShaderContext* shaderContext, LatteDecomp
/*
* Emits code to access one component (xyzw) of the texture coordinate input vector
*/
-void _emitTEXSampleCoordInputComponent(LatteDecompilerShaderContext* shaderContext, LatteDecompilerTEXInstruction* texInstruction, sint32 componentIndex, sint32 varType)
+void _emitTEXSampleCoordInputComponent(LatteDecompilerShaderContext* shaderContext, LatteDecompilerTEXInstruction* texInstruction, sint32 componentIndex, sint32 interpretSrcAsType)
{
+ cemu_assert(componentIndex >= 0 && componentIndex < 4);
+ cemu_assert_debug(interpretSrcAsType == LATTE_DECOMPILER_DTYPE_SIGNED_INT || interpretSrcAsType == LATTE_DECOMPILER_DTYPE_FLOAT);
StringBuf* src = shaderContext->shaderSource;
- if( componentIndex >= 4 )
+ sint32 elementSel = texInstruction->textureFetch.srcSel[componentIndex];
+ if (elementSel < 4)
{
- debugBreakpoint();
+ _emitRegisterChannelAccessCode(shaderContext, texInstruction->srcGpr, elementSel, interpretSrcAsType);
return;
}
- sint32 elementSel = texInstruction->textureFetch.srcSel[componentIndex];
const char* resultElemTable[4] = {"x","y","z","w"};
- if( varType == LATTE_DECOMPILER_DTYPE_SIGNED_INT )
+ if(interpretSrcAsType == LATTE_DECOMPILER_DTYPE_SIGNED_INT )
{
- if (elementSel < 4)
- {
- if (shaderContext->typeTracker.defaultDataType == LATTE_DECOMPILER_DTYPE_SIGNED_INT)
- src->addFmt("{}.{}", _getRegisterVarName(shaderContext, texInstruction->srcGpr), resultElemTable[elementSel]);
- else if (shaderContext->typeTracker.defaultDataType == LATTE_DECOMPILER_DTYPE_FLOAT)
- src->addFmt("floatBitsToInt({}.{})", _getRegisterVarName(shaderContext, texInstruction->srcGpr), resultElemTable[elementSel]);
- else
- {
- cemu_assert_unimplemented();
- }
- }
- else if( elementSel == 4 )
+ if( elementSel == 4 )
src->add("floatBitsToInt(0.0)");
else if( elementSel == 5 )
src->add("floatBitsToInt(1.0)");
- else
- {
- cemu_assert_unimplemented();
- }
}
- else if( varType == LATTE_DECOMPILER_DTYPE_FLOAT )
+ else if(interpretSrcAsType == LATTE_DECOMPILER_DTYPE_FLOAT )
{
- if (elementSel < 4)
- {
- if (shaderContext->typeTracker.defaultDataType == LATTE_DECOMPILER_DTYPE_SIGNED_INT)
- src->addFmt("intBitsToFloat({}.{})", _getRegisterVarName(shaderContext, texInstruction->srcGpr), resultElemTable[elementSel]);
- else if (shaderContext->typeTracker.defaultDataType == LATTE_DECOMPILER_DTYPE_FLOAT)
- src->addFmt("{}.{}", _getRegisterVarName(shaderContext, texInstruction->srcGpr), resultElemTable[elementSel]);
- else
- {
- cemu_assert_unimplemented();
- }
- }
- else if( elementSel == 4 )
- src->addFmt("0.0");
+ if( elementSel == 4 )
+ src->add("0.0");
else if( elementSel == 5 )
- src->addFmt("1.0");
- else
- {
- cemu_assert_unimplemented();
- }
- }
- else
- {
- cemu_assert_unimplemented();
+ src->add("1.0");
}
}
@@ -2430,10 +2418,6 @@ void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContext, Latt
cemu_assert_unimplemented();
src->add("texture(");
}
- if( texInstruction->textureFetch.srcSel[0] >= 4 )
- cemu_assert_unimplemented();
- if( texInstruction->textureFetch.srcSel[1] >= 4 )
- cemu_assert_unimplemented();
src->addFmt("{}{}, ", _getTextureUnitVariablePrefixName(shaderContext->shader->shaderType), texInstruction->textureFetch.textureIndex);
// for textureGather() add shift (todo: depends on rounding mode set in sampler registers?)
@@ -2455,7 +2439,7 @@ void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContext, Latt
}
}
-
+ const sint32 texCoordDataType = (texOpcode == GPU7_TEX_INST_LD) ? LATTE_DECOMPILER_DTYPE_SIGNED_INT : LATTE_DECOMPILER_DTYPE_FLOAT;
if(useTexelCoordinates)
{
// handle integer coordinates for texelFetch
@@ -2463,9 +2447,9 @@ void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContext, Latt
{
src->add("ivec2(");
src->add("vec2(");
- _emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 0, (texOpcode == GPU7_TEX_INST_LD) ? LATTE_DECOMPILER_DTYPE_SIGNED_INT : LATTE_DECOMPILER_DTYPE_FLOAT);
+ _emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 0, texCoordDataType);
src->addFmt(", ");
- _emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 1, (texOpcode == GPU7_TEX_INST_LD) ? LATTE_DECOMPILER_DTYPE_SIGNED_INT : LATTE_DECOMPILER_DTYPE_FLOAT);
+ _emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 1, texCoordDataType);
src->addFmt(")*uf_tex{}Scale", texInstruction->textureFetch.textureIndex); // close vec2 and scale
@@ -2485,7 +2469,7 @@ void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContext, Latt
else
cemu_assert_debug(false);
}
- else
+ else /* useTexelCoordinates == false */
{
// float coordinates
if ( (texOpcode == GPU7_TEX_INST_SAMPLE_C || texOpcode == GPU7_TEX_INST_SAMPLE_C_L || texOpcode == GPU7_TEX_INST_SAMPLE_C_LZ) )
@@ -2549,10 +2533,8 @@ void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContext, Latt
else if( texDim == Latte::E_DIM::DIM_CUBEMAP )
{
// 2 coords + faceId
- if( texInstruction->textureFetch.srcSel[0] >= 4 || texInstruction->textureFetch.srcSel[1] >= 4 )
- {
- debugBreakpoint();
- }
+ cemu_assert_debug(texInstruction->textureFetch.srcSel[0] < 4);
+ cemu_assert_debug(texInstruction->textureFetch.srcSel[1] < 4);
src->add("vec4(");
src->addFmt("redcCUBEReverse({},", _getTexGPRAccess(shaderContext, texInstruction->srcGpr, LATTE_DECOMPILER_DTYPE_FLOAT, texInstruction->textureFetch.srcSel[0], texInstruction->textureFetch.srcSel[1], -1, -1, tempBuffer0));
_emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 2, LATTE_DECOMPILER_DTYPE_SIGNED_INT);
@@ -2567,8 +2549,11 @@ void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContext, Latt
else
{
// 2 coords
- src->add(_getTexGPRAccess(shaderContext, texInstruction->srcGpr, LATTE_DECOMPILER_DTYPE_FLOAT, texInstruction->textureFetch.srcSel[0], texInstruction->textureFetch.srcSel[1], -1, -1, tempBuffer0));
-
+ src->add("vec2(");
+ _emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 0, LATTE_DECOMPILER_DTYPE_FLOAT);
+ src->add(",");
+ _emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 1, LATTE_DECOMPILER_DTYPE_FLOAT);
+ src->add(")");
// avoid truncate to effectively round downwards on texel edges
if (ActiveSettings::ForceSamplerRoundToPrecision())
src->addFmt("+ vec2(1.0)/vec2(textureSize({}{}, 0))/512.0", _getTextureUnitVariablePrefixName(shaderContext->shader->shaderType), texInstruction->textureFetch.textureIndex);
@@ -2576,9 +2561,8 @@ void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContext, Latt
// lod or lod bias parameter
if( texOpcode == GPU7_TEX_INST_SAMPLE_L || texOpcode == GPU7_TEX_INST_SAMPLE_LB || texOpcode == GPU7_TEX_INST_SAMPLE_C_L)
{
- if( texInstruction->textureFetch.srcSel[3] >= 4 )
- debugBreakpoint();
- src->addFmt(",{}", _getTexGPRAccess(shaderContext, texInstruction->srcGpr, LATTE_DECOMPILER_DTYPE_FLOAT, texInstruction->textureFetch.srcSel[3], -1, -1, -1, tempBuffer0));
+ src->add(",");
+ _emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 3, LATTE_DECOMPILER_DTYPE_FLOAT);
}
else if( texOpcode == GPU7_TEX_INST_SAMPLE_LZ || texOpcode == GPU7_TEX_INST_SAMPLE_C_LZ )
{
From 646835346c1eb6d29f632843b5e07e90a804d62c Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Thu, 7 Dec 2023 13:50:16 +0100
Subject: [PATCH 011/319] Latte: Refactor legacy OpenGL code for shader binding
---
src/Cafe/HW/Latte/Core/LatteShader.cpp | 16 +------------
.../Latte/Renderer/OpenGL/OpenGLRenderer.cpp | 24 +++----------------
.../HW/Latte/Renderer/OpenGL/OpenGLRenderer.h | 14 ++++-------
.../Renderer/OpenGL/OpenGLRendererCore.cpp | 15 ++++++++++++
.../Renderer/OpenGL/RendererShaderGL.cpp | 5 ----
.../Latte/Renderer/OpenGL/RendererShaderGL.h | 1 -
src/Cafe/HW/Latte/Renderer/Renderer.h | 2 --
.../HW/Latte/Renderer/RendererOuputShader.cpp | 6 -----
.../HW/Latte/Renderer/RendererOuputShader.h | 1 -
src/Cafe/HW/Latte/Renderer/RendererShader.h | 3 +--
.../Renderer/Vulkan/RendererShaderVk.cpp | 5 ----
.../Latte/Renderer/Vulkan/RendererShaderVk.h | 1 -
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 11 ---------
.../HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 2 --
14 files changed, 25 insertions(+), 81 deletions(-)
diff --git a/src/Cafe/HW/Latte/Core/LatteShader.cpp b/src/Cafe/HW/Latte/Core/LatteShader.cpp
index c0ad06a1..503fb664 100644
--- a/src/Cafe/HW/Latte/Core/LatteShader.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteShader.cpp
@@ -838,7 +838,6 @@ LatteDecompilerShader* LatteShader_CompileSeparablePixelShader(uint64 baseHash,
void LatteSHRC_UpdateVertexShader(uint8* vertexShaderPtr, uint32 vertexShaderSize, bool usesGeometryShader)
{
// todo - should include VTX_SEMANTIC table in state
-
LatteSHRC_UpdateVSBaseHash(vertexShaderPtr, vertexShaderSize, usesGeometryShader);
uint64 vsAuxHash = 0;
auto itBaseShader = sVertexShaders.find(_shaderBaseHash_vs);
@@ -855,15 +854,13 @@ void LatteSHRC_UpdateVertexShader(uint8* vertexShaderPtr, uint32 vertexShaderSiz
LatteGPUState.activeShaderHasError = true;
return;
}
- g_renderer->shader_bind(vertexShader->shader);
_activeVertexShader = vertexShader;
}
void LatteSHRC_UpdateGeometryShader(bool usesGeometryShader, uint8* geometryShaderPtr, uint32 geometryShaderSize, uint8* geometryCopyShader, uint32 geometryCopyShaderSize)
{
- if (usesGeometryShader == false || _activeVertexShader == nullptr)
+ if (!usesGeometryShader || !_activeVertexShader)
{
- g_renderer->shader_unbind(RendererShader::ShaderType::kGeometry);
_shaderBaseHash_gs = 0;
_activeGeometryShader = nullptr;
return;
@@ -887,21 +884,11 @@ void LatteSHRC_UpdateGeometryShader(bool usesGeometryShader, uint8* geometryShad
LatteGPUState.activeShaderHasError = true;
return;
}
- g_renderer->shader_bind(geometryShader->shader);
_activeGeometryShader = geometryShader;
}
void LatteSHRC_UpdatePixelShader(uint8* pixelShaderPtr, uint32 pixelShaderSize, bool usesGeometryShader)
{
- if (LatteGPUState.contextRegister[mmVGT_STRMOUT_EN] != 0 && g_renderer->GetType() == RendererAPI::OpenGL)
- {
- if (_activePixelShader)
- {
- g_renderer->shader_unbind(RendererShader::ShaderType::kFragment);
- _activePixelShader = nullptr;
- }
- return;
- }
LatteSHRC_UpdatePSBaseHash(pixelShaderPtr, pixelShaderSize, usesGeometryShader);
uint64 psAuxHash = 0;
auto itBaseShader = sPixelShaders.find(_shaderBaseHash_ps);
@@ -918,7 +905,6 @@ void LatteSHRC_UpdatePixelShader(uint8* pixelShaderPtr, uint32 pixelShaderSize,
LatteGPUState.activeShaderHasError = true;
return;
}
- g_renderer->shader_bind(pixelShader->shader);
_activePixelShader = pixelShader;
}
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
index 5269be64..01068a3d 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
@@ -275,10 +275,6 @@ void OpenGLRenderer::Initialize()
cemuLog_log(LogType::Force, "ARB_copy_image: {}", (glCopyImageSubData != NULL) ? "available" : "not supported");
cemuLog_log(LogType::Force, "NV_depth_buffer_float: {}", (glDepthRangedNV != NULL) ? "available" : "not supported");
- // generate default frame buffer
- glGenFramebuffers(1, &m_defaultFramebufferId);
- catchOpenGLError();
-
// enable framebuffer SRGB support
glEnable(GL_FRAMEBUFFER_SRGB);
@@ -566,10 +562,9 @@ void OpenGLRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
sint32 effectiveHeight;
LatteTexture_getEffectiveSize(texView->baseTexture, &effectiveWidth, &effectiveHeight, nullptr, 0);
- g_renderer->shader_unbind(RendererShader::ShaderType::kVertex);
- g_renderer->shader_unbind(RendererShader::ShaderType::kGeometry);
- g_renderer->shader_unbind(RendererShader::ShaderType::kFragment);
- shader->Bind();
+ shader_unbind(RendererShader::ShaderType::kGeometry);
+ shader_bind(shader->GetVertexShader());
+ shader_bind(shader->GetFragmentShader());
shader->SetUniformParameters(*texView, { effectiveWidth, effectiveHeight }, { imageWidth, imageHeight });
// set viewport
@@ -1433,31 +1428,25 @@ RendererShader* OpenGLRenderer::shader_create(RendererShader::ShaderType type, u
void OpenGLRenderer::shader_bind(RendererShader* shader)
{
auto shaderGL = (RendererShaderGL*)shader;
-
GLbitfield shaderBit;
-
const auto program = shaderGL->GetProgram();
-
switch(shader->GetType())
{
case RendererShader::ShaderType::kVertex:
if (program == prevVertexShaderProgram)
return;
-
shaderBit = GL_VERTEX_SHADER_BIT;
prevVertexShaderProgram = program;
break;
case RendererShader::ShaderType::kFragment:
if (program == prevPixelShaderProgram)
return;
-
shaderBit = GL_FRAGMENT_SHADER_BIT;
prevPixelShaderProgram = program;
break;
case RendererShader::ShaderType::kGeometry:
if (program == prevGeometryShaderProgram)
return;
-
shaderBit = GL_GEOMETRY_SHADER_BIT;
prevGeometryShaderProgram = program;
break;
@@ -1470,13 +1459,6 @@ void OpenGLRenderer::shader_bind(RendererShader* shader)
catchOpenGLError();
}
-void OpenGLRenderer::shader_bind(GLuint program, GLbitfield shaderType)
-{
- catchOpenGLError();
- glUseProgramStages(m_pipeline, shaderType, program);
- catchOpenGLError();
-}
-
void OpenGLRenderer::shader_unbind(RendererShader::ShaderType shaderType)
{
switch (shaderType) {
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
index 600985ff..b789e2a7 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
@@ -127,9 +127,8 @@ public:
// shader
RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool isGameShader, bool isGfxPackShader) override;
- void shader_bind(RendererShader* shader) override;
- void shader_bind(GLuint program, GLbitfield shaderType);
- void shader_unbind(RendererShader::ShaderType shaderType) override;
+ void shader_bind(RendererShader* shader);
+ void shader_unbind(RendererShader::ShaderType shaderType);
// streamout
void streamout_setupXfbBuffer(uint32 bufferIndex, sint32 ringBufferOffset, uint32 rangeAddr, uint32 rangeSize) override;
@@ -165,7 +164,6 @@ private:
void texture_syncSliceSpecialBC4(LatteTexture* srcTexture, sint32 srcSliceIndex, sint32 srcMipIndex, LatteTexture* dstTexture, sint32 dstSliceIndex, sint32 dstMipIndex);
void texture_syncSliceSpecialIntegerToBC3(LatteTexture* srcTexture, sint32 srcSliceIndex, sint32 srcMipIndex, LatteTexture* dstTexture, sint32 dstSliceIndex, sint32 dstMipIndex);
- GLuint m_defaultFramebufferId;
GLuint m_pipeline = 0;
bool m_isPadViewContext{};
@@ -216,8 +214,6 @@ private:
uint32 prevLogicOp = 0;
uint32 prevBlendColorConstant[4] = { 0 };
uint8 prevAlphaTestEnable = 0;
- uint8 prevAlphaTestFunc = 0;
- uint32 prevAlphaTestRefU32 = 0;
bool prevDepthEnable = 0;
bool prevDepthWriteEnable = 0;
Latte::LATTE_DB_DEPTH_CONTROL::E_ZFUNC prevDepthFunc = (Latte::LATTE_DB_DEPTH_CONTROL::E_ZFUNC)-1;
@@ -263,9 +259,9 @@ private:
std::vector list_queryCacheOcclusion; // cache for unused queries
// resource garbage collection
- struct bufferCacheReleaseQueueEntry_t
+ struct BufferCacheReleaseQueueEntry
{
- bufferCacheReleaseQueueEntry_t(VirtualBufferHeap_t* heap, VirtualBufferHeapEntry_t* entry) : m_heap(heap), m_entry(entry) {};
+ BufferCacheReleaseQueueEntry(VirtualBufferHeap_t* heap, VirtualBufferHeapEntry_t* entry) : m_heap(heap), m_entry(entry) {};
void free()
{
@@ -279,7 +275,7 @@ private:
struct
{
sint32 index;
- std::vector bufferCacheEntries;
+ std::vector bufferCacheEntries;
}m_destructionQueues;
};
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp
index d5cec237..f78b8bd6 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp
@@ -912,6 +912,21 @@ void OpenGLRenderer::draw_genericDrawHandler(uint32 baseVertex, uint32 baseInsta
{
beginPerfMonProfiling(performanceMonitor.gpuTime_dcStageShaderAndUniformMgr);
LatteSHRC_UpdateActiveShaders();
+ LatteDecompilerShader* vs = (LatteDecompilerShader*)LatteSHRC_GetActiveVertexShader();
+ LatteDecompilerShader* gs = (LatteDecompilerShader*)LatteSHRC_GetActiveGeometryShader();
+ LatteDecompilerShader* ps = (LatteDecompilerShader*)LatteSHRC_GetActivePixelShader();
+ if (vs)
+ shader_bind(vs->shader);
+ else
+ shader_unbind(RendererShader::ShaderType::kVertex);
+ if (ps && LatteGPUState.contextRegister[mmVGT_STRMOUT_EN] == 0)
+ shader_bind(ps->shader);
+ else
+ shader_unbind(RendererShader::ShaderType::kFragment);
+ if (gs)
+ shader_bind(gs->shader);
+ else
+ shader_unbind(RendererShader::ShaderType::kGeometry);
endPerfMonProfiling(performanceMonitor.gpuTime_dcStageShaderAndUniformMgr);
}
if (LatteGPUState.activeShaderHasError)
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp
index 5530b4ec..3d46f206 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp
@@ -230,11 +230,6 @@ sint32 RendererShaderGL::GetUniformLocation(const char* name)
return glGetUniformLocation(m_program, name);
}
-void RendererShaderGL::SetUniform1iv(sint32 location, void* data, sint32 count)
-{
- glProgramUniform1iv(m_program, location, count, (const GLint*)data);
-}
-
void RendererShaderGL::SetUniform2fv(sint32 location, void* data, sint32 count)
{
glProgramUniform2fv(m_program, location, count, (const GLfloat*)data);
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h
index abc62358..60c51cc1 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h
@@ -18,7 +18,6 @@ public:
GLuint GetShaderObject() const { cemu_assert_debug(m_isCompiled); return m_shader_object; }
sint32 GetUniformLocation(const char* name) override;
- void SetUniform1iv(sint32 location, void* data, sint32 count) override;
void SetUniform2fv(sint32 location, void* data, sint32 count) override;
void SetUniform4iv(sint32 location, void* data, sint32 count) override;
diff --git a/src/Cafe/HW/Latte/Renderer/Renderer.h b/src/Cafe/HW/Latte/Renderer/Renderer.h
index 61ff10c8..11d102d0 100644
--- a/src/Cafe/HW/Latte/Renderer/Renderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Renderer.h
@@ -135,8 +135,6 @@ public:
// shader
virtual RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool compileAsync, bool isGfxPackSource) = 0;
- virtual void shader_bind(RendererShader* shader) = 0;
- virtual void shader_unbind(RendererShader::ShaderType shaderType) = 0;
// streamout
virtual void streamout_setupXfbBuffer(uint32 bufferIndex, sint32 ringBufferOffset, uint32 rangeAddr, uint32 rangeSize) = 0;
diff --git a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp
index ae528944..cdbeb3f3 100644
--- a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp
+++ b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.cpp
@@ -233,12 +233,6 @@ void RendererOutputShader::SetUniformParameters(const LatteTextureView& texture_
}
}
-void RendererOutputShader::Bind() const
-{
- g_renderer->shader_bind(m_vertex_shader);
- g_renderer->shader_bind(m_fragment_shader);
-}
-
RendererOutputShader* RendererOutputShader::s_copy_shader;
RendererOutputShader* RendererOutputShader::s_copy_shader_ud;
diff --git a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.h b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.h
index 253990e2..398ac663 100644
--- a/src/Cafe/HW/Latte/Renderer/RendererOuputShader.h
+++ b/src/Cafe/HW/Latte/Renderer/RendererOuputShader.h
@@ -18,7 +18,6 @@ public:
virtual ~RendererOutputShader() = default;
void SetUniformParameters(const LatteTextureView& texture_view, const Vector2i& input_res, const Vector2i& output_res) const;
- void Bind() const;
RendererShader* GetVertexShader() const
{
diff --git a/src/Cafe/HW/Latte/Renderer/RendererShader.h b/src/Cafe/HW/Latte/Renderer/RendererShader.h
index 1c15211f..e3f254c6 100644
--- a/src/Cafe/HW/Latte/Renderer/RendererShader.h
+++ b/src/Cafe/HW/Latte/Renderer/RendererShader.h
@@ -19,8 +19,7 @@ public:
virtual bool WaitForCompiled() = 0;
virtual sint32 GetUniformLocation(const char* name) = 0;
-
- virtual void SetUniform1iv(sint32 location, void* data, sint32 count) = 0;
+
virtual void SetUniform2fv(sint32 location, void* data, sint32 count) = 0;
virtual void SetUniform4iv(sint32 location, void* data, sint32 count) = 0;
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
index 8460c8b5..970f5517 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
@@ -227,11 +227,6 @@ sint32 RendererShaderVk::GetUniformLocation(const char* name)
return 0;
}
-void RendererShaderVk::SetUniform1iv(sint32 location, void* data, sint32 count)
-{
- cemu_assert_suspicious();
-}
-
void RendererShaderVk::SetUniform2fv(sint32 location, void* data, sint32 count)
{
cemu_assert_suspicious();
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h
index 207ea3ea..f9c3ede1 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h
@@ -32,7 +32,6 @@ public:
static void Shutdown();
sint32 GetUniformLocation(const char* name) override;
- void SetUniform1iv(sint32 location, void* data, sint32 count) override;
void SetUniform2fv(sint32 location, void* data, sint32 count) override;
void SetUniform4iv(sint32 location, void* data, sint32 count) override;
VkShaderModule& GetShaderModule() { return m_shader_module; }
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index 5b4dd739..2ce5dacd 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -1090,17 +1090,6 @@ RendererShader* VulkanRenderer::shader_create(RendererShader::ShaderType type, u
return new RendererShaderVk(type, baseHash, auxHash, isGameShader, isGfxPackShader, source);
}
-void VulkanRenderer::shader_bind(RendererShader* shader)
-{
- // does nothing on Vulkan
- // remove from main render backend and internalize into GL backend
-}
-
-void VulkanRenderer::shader_unbind(RendererShader::ShaderType shaderType)
-{
- // does nothing on Vulkan
-}
-
bool VulkanRenderer::CheckDeviceExtensionSupport(const VkPhysicalDevice device, FeatureControl& info)
{
std::vector availableDeviceExtensions;
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
index 3d68f844..84cae587 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
@@ -350,8 +350,6 @@ public:
void buffer_bindUniformBuffer(LatteConst::ShaderType shaderType, uint32 bufferIndex, uint32 offset, uint32 size) override;
RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool isGameShader, bool isGfxPackShader) override;
- void shader_bind(RendererShader* shader) override;
- void shader_unbind(RendererShader::ShaderType shaderType) override;
void* indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex) override;
void indexData_uploadIndexMemory(uint32 offset, uint32 size) override;
From df282ab230d07629e28dca16b5decea198879baa Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Fri, 8 Dec 2023 15:19:12 +0100
Subject: [PATCH 012/319] Latte: Clean up OpenGL relics in shared render code
---
src/Cafe/HW/Latte/Core/Latte.h | 2 +-
src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp | 4 -
src/Cafe/HW/Latte/Core/LatteTexture.cpp | 14 +-
src/Cafe/HW/Latte/Core/LatteTexture.h | 6 +-
src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp | 23 ++-
src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp | 2 +-
src/Cafe/HW/Latte/Core/LatteThread.cpp | 8 +-
.../Latte/Renderer/OpenGL/LatteTextureGL.cpp | 28 +--
.../HW/Latte/Renderer/OpenGL/LatteTextureGL.h | 6 +-
.../Renderer/OpenGL/LatteTextureViewGL.cpp | 2 +-
.../Latte/Renderer/OpenGL/OpenGLRenderer.cpp | 147 ++++-----------
.../HW/Latte/Renderer/OpenGL/OpenGLRenderer.h | 18 +-
.../Renderer/OpenGL/OpenGLRendererCore.cpp | 4 +-
.../Renderer/OpenGL/OpenGLSurfaceCopy.cpp | 2 +-
.../Renderer/OpenGL/TextureReadbackGL.cpp | 4 +-
src/Cafe/HW/Latte/Renderer/Renderer.h | 8 +-
.../Latte/Renderer/Vulkan/LatteTextureVk.cpp | 4 +-
.../HW/Latte/Renderer/Vulkan/LatteTextureVk.h | 2 +-
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 11 +-
.../HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 9 +-
src/Common/GLInclude/GLInclude.h | 171 ++++++++++++++++++
src/Common/GLInclude/glFunctions.h | 8 +
22 files changed, 267 insertions(+), 216 deletions(-)
diff --git a/src/Cafe/HW/Latte/Core/Latte.h b/src/Cafe/HW/Latte/Core/Latte.h
index 861d7ddf..dc3cbc91 100644
--- a/src/Cafe/HW/Latte/Core/Latte.h
+++ b/src/Cafe/HW/Latte/Core/Latte.h
@@ -115,7 +115,7 @@ void LatteTC_RegisterTexture(LatteTexture* tex);
void LatteTC_UnregisterTexture(LatteTexture* tex);
uint32 LatteTexture_CalculateTextureDataHash(LatteTexture* hostTexture);
-void LatteTexture_ReloadData(LatteTexture* hostTexture, uint32 textureUnit);
+void LatteTexture_ReloadData(LatteTexture* hostTexture);
bool LatteTC_HasTextureChanged(LatteTexture* hostTexture, bool force = false);
void LatteTC_ResetTextureChangeTracker(LatteTexture* hostTexture, bool force = false);
diff --git a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
index 06015949..abdfda21 100644
--- a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
@@ -239,8 +239,6 @@ LatteTextureView* LatteMRT_CreateColorBuffer(MPTR colorBufferPhysMem, uint32 wid
textureView = LatteTexture_CreateMapping(colorBufferPhysMem, MPTR_NULL, width, height, viewSlice+1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D_ARRAY, Latte::E_DIM::DIM_2D, false);
else
textureView = LatteTexture_CreateMapping(colorBufferPhysMem, MPTR_NULL, width, height, 1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, false);
- // unbind texture
- g_renderer->texture_bindAndActivate(nullptr, 0);
return textureView;
}
@@ -253,8 +251,6 @@ LatteTextureView* LatteMRT_CreateDepthBuffer(MPTR depthBufferPhysMem, uint32 wid
textureView = LatteTexture_CreateMapping(depthBufferPhysMem, MPTR_NULL, width, height, viewSlice+1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D_ARRAY, Latte::E_DIM::DIM_2D, true);
LatteMRT::SetDepthAndStencilAttachment(textureView, textureView->baseTexture->hasStencil);
- // unbind texture
- g_renderer->texture_bindAndActivate(nullptr, 0);
return textureView;
}
diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.cpp b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
index 42a9d8c6..06afed60 100644
--- a/src/Cafe/HW/Latte/Core/LatteTexture.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
@@ -985,7 +985,7 @@ void LatteTexture_RecreateTextureWithDifferentMipSliceCount(LatteTexture* textur
newDim = Latte::E_DIM::DIM_2D_ARRAY;
else if (newDim == Latte::E_DIM::DIM_1D && newDepth > 1)
newDim = Latte::E_DIM::DIM_1D_ARRAY;
- LatteTextureView* view = LatteTexture_CreateTexture(0, newDim, texture->physAddress, physMipAddr, texture->format, texture->width, texture->height, newDepth, texture->pitch, newMipCount, texture->swizzle, texture->tileMode, texture->isDepth);
+ LatteTextureView* view = LatteTexture_CreateTexture(newDim, texture->physAddress, physMipAddr, texture->format, texture->width, texture->height, newDepth, texture->pitch, newMipCount, texture->swizzle, texture->tileMode, texture->isDepth);
cemu_assert(!(view->baseTexture->mipLevels <= 1 && physMipAddr == MPTR_NULL && newMipCount > 1));
// copy data from old texture if its dynamically updated
if (texture->isUpdatedOnGPU)
@@ -1112,7 +1112,7 @@ LatteTextureView* LatteTexture_CreateMapping(MPTR physAddr, MPTR physMipAddr, si
// create new texture
if (allowCreateNewDataTexture == false)
return nullptr;
- LatteTextureView* view = LatteTexture_CreateTexture(0, dimBase, physAddr, physMipAddr, format, width, height, depth, pitch, firstMip + numMip, swizzle, tileMode, isDepth);
+ LatteTextureView* view = LatteTexture_CreateTexture(dimBase, physAddr, physMipAddr, format, width, height, depth, pitch, firstMip + numMip, swizzle, tileMode, isDepth);
LatteTexture* newTexture = view->baseTexture;
LatteTexture_GatherTextureRelations(view->baseTexture);
LatteTexture_UpdateTextureFromDynamicChanges(view->baseTexture);
@@ -1191,12 +1191,8 @@ LatteTextureView* LatteTC_GetTextureSliceViewOrTryCreate(MPTR srcImagePtr, MPTR
void LatteTexture_UpdateDataToLatest(LatteTexture* texture)
{
if (LatteTC_HasTextureChanged(texture))
- {
- g_renderer->texture_rememberBoundTexture(0);
- g_renderer->texture_bindAndActivateRawTex(texture, 0);
- LatteTexture_ReloadData(texture, 0);
- g_renderer->texture_restoreBoundTexture(0);
- }
+ LatteTexture_ReloadData(texture);
+
if (texture->reloadFromDynamicTextures)
{
LatteTexture_UpdateCacheFromDynamicTextures(texture);
@@ -1245,7 +1241,7 @@ std::vector& LatteTexture::GetAllTextures()
return sAllTextures;
}
-LatteTexture::LatteTexture(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
+LatteTexture::LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
Latte::E_HWTILEMODE tileMode, bool isDepth)
{
_AddTextureToGlobalList(this);
diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.h b/src/Cafe/HW/Latte/Core/LatteTexture.h
index 6cdc528e..d5e872e6 100644
--- a/src/Cafe/HW/Latte/Core/LatteTexture.h
+++ b/src/Cafe/HW/Latte/Core/LatteTexture.h
@@ -24,11 +24,9 @@ struct LatteSamplerState
class LatteTexture
{
public:
- LatteTexture(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
+ LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
virtual ~LatteTexture();
- virtual void InitTextureState() {};
-
LatteTextureView* GetOrCreateView(Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount)
{
for (auto& itr : views)
@@ -307,7 +305,7 @@ std::vector LatteTexture_QueryCacheInfo();
float* LatteTexture_getEffectiveTextureScale(LatteConst::ShaderType shaderType, sint32 texUnit);
-LatteTextureView* LatteTexture_CreateTexture(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
+LatteTextureView* LatteTexture_CreateTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
void LatteTexture_Delete(LatteTexture* texture);
void LatteTextureLoader_writeReadbackTextureToMemory(LatteTextureDefinition* textureData, uint32 sliceIndex, uint32 mipIndex, uint8* linearPixelData);
diff --git a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
index 9cce2526..0260002b 100644
--- a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
@@ -32,9 +32,9 @@ void LatteTexture_setEffectiveTextureScale(LatteConst::ShaderType shaderType, si
t[1] = v;
}
-void LatteTextureLoader_UpdateTextureSliceData(LatteTexture* tex, sint32 textureUnit, uint32 sliceIndex, uint32 mipIndex, MPTR physImagePtr, MPTR physMipPtr, Latte::E_DIM dim, uint32 width, uint32 height, uint32 depth, uint32 mipLevels, uint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, bool dumpTex);
+void LatteTextureLoader_UpdateTextureSliceData(LatteTexture* tex, uint32 sliceIndex, uint32 mipIndex, MPTR physImagePtr, MPTR physMipPtr, Latte::E_DIM dim, uint32 width, uint32 height, uint32 depth, uint32 mipLevels, uint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, bool dumpTex);
-void LatteTexture_ReloadData(LatteTexture* tex, uint32 textureUnit)
+void LatteTexture_ReloadData(LatteTexture* tex)
{
tex->reloadCount++;
for(sint32 mip=0; mipmipLevels; mip++)
@@ -44,35 +44,35 @@ void LatteTexture_ReloadData(LatteTexture* tex, uint32 textureUnit)
{
sint32 numSlices = std::max(tex->depth, 1);
for(sint32 s=0; sphysAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
+ LatteTextureLoader_UpdateTextureSliceData(tex, s, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
}
else if( tex->dim == Latte::E_DIM::DIM_CUBEMAP )
{
cemu_assert_debug((tex->depth % 6) == 0);
sint32 numFullCubeMaps = tex->depth/6; // number of cubemaps (if numFullCubeMaps is >1 then this texture is a cubemap array)
for(sint32 s=0; sphysAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
+ LatteTextureLoader_UpdateTextureSliceData(tex, s, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
}
else if( tex->dim == Latte::E_DIM::DIM_3D )
{
sint32 mipDepth = std::max(tex->depth>>mip, 1);
for(sint32 s=0; sphysAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
+ LatteTextureLoader_UpdateTextureSliceData(tex, s, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
}
}
else
{
// load slice 0
- LatteTextureLoader_UpdateTextureSliceData(tex, textureUnit, 0, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
+ LatteTextureLoader_UpdateTextureSliceData(tex, 0, mip, tex->physAddress, tex->physMipAddress, tex->dim, tex->width, tex->height, tex->depth, tex->mipLevels, tex->pitch, tex->tileMode, tex->swizzle, true);
}
}
tex->lastUpdateEventCounter = LatteTexture_getNextUpdateEventCounter();
}
-LatteTextureView* LatteTexture_CreateTexture(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth)
+LatteTextureView* LatteTexture_CreateTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth)
{
- const auto tex = g_renderer->texture_createTextureEx(textureUnit, dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
+ const auto tex = g_renderer->texture_createTextureEx(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
// init slice/mip info array
LatteTexture_InitSliceAndMipInfo(tex);
LatteTexture_RegisterTextureMemoryOccupancy(tex);
@@ -110,7 +110,7 @@ LatteTextureView* LatteTexture_CreateTexture(uint32 textureUnit, Latte::E_DIM di
}
}
}
- LatteTexture_ReloadData(tex, textureUnit);
+ LatteTexture_ReloadData(tex);
LatteTC_MarkTextureStillInUse(tex);
LatteTC_RegisterTexture(tex);
// create initial view that maps to the whole texture
@@ -247,7 +247,7 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u
textureView->lastTextureBindIndex = LatteGPUState.textureBindCounter;
rendererGL->renderstate_updateTextureSettingsGL(shaderContext, textureView, textureIndex + glBackendBaseTexUnit, word4, textureIndex, isDepthSampler);
}
- g_renderer->texture_bindOnly(textureView, textureIndex + glBackendBaseTexUnit);
+ g_renderer->texture_setLatteTexture(textureView, textureIndex + glBackendBaseTexUnit);
// update if data changed
bool swizzleChanged = false;
if (textureView->baseTexture->swizzle != swizzle)
@@ -285,9 +285,8 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u
textureView->baseTexture->physMipAddress = physMipAddr;
}
}
- g_renderer->texture_bindAndActivateRawTex(textureView->baseTexture, textureIndex + glBackendBaseTexUnit);
debug_printf("Reload reason: Data-change when bound as texture (new hash 0x%08x)\n", textureView->baseTexture->texDataHash2);
- LatteTexture_ReloadData(textureView->baseTexture, textureIndex + glBackendBaseTexUnit);
+ LatteTexture_ReloadData(textureView->baseTexture);
}
LatteTexture* baseTexture = textureView->baseTexture;
if (baseTexture->reloadFromDynamicTextures)
diff --git a/src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp b/src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp
index 331c1500..862fff06 100644
--- a/src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp
@@ -599,7 +599,7 @@ void LatteTextureLoader_loadTextureDataIntoSlice(LatteTexture* hostTexture, sint
}
}
-void LatteTextureLoader_UpdateTextureSliceData(LatteTexture* tex, sint32 textureUnit, uint32 sliceIndex, uint32 mipIndex, MPTR physImagePtr, MPTR physMipPtr, Latte::E_DIM dim, uint32 width, uint32 height, uint32 depth, uint32 mipLevels, uint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, bool dumpTex)
+void LatteTextureLoader_UpdateTextureSliceData(LatteTexture* tex, uint32 sliceIndex, uint32 mipIndex, MPTR physImagePtr, MPTR physMipPtr, Latte::E_DIM dim, uint32 width, uint32 height, uint32 depth, uint32 mipLevels, uint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, bool dumpTex)
{
LatteTextureLoaderCtx textureLoader = { 0 };
diff --git a/src/Cafe/HW/Latte/Core/LatteThread.cpp b/src/Cafe/HW/Latte/Core/LatteThread.cpp
index 897f769c..60b32ec4 100644
--- a/src/Cafe/HW/Latte/Core/LatteThread.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteThread.cpp
@@ -44,7 +44,7 @@ LatteTextureView* LatteHandleOSScreen_getOrCreateScreenTex(MPTR physAddress, uin
LatteTextureView* texView = LatteTextureViewLookupCache::lookup(physAddress, width, height, 1, pitch, 0, 1, 0, 1, Latte::E_GX2SURFFMT::R8_G8_B8_A8_UNORM, Latte::E_DIM::DIM_2D);
if (texView)
return texView;
- return LatteTexture_CreateTexture(0, Latte::E_DIM::DIM_2D, physAddress, 0, Latte::E_GX2SURFFMT::R8_G8_B8_A8_UNORM, width, height, 1, pitch, 1, 0, Latte::E_HWTILEMODE::TM_LINEAR_ALIGNED, false);
+ return LatteTexture_CreateTexture(Latte::E_DIM::DIM_2D, physAddress, 0, Latte::E_GX2SURFFMT::R8_G8_B8_A8_UNORM, width, height, 1, pitch, 1, 0, Latte::E_HWTILEMODE::TM_LINEAR_ALIGNED, false);
}
void LatteHandleOSScreen_prepareTextures()
@@ -71,8 +71,7 @@ bool LatteHandleOSScreen_TV()
const uint32 bufferIndexTV = (bufferDisplayTV);
const uint32 bufferIndexDRC = bufferDisplayDRC;
- g_renderer->texture_bindAndActivate(osScreenTVTex[bufferIndexTV], 0);
- LatteTexture_ReloadData(osScreenTVTex[bufferIndexTV]->baseTexture, 0);
+ LatteTexture_ReloadData(osScreenTVTex[bufferIndexTV]->baseTexture);
// TV screen
LatteRenderTarget_copyToBackbuffer(osScreenTVTex[bufferIndexTV]->baseTexture->baseView, false);
@@ -94,8 +93,7 @@ bool LatteHandleOSScreen_DRC()
const uint32 bufferIndexDRC = bufferDisplayDRC;
- g_renderer->texture_bindAndActivate(osScreenDRCTex[bufferIndexDRC], 0);
- LatteTexture_ReloadData(osScreenDRCTex[bufferIndexDRC]->baseTexture, 0);
+ LatteTexture_ReloadData(osScreenDRCTex[bufferIndexDRC]->baseTexture);
// GamePad screen
LatteRenderTarget_copyToBackbuffer(osScreenDRCTex[bufferIndexDRC]->baseTexture->baseView, true);
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp
index c9541470..584af40c 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp
@@ -19,20 +19,17 @@ static GLuint _genTextureHandleGL()
return texIdPool[texIdPoolIndex - 1];
}
-LatteTextureGL::LatteTextureGL(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
+LatteTextureGL::LatteTextureGL(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
Latte::E_HWTILEMODE tileMode, bool isDepth)
- : LatteTexture(textureUnit, dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth)
+ : LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth)
{
- GenerateEmptyTextureFromGX2Dim(dim, this->glId_texture, this->glTexTarget);
+ GenerateEmptyTextureFromGX2Dim(dim, this->glId_texture, this->glTexTarget, true);
// set format info
FormatInfoGL glFormatInfo;
GetOpenGLFormatInfo(isDepth, format, dim, &glFormatInfo);
this->glInternalFormat = glFormatInfo.glInternalFormat;
this->isAlternativeFormat = glFormatInfo.isUsingAlternativeFormat;
this->hasStencil = glFormatInfo.hasStencil; // todo - should get this from the GX2 format?
- // bind texture
- g_renderer->texture_bindAndActivateRawTex(this, textureUnit);
- LatteTextureGL::InitTextureState();
// set debug name
bool useGLDebugNames = false;
#ifdef CEMU_DEBUG_ASSERT
@@ -54,9 +51,8 @@ LatteTextureGL::~LatteTextureGL()
catchOpenGLError();
}
-void LatteTextureGL::GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& texId, GLint& texTarget)
+void LatteTextureGL::GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& texId, GLint& texTarget, bool createForTargetType)
{
- texId = _genTextureHandleGL();
if (dim == Latte::E_DIM::DIM_2D)
texTarget = GL_TEXTURE_2D;
else if (dim == Latte::E_DIM::DIM_1D)
@@ -73,6 +69,10 @@ void LatteTextureGL::GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& te
{
cemu_assert_unimplemented();
}
+ if(createForTargetType)
+ texId = glCreateTextureWrapper(texTarget); // initializes the texture to texTarget (equivalent to calling glGenTextures + glBindTexture)
+ else
+ glGenTextures(1, &texId);
}
LatteTextureView* LatteTextureGL::CreateView(Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount)
@@ -80,18 +80,6 @@ LatteTextureView* LatteTextureGL::CreateView(Latte::E_DIM dim, Latte::E_GX2SURFF
return new LatteTextureViewGL(this, dim, format, firstMip, mipCount, firstSlice, sliceCount);
}
-void LatteTextureGL::InitTextureState()
-{
- // init texture with some default parameters (todo - this shouldn't be necessary if we properly set parameters when a texture is used)
- catchOpenGLError();
- glTexParameteri(glTexTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(glTexTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(glTexTarget, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(glTexTarget, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(glTexTarget, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- catchOpenGLError();
-}
-
void LatteTextureGL::GetOpenGLFormatInfo(bool isDepth, Latte::E_GX2SURFFMT format, Latte::E_DIM dim, FormatInfoGL* formatInfoOut)
{
formatInfoOut->isUsingAlternativeFormat = false;
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.h b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.h
index fabd1bac..9169bb29 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.h
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.h
@@ -6,14 +6,12 @@
class LatteTextureGL : public LatteTexture
{
public:
- LatteTextureGL(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
+ LatteTextureGL(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
~LatteTextureGL();
- static void GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& texId, GLint& texTarget);
-
- void InitTextureState() override;
+ static void GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& texId, GLint& texTarget, bool createForTargetType);
protected:
LatteTextureView* CreateView(Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount) override;
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.cpp
index f33fd7ff..29085642 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.cpp
@@ -11,7 +11,7 @@ LatteTextureViewGL::LatteTextureViewGL(LatteTextureGL* texture, Latte::E_DIM dim
firstSlice != 0 || firstMip != 0 || mipCount != texture->mipLevels || sliceCount != texture->depth ||
forceCreateNewTexId)
{
- LatteTextureGL::GenerateEmptyTextureFromGX2Dim(dim, glTexId, glTexTarget);
+ LatteTextureGL::GenerateEmptyTextureFromGX2Dim(dim, glTexId, glTexTarget, false);
this->glInternalFormat = 0;
InitAliasView();
}
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
index 01068a3d..f09f04f1 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
@@ -77,8 +77,6 @@ static const GLenum glAlphaTestFunc[] =
GL_ALWAYS
};
-
-
OpenGLRenderer::OpenGLRenderer()
{
glRendererState.useTextureUploadBuffer = false;
@@ -571,7 +569,7 @@ void OpenGLRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
glViewportIndexedf(0, imageX, imageY, imageWidth, imageHeight);
LatteTextureViewGL* texViewGL = (LatteTextureViewGL*)texView;
- g_renderer->texture_bindAndActivate(texView, 0);
+ texture_bindAndActivate(texView, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, useLinearTexFilter ? GL_LINEAR : GL_NEAREST);
texViewGL->samplerState.filterMag = 0xFFFFFFFF;
@@ -586,7 +584,7 @@ void OpenGLRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
glEnable(GL_FRAMEBUFFER_SRGB);
// unbind texture
- g_renderer->texture_bindAndActivate(nullptr, 0);
+ texture_bindAndActivate(nullptr, 0);
catchOpenGLError();
@@ -990,8 +988,9 @@ void OpenGLRenderer::texture_destroy(LatteTexture* hostTexture)
delete hostTexture;
}
-void OpenGLRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTexture)
+void OpenGLRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTextureGeneric)
{
+ auto hostTexture = (LatteTextureGL*)hostTextureGeneric;
cemu_assert_debug(hostTexture->isDataDefined == false);
sint32 effectiveBaseWidth = hostTexture->width;
sint32 effectiveBaseHeight = hostTexture->height;
@@ -1012,25 +1011,25 @@ void OpenGLRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTexture)
if (hostTexture->dim == Latte::E_DIM::DIM_2D || hostTexture->dim == Latte::E_DIM::DIM_2D_MSAA)
{
cemu_assert_debug(effectiveBaseDepth == 1);
- glTexStorage2D(GL_TEXTURE_2D, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight);
+ glTextureStorage2DWrapper(GL_TEXTURE_2D, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight);
}
else if (hostTexture->dim == Latte::E_DIM::DIM_1D)
{
cemu_assert_debug(effectiveBaseHeight == 1);
cemu_assert_debug(effectiveBaseDepth == 1);
- glTexStorage1D(GL_TEXTURE_1D, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth);
+ glTextureStorage1DWrapper(GL_TEXTURE_1D, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth);
}
else if (hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY || hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY_MSAA)
{
- glTexStorage3D(GL_TEXTURE_2D_ARRAY, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
+ glTextureStorage3DWrapper(GL_TEXTURE_2D_ARRAY, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
}
else if (hostTexture->dim == Latte::E_DIM::DIM_3D)
{
- glTexStorage3D(GL_TEXTURE_3D, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
+ glTextureStorage3DWrapper(GL_TEXTURE_3D, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
}
else if (hostTexture->dim == Latte::E_DIM::DIM_CUBEMAP)
{
- glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, effectiveBaseDepth);
+ glTextureStorage3DWrapper(GL_TEXTURE_CUBE_MAP_ARRAY, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, effectiveBaseDepth);
}
else
{
@@ -1042,7 +1041,6 @@ void OpenGLRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTexture)
void OpenGLRenderer_texture_loadSlice_normal(LatteTexture* hostTextureGeneric, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 imageSize)
{
auto hostTexture = (LatteTextureGL*)hostTextureGeneric;
-
sint32 effectiveWidth = width;
sint32 effectiveHeight = height;
sint32 effectiveDepth = depth;
@@ -1053,58 +1051,37 @@ void OpenGLRenderer_texture_loadSlice_normal(LatteTexture* hostTextureGeneric, s
LatteTextureGL::GetOpenGLFormatInfo(hostTexture->isDepth, hostTexture->overwriteInfo.hasFormatOverwrite ? (Latte::E_GX2SURFFMT)hostTexture->overwriteInfo.format : hostTexture->format, hostTexture->dim, &glFormatInfo);
// upload slice
catchOpenGLError();
+ if (mipIndex >= hostTexture->maxPossibleMipLevels)
+ {
+ cemuLog_logDebug(LogType::Force, "2D texture mip level allocated out of range");
+ return;
+ }
if (hostTexture->dim == Latte::E_DIM::DIM_2D || hostTexture->dim == Latte::E_DIM::DIM_2D_MSAA)
{
if (glFormatInfo.glIsCompressed)
- {
- if (glCompressedTextureSubImage2D)
- glCompressedTextureSubImage2D(hostTexture->glId_texture, mipIndex, 0, 0, effectiveWidth, effectiveHeight, glFormatInfo.glInternalFormat, imageSize, pixelData);
- else
- glCompressedTexSubImage2D(GL_TEXTURE_2D, mipIndex, 0, 0, effectiveWidth, effectiveHeight, glFormatInfo.glInternalFormat, imageSize, pixelData);
- }
+ glCompressedTextureSubImage2DWrapper(hostTexture->glTexTarget, hostTexture->glId_texture, mipIndex, 0, 0, effectiveWidth, effectiveHeight, glFormatInfo.glInternalFormat, imageSize, pixelData);
else
- {
- if (mipIndex < hostTexture->maxPossibleMipLevels)
- glTexSubImage2D(GL_TEXTURE_2D, mipIndex, 0, 0, effectiveWidth, effectiveHeight, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
- else
- cemuLog_logDebug(LogType::Force, "2D texture mip level allocated out of range");
- }
+ glTextureSubImage2DWrapper(hostTexture->glTexTarget, hostTexture->glId_texture, mipIndex, 0, 0, effectiveWidth, effectiveHeight, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
}
else if (hostTexture->dim == Latte::E_DIM::DIM_1D)
{
- if (glFormatInfo.glIsCompressed == true)
- cemu_assert_unimplemented();
- glTexSubImage1D(GL_TEXTURE_1D, mipIndex, 0, width, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
+ if (glFormatInfo.glIsCompressed)
+ glCompressedTextureSubImage1DWrapper(hostTexture->glTexTarget, hostTexture->glId_texture, mipIndex, 0, width, glFormatInfo.glInternalFormat, imageSize, pixelData);
+ else
+ glTextureSubImage1DWrapper(hostTexture->glTexTarget, hostTexture->glId_texture, mipIndex, 0, width, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
}
- else if (hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY || hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY_MSAA)
+ else if (hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY || hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY_MSAA ||
+ hostTexture->dim == Latte::E_DIM::DIM_3D ||
+ hostTexture->dim == Latte::E_DIM::DIM_CUBEMAP)
{
if (glFormatInfo.glIsCompressed)
- glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, glFormatInfo.glInternalFormat, imageSize, pixelData);
+ glCompressedTextureSubImage3DWrapper(hostTexture->glTexTarget, hostTexture->glId_texture, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, glFormatInfo.glInternalFormat, imageSize, pixelData);
else
- glTexSubImage3D(GL_TEXTURE_2D_ARRAY, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
- }
- else if (hostTexture->dim == Latte::E_DIM::DIM_3D)
- {
- if (glFormatInfo.glIsCompressed)
- glCompressedTexSubImage3D(GL_TEXTURE_3D, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, glFormatInfo.glInternalFormat, imageSize, pixelData);
- else
- glTexSubImage3D(GL_TEXTURE_3D, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
- }
- else if (hostTexture->dim == Latte::E_DIM::DIM_CUBEMAP)
- {
- if (glFormatInfo.glIsCompressed)
- glCompressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mipIndex, 0, 0, sliceIndex, width, height, 1, glFormatInfo.glInternalFormat, imageSize, pixelData);
- else
- glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mipIndex, 0, 0, sliceIndex, width, height, 1, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
- }
- else
- {
- cemu_assert_debug(false);
+ glTextureSubImage3DWrapper(hostTexture->glTexTarget, hostTexture->glId_texture, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, glFormatInfo.glSuppliedFormat, glFormatInfo.glSuppliedFormatType, pixelData);
}
catchOpenGLError();
}
-
// use persistent buffers to upload data
void OpenGLRenderer_texture_loadSlice_viaBuffers(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 imageSize)
{
@@ -1220,10 +1197,10 @@ void OpenGLRenderer::texture_clearSlice(LatteTexture* hostTextureGeneric, sint32
glClearTexSubImage(hostTexture->glId_texture, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, formatInfoGL.glSuppliedFormat, formatInfoGL.glSuppliedFormatType, NULL);
}
-LatteTexture* OpenGLRenderer::texture_createTextureEx(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
+LatteTexture* OpenGLRenderer::texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth)
{
- return new LatteTextureGL(textureUnit, dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
+ return new LatteTextureGL(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
}
@@ -1239,42 +1216,18 @@ void OpenGLRenderer::texture_setActiveTextureUnit(sint32 index)
void OpenGLRenderer::texture_bindAndActivate(LatteTextureView* textureView, uint32 textureUnit)
{
const auto textureViewGL = (LatteTextureViewGL*)textureView;
- cemu_assert_debug(textureUnit < (sizeof(LatteBoundTexturesBackup) / sizeof(LatteBoundTexturesBackup[0])));
// don't call glBindTexture if the texture is already bound
- if (LatteBoundTextures[textureUnit] == textureViewGL)
+ if (m_latteBoundTextures[textureUnit] == textureViewGL)
{
texture_setActiveTextureUnit(textureUnit);
return; // already bound
}
// bind
- LatteBoundTextures[textureUnit] = textureViewGL;
+ m_latteBoundTextures[textureUnit] = textureViewGL;
texture_setActiveTextureUnit(textureUnit);
if (textureViewGL)
{
glBindTexture(textureViewGL->glTexTarget, textureViewGL->glTexId);
- texUnitTexId[textureUnit] = textureViewGL->glTexId;
- texUnitTexTarget[textureUnit] = textureViewGL->glTexTarget;
- }
-}
-
-void OpenGLRenderer::texture_bindAndActivateRawTex(LatteTexture* texture, uint32 textureUnit)
-{
- cemu_assert_debug(textureUnit < (sizeof(LatteBoundTexturesBackup) / sizeof(LatteBoundTexturesBackup[0])));
- // don't call glBindTexture if the texture is already bound
- if (LatteBoundTextures[textureUnit] == texture)
- {
- texture_setActiveTextureUnit(textureUnit);
- return; // already bound
- }
- // bind
- LatteBoundTextures[textureUnit] = texture;
- texture_setActiveTextureUnit(textureUnit);
- if (texture)
- {
- auto textureGL = (LatteTextureGL*)texture;
- glBindTexture(textureGL->glTexTarget, textureGL->glId_texture);
- texUnitTexId[textureUnit] = textureGL->glId_texture;
- texUnitTexTarget[textureUnit] = textureGL->glTexTarget;
}
}
@@ -1282,18 +1235,18 @@ void OpenGLRenderer::texture_notifyDelete(LatteTextureView* textureView)
{
for (uint32 i = 0; i < Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3; i++)
{
- if (LatteBoundTextures[i] == textureView)
- LatteBoundTextures[i] = nullptr;
+ if (m_latteBoundTextures[i] == textureView)
+ m_latteBoundTextures[i] = nullptr;
}
}
-// similar to _bindAndActivate() but doesn't call _setActiveTextureUnit() if texture is already bound
-void OpenGLRenderer::texture_bindOnly(LatteTextureView* textureView1, uint32 textureUnit)
+// set Latte texture, on the OpenGL renderer this behaves like _bindAndActivate() but doesn't call _setActiveTextureUnit() if the texture is already bound
+void OpenGLRenderer::texture_setLatteTexture(LatteTextureView* textureView1, uint32 textureUnit)
{
auto textureView = ((LatteTextureViewGL*)textureView1);
cemu_assert_debug(textureUnit < Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3);
- if (LatteBoundTextures[textureUnit] == textureView)
+ if (m_latteBoundTextures[textureUnit] == textureView)
return;
if (textureView == nullptr)
return;
@@ -1301,45 +1254,17 @@ void OpenGLRenderer::texture_bindOnly(LatteTextureView* textureView1, uint32 tex
if (glBindTextureUnit)
{
glBindTextureUnit(textureUnit, textureView->glTexId);
- LatteBoundTextures[textureUnit] = textureView;
- texUnitTexId[textureUnit] = textureView->glTexId;
- texUnitTexTarget[textureUnit] = textureView->glTexTarget;
+ m_latteBoundTextures[textureUnit] = textureView;
activeTextureUnit = -1;
}
else
{
texture_setActiveTextureUnit(textureUnit);
glBindTexture(textureView->glTexTarget, textureView->glTexId);
- LatteBoundTextures[textureUnit] = textureView;
- texUnitTexId[textureUnit] = textureView->glTexId;
- texUnitTexTarget[textureUnit] = textureView->glTexTarget;
+ m_latteBoundTextures[textureUnit] = textureView;
}
}
-void OpenGLRenderer::texture_rememberBoundTexture(uint32 textureUnit)
-{
- cemu_assert_debug(texUnitBackupSlotUsed[textureUnit] == false);
- texUnitBackupSlotUsed[textureUnit] = true;
- LatteBoundTexturesBackup[textureUnit] = LatteBoundTextures[textureUnit];
- texUnitTexIdBackup[textureUnit] = texUnitTexId[textureUnit];
- texUnitTexTargetBackup[textureUnit] = texUnitTexTarget[textureUnit];
-}
-
-void OpenGLRenderer::texture_restoreBoundTexture(uint32 textureUnit)
-{
- cemu_assert_debug(texUnitBackupSlotUsed[textureUnit] == true);
- texUnitBackupSlotUsed[textureUnit] = false;
- if (LatteBoundTextures[textureUnit] == LatteBoundTexturesBackup[textureUnit])
- {
- return; // already bound
- }
- LatteBoundTextures[textureUnit] = LatteBoundTexturesBackup[textureUnit];
- texUnitTexId[textureUnit] = texUnitTexIdBackup[textureUnit];
- texUnitTexTarget[textureUnit] = texUnitTexTargetBackup[textureUnit];
- texture_setActiveTextureUnit(textureUnit);
- glBindTexture(texUnitTexTargetBackup[textureUnit], texUnitTexIdBackup[textureUnit]);
-}
-
void OpenGLRenderer::texture_copyImageSubData(LatteTexture* src, sint32 srcMip, sint32 effectiveSrcX, sint32 effectiveSrcY, sint32 srcSlice, LatteTexture* dst, sint32 dstMip, sint32 effectiveDstX, sint32 effectiveDstY,
sint32 dstSlice, sint32 effectiveCopyWidth, sint32 effectiveCopyHeight, sint32 srcDepth)
{
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
index b789e2a7..8a4b1a1d 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
@@ -79,13 +79,10 @@ public:
void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) override;
void texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sliceIndex, sint32 mipIndex, bool clearDepth, bool clearStencil, float depthValue, uint32 stencilValue) override;
- LatteTexture* texture_createTextureEx(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) override;
+ LatteTexture* texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) override;
- void texture_bindAndActivate(LatteTextureView* textureView, uint32 textureUnit) override;
- void texture_bindAndActivateRawTex(LatteTexture* texture, uint32 textureUnit) override;
- void texture_bindOnly(LatteTextureView* textureView, uint32 textureUnit) override;
- void texture_rememberBoundTexture(uint32 textureUnit) override;
- void texture_restoreBoundTexture(uint32 textureUnit) override;
+ void texture_setLatteTexture(LatteTextureView* textureView, uint32 textureUnit) override;
+ void texture_bindAndActivate(LatteTextureView* textureView, uint32 textureUnit);
void texture_copyImageSubData(LatteTexture* src, sint32 srcMip, sint32 effectiveSrcX, sint32 effectiveSrcY, sint32 srcSlice, LatteTexture* dst, sint32 dstMip, sint32 effectiveDstX, sint32 effectiveDstY, sint32 dstSlice, sint32 effectiveCopyWidth, sint32 effectiveCopyHeight, sint32 srcDepth) override;
void texture_notifyDelete(LatteTextureView* textureView);
@@ -188,14 +185,7 @@ private:
bool m_isXfbActive = false;
sint32 activeTextureUnit = 0;
- void* LatteBoundTextures[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
- GLuint texUnitTexId[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
- GLenum texUnitTexTarget[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
-
- void* LatteBoundTexturesBackup[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
- GLuint texUnitTexIdBackup[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
- GLenum texUnitTexTargetBackup[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
- bool texUnitBackupSlotUsed[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
+ void* m_latteBoundTextures[Latte::GPU_LIMITS::NUM_TEXTURES_PER_STAGE * 3]{};
// attribute stream
GLuint glAttributeCacheAB{};
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp
index f78b8bd6..51d0d206 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp
@@ -1342,7 +1342,7 @@ uint32 _correctTextureCompSelGL(Latte::E_GX2SURFFMT format, uint32 compSel)
return compSel;
}
-#define quickBindTexture() if( textureIsActive == false ) { g_renderer->texture_bindAndActivate(hostTextureView, hostTextureUnit); textureIsActive = true; }
+#define quickBindTexture() if( textureIsActive == false ) { texture_bindAndActivate(hostTextureView, hostTextureUnit); textureIsActive = true; }
uint32 _getGLMinFilter(Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_XY_FILTER filterMin, Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_Z_FILTER filterMip)
{
@@ -1365,11 +1365,9 @@ uint32 _getGLMinFilter(Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_XY_FILTER filterMi
/*
* Update channel swizzling and other texture settings for a texture unit
* hostTextureView is the texture unit view used on the host side
-* The baseGX2TexUnit parameter is used to identify the shader stage in which this texture is accessed
*/
void OpenGLRenderer::renderstate_updateTextureSettingsGL(LatteDecompilerShader* shaderContext, LatteTextureView* _hostTextureView, uint32 hostTextureUnit, const Latte::LATTE_SQ_TEX_RESOURCE_WORD4_N texUnitWord4, uint32 texUnitIndex, bool isDepthSampler)
{
- // todo - this is OpenGL-specific, decouple this from the renderer-neutral backend
auto hostTextureView = (LatteTextureViewGL*)_hostTextureView;
LatteTexture* baseTexture = hostTextureView->baseTexture;
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp
index 8c8c36d7..c49a57e4 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp
@@ -52,7 +52,7 @@ void OpenGLRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* s
LatteTextureView* sourceView = sourceTexture->GetOrCreateView(srcMip, 1, srcSlice, 1);
LatteTextureView* destinationView = destinationTexture->GetOrCreateView(dstMip, 1, dstSlice, 1);
- g_renderer->texture_bindAndActivate(sourceView, 0);
+ texture_bindAndActivate(sourceView, 0);
catchOpenGLError();
// setup texture attributes
_setDepthCompareMode((LatteTextureViewGL*)sourceView, 0);
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/TextureReadbackGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/TextureReadbackGL.cpp
index 56011dab..b2966706 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/TextureReadbackGL.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/TextureReadbackGL.cpp
@@ -1,4 +1,5 @@
#include "Cafe/HW/Latte/Renderer/Renderer.h"
+#include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h"
#include "Cafe/HW/Latte/Renderer/OpenGL/OpenGLTextureReadback.h"
#include "Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.h"
@@ -93,8 +94,7 @@ LatteTextureReadbackInfoGL::~LatteTextureReadbackInfoGL()
void LatteTextureReadbackInfoGL::StartTransfer()
{
cemu_assert(m_textureView);
-
- g_renderer->texture_bindAndActivate(m_textureView, 0);
+ ((OpenGLRenderer*)g_renderer.get())->texture_bindAndActivate(m_textureView, 0);
// create unsynchronized buffer
glGenBuffers(1, &texImageBufferGL);
glBindBuffer(GL_PIXEL_PACK_BUFFER, texImageBufferGL);
diff --git a/src/Cafe/HW/Latte/Renderer/Renderer.h b/src/Cafe/HW/Latte/Renderer/Renderer.h
index 11d102d0..93edaf8d 100644
--- a/src/Cafe/HW/Latte/Renderer/Renderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Renderer.h
@@ -110,13 +110,9 @@ public:
virtual void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) = 0;
virtual void texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sliceIndex, sint32 mipIndex, bool clearDepth, bool clearStencil, float depthValue, uint32 stencilValue) = 0;
- virtual LatteTexture* texture_createTextureEx(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) = 0;
+ virtual LatteTexture* texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) = 0;
- virtual void texture_bindAndActivate(LatteTextureView* textureView, uint32 textureUnit) = 0;
- virtual void texture_bindAndActivateRawTex(LatteTexture* texture, uint32 textureUnit) = 0;
- virtual void texture_bindOnly(LatteTextureView* textureView, uint32 textureUnit) = 0;
- virtual void texture_rememberBoundTexture(uint32 textureUnit) = 0;
- virtual void texture_restoreBoundTexture(uint32 textureUnit) = 0;
+ virtual void texture_setLatteTexture(LatteTextureView* textureView, uint32 textureUnit) = 0;
virtual void texture_copyImageSubData(LatteTexture* src, sint32 srcMip, sint32 effectiveSrcX, sint32 effectiveSrcY, sint32 srcSlice, LatteTexture* dst, sint32 dstMip, sint32 effectiveDstX, sint32 effectiveDstY, sint32 dstSlice, sint32 effectiveCopyWidth, sint32 effectiveCopyHeight, sint32 srcDepth) = 0;
virtual LatteTextureReadbackInfo* texture_createReadback(LatteTextureView* textureView) = 0;
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp
index b41760bc..b5f62707 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp
@@ -3,9 +3,9 @@
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
-LatteTextureVk::LatteTextureVk(class VulkanRenderer* vkRenderer, uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
+LatteTextureVk::LatteTextureVk(class VulkanRenderer* vkRenderer, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
Latte::E_HWTILEMODE tileMode, bool isDepth)
- : LatteTexture(textureUnit, dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth), m_vkr(vkRenderer)
+ : LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth), m_vkr(vkRenderer)
{
vkObjTex = new VKRObjectTexture();
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.h b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.h
index 2131ed9c..714c4e17 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.h
@@ -9,7 +9,7 @@
class LatteTextureVk : public LatteTexture
{
public:
- LatteTextureVk(class VulkanRenderer* vkRenderer, uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
+ LatteTextureVk(class VulkanRenderer* vkRenderer, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
~LatteTextureVk();
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index 2ce5dacd..44214606 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -3326,18 +3326,13 @@ void VulkanRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width,
barrier_image(vkTexture, barrierSubresourceRange, VK_IMAGE_LAYOUT_GENERAL);
}
-LatteTexture* VulkanRenderer::texture_createTextureEx(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
+LatteTexture* VulkanRenderer::texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels,
uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth)
{
- return new LatteTextureVk(this, textureUnit, dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
+ return new LatteTextureVk(this, dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
}
-void VulkanRenderer::texture_bindAndActivate(LatteTextureView* textureView, uint32 textureUnit)
-{
- m_state.boundTexture[textureUnit] = static_cast(textureView);
-}
-
-void VulkanRenderer::texture_bindOnly(LatteTextureView* textureView, uint32 textureUnit)
+void VulkanRenderer::texture_setLatteTexture(LatteTextureView* textureView, uint32 textureUnit)
{
m_state.boundTexture[textureUnit] = static_cast(textureView);
}
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
index 84cae587..b61a0b40 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
@@ -300,15 +300,10 @@ public:
void texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize) override;
- LatteTexture* texture_createTextureEx(uint32 textureUnit, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) override;
+ LatteTexture* texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) override;
- void texture_bindAndActivate(LatteTextureView* textureView, uint32 textureUnit) override;
- void texture_bindOnly(LatteTextureView* textureView, uint32 textureUnit) override;
+ void texture_setLatteTexture(LatteTextureView* textureView, uint32 textureUnit) override;
- void texture_bindAndActivateRawTex(LatteTexture* texture, uint32 textureUnit) override {};
-
- void texture_rememberBoundTexture(uint32 textureUnit) override {};
- void texture_restoreBoundTexture(uint32 textureUnit) override {};
void texture_copyImageSubData(LatteTexture* src, sint32 srcMip, sint32 effectiveSrcX, sint32 effectiveSrcY, sint32 srcSlice, LatteTexture* dst, sint32 dstMip, sint32 effectiveDstX, sint32 effectiveDstY, sint32 dstSlice, sint32 effectiveCopyWidth, sint32 effectiveCopyHeight, sint32 srcDepth) override;
LatteTextureReadbackInfo* texture_createReadback(LatteTextureView* textureView) override;
diff --git a/src/Common/GLInclude/GLInclude.h b/src/Common/GLInclude/GLInclude.h
index 6f5d33db..bf7a6bf8 100644
--- a/src/Common/GLInclude/GLInclude.h
+++ b/src/Common/GLInclude/GLInclude.h
@@ -42,6 +42,177 @@ typedef struct __GLXFBConfigRec *GLXFBConfig;
#undef GLFUNC
#undef EGLFUNC
+// DSA-style helpers with fallback to legacy API if DSA is not supported
+
+#define DSA_FORCE_DISABLE false // set to true to simulate DSA not being supported
+
+static GLenum GetGLBindingFromTextureTarget(GLenum texTarget)
+{
+ switch(texTarget)
+ {
+ case GL_TEXTURE_1D: return GL_TEXTURE_BINDING_1D;
+ case GL_TEXTURE_2D: return GL_TEXTURE_BINDING_2D;
+ case GL_TEXTURE_3D: return GL_TEXTURE_BINDING_3D;
+ case GL_TEXTURE_2D_ARRAY: return GL_TEXTURE_BINDING_2D_ARRAY;
+ case GL_TEXTURE_CUBE_MAP: return GL_TEXTURE_BINDING_CUBE_MAP;
+ case GL_TEXTURE_CUBE_MAP_ARRAY: return GL_TEXTURE_BINDING_CUBE_MAP_ARRAY;
+ default:
+ cemu_assert_unimplemented();
+ return 0;
+ }
+}
+
+static GLuint glCreateTextureWrapper(GLenum target)
+{
+ GLuint tex;
+ if (glCreateTextures && !DSA_FORCE_DISABLE)
+ {
+ glCreateTextures(target, 1, &tex);
+ return tex;
+ }
+ GLint originalTexture;
+ glGetIntegerv(GetGLBindingFromTextureTarget(target), &originalTexture);
+ glGenTextures(1, &tex);
+ glBindTexture(target, tex);
+ glBindTexture(target, originalTexture);
+ return tex;
+}
+
+static void glTextureStorage1DWrapper(GLenum target, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width)
+{
+ if (glTextureStorage1D && !DSA_FORCE_DISABLE)
+ {
+ glTextureStorage1D(texture, levels, internalformat, width);
+ return;
+ }
+ GLenum binding = GetGLBindingFromTextureTarget(target);
+ GLint originalTexture;
+ glGetIntegerv(binding, &originalTexture);
+ glBindTexture(target, texture);
+ glTexStorage1D(target, levels, internalformat, width);
+ glBindTexture(target, originalTexture);
+}
+
+static void glTextureStorage2DWrapper(GLenum target, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ if (glTextureStorage2D && !DSA_FORCE_DISABLE)
+ {
+ glTextureStorage2D(texture, levels, internalformat, width, height);
+ return;
+ }
+ GLenum binding = GetGLBindingFromTextureTarget(target);
+ GLint originalTexture;
+ glGetIntegerv(binding, &originalTexture);
+ glBindTexture(target, texture);
+ glTexStorage2D(target, levels, internalformat, width, height);
+ glBindTexture(target, originalTexture);
+}
+
+static void glTextureStorage3DWrapper(GLenum target, GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+{
+ if (glTextureStorage3D && !DSA_FORCE_DISABLE)
+ {
+ glTextureStorage3D(texture, levels, internalformat, width, height, depth);
+ return;
+ }
+ GLenum binding = GetGLBindingFromTextureTarget(target);
+ GLint originalTexture;
+ glGetIntegerv(binding, &originalTexture);
+ glBindTexture(target, texture);
+ glTexStorage3D(target, levels, internalformat, width, height, depth);
+ glBindTexture(target, originalTexture);
+}
+
+static void glTextureSubImage1DWrapper(GLenum target, GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels)
+{
+ if (glTextureSubImage1D && !DSA_FORCE_DISABLE)
+ {
+ glTextureSubImage1D(texture, level, xoffset, width, format, type, pixels);
+ return;
+ }
+ GLenum binding = GetGLBindingFromTextureTarget(target);
+ GLint originalTexture;
+ glGetIntegerv(binding, &originalTexture);
+ glBindTexture(target, texture);
+ glTexSubImage1D(target, level, xoffset, width, format, type, pixels);
+ glBindTexture(target, originalTexture);
+}
+
+static void glCompressedTextureSubImage1DWrapper(GLenum target, GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data)
+{
+ if (glCompressedTextureSubImage1D && !DSA_FORCE_DISABLE)
+ {
+ glCompressedTextureSubImage1D(texture, level, xoffset, width, format, imageSize, data);
+ return;
+ }
+ GLenum binding = GetGLBindingFromTextureTarget(target);
+ GLint originalTexture;
+ glGetIntegerv(binding, &originalTexture);
+ glBindTexture(target, texture);
+ glCompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, data);
+ glBindTexture(target, originalTexture);
+}
+
+static void glTextureSubImage2DWrapper(GLenum target, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels)
+{
+ if (glTextureSubImage2D && !DSA_FORCE_DISABLE)
+ {
+ glTextureSubImage2D(texture, level, xoffset, yoffset, width, height, format, type, pixels);
+ return;
+ }
+ GLenum binding = GetGLBindingFromTextureTarget(target);
+ GLint originalTexture;
+ glGetIntegerv(binding, &originalTexture);
+ glBindTexture(target, texture);
+ glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
+ glBindTexture(target, originalTexture);
+}
+
+static void glCompressedTextureSubImage2DWrapper(GLenum target, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
+{
+ if (glCompressedTextureSubImage2D && !DSA_FORCE_DISABLE)
+ {
+ glCompressedTextureSubImage2D(texture, level, xoffset, yoffset, width, height, format, imageSize, data);
+ return;
+ }
+ GLenum binding = GetGLBindingFromTextureTarget(target);
+ GLint originalTexture;
+ glGetIntegerv(binding, &originalTexture);
+ glBindTexture(target, texture);
+ glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+ glBindTexture(target, originalTexture);
+}
+
+static void glTextureSubImage3DWrapper(GLenum target, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels)
+{
+ if(glTextureSubImage3D && !DSA_FORCE_DISABLE)
+ {
+ glTextureSubImage3D(texture, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+ return;
+ }
+ GLenum binding = GetGLBindingFromTextureTarget(target);
+ GLint originalTexture;
+ glGetIntegerv(binding, &originalTexture);
+ glBindTexture(target, texture);
+ glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+ glBindTexture(target, originalTexture);
+}
+
+static void glCompressedTextureSubImage3DWrapper(GLenum target, GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data)
+{
+ if(glCompressedTextureSubImage3D && !DSA_FORCE_DISABLE)
+ {
+ glCompressedTextureSubImage3D(texture, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
+ return;
+ }
+ GLenum binding = GetGLBindingFromTextureTarget(target);
+ GLint originalTexture;
+ glGetIntegerv(binding, &originalTexture);
+ glBindTexture(target, texture);
+ glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
+ glBindTexture(target, originalTexture);
+}
+
// this prevents Windows GL.h from being included:
#define __gl_h_
#define __GL_H__
diff --git a/src/Common/GLInclude/glFunctions.h b/src/Common/GLInclude/glFunctions.h
index 4cf25a6b..76308fdb 100644
--- a/src/Common/GLInclude/glFunctions.h
+++ b/src/Common/GLInclude/glFunctions.h
@@ -171,10 +171,13 @@ GLFUNC(PFNGLTEXSTORAGE2DPROC, glTexStorage2D)
GLFUNC(PFNGLTEXSTORAGE3DPROC, glTexStorage3D)
GLFUNC(PFNGLTEXIMAGE3DPROC, glTexImage3D)
GLFUNC(PFNGLTEXSUBIMAGE3DPROC, glTexSubImage3D)
+GLFUNC(PFNGLCOMPRESSEDTEXIMAGE1DPROC, glCompressedTexImage1D)
GLFUNC(PFNGLCOMPRESSEDTEXIMAGE2DPROC, glCompressedTexImage2D)
GLFUNC(PFNGLCOMPRESSEDTEXIMAGE3DPROC, glCompressedTexImage3D)
+GLFUNC(PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC, glCompressedTexSubImage1D)
GLFUNC(PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedTexSubImage2D)
GLFUNC(PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedTexSubImage3D)
+GLFUNC(PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC, glCompressedTextureSubImage1D)
GLFUNC(PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC, glCompressedTextureSubImage2D)
GLFUNC(PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC, glCompressedTextureSubImage3D)
GLFUNC(PFNGLCOPYIMAGESUBDATAPROC, glCopyImageSubData)
@@ -184,12 +187,17 @@ GLFUNC(PFNGLINVALIDATETEXIMAGEPROC, glInvalidateTexImage)
// texture DSA
+GLFUNC(PFNGLCREATETEXTURESPROC, glCreateTextures)
GLFUNC(PFNGLBINDTEXTUREUNITPROC, glBindTextureUnit)
GLFUNC(PFNGLGETTEXTURELEVELPARAMETERIVPROC, glGetTextureLevelParameteriv)
GLFUNC(PFNGLTEXTUREPARAMETERIPROC, glTextureParameteri)
GLFUNC(PFNGLGETTEXTURESUBIMAGEPROC, glGetTextureSubImage)
+GLFUNC(PFNGLTEXTURESUBIMAGE1DPROC, glTextureSubImage1D)
GLFUNC(PFNGLTEXTURESUBIMAGE2DPROC, glTextureSubImage2D);
GLFUNC(PFNGLTEXTURESUBIMAGE3DPROC, glTextureSubImage3D)
+GLFUNC(PFNGLTEXTURESTORAGE1DPROC, glTextureStorage1D)
+GLFUNC(PFNGLTEXTURESTORAGE2DPROC, glTextureStorage2D)
+GLFUNC(PFNGLTEXTURESTORAGE3DPROC, glTextureStorage3D)
// instancing / draw
From 2167143c17168cc7376b08a8fb3a501c1bc3ab87 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Wed, 13 Dec 2023 12:22:59 +0100
Subject: [PATCH 013/319] Latte: Support for SAMPLE_LB
---
.../HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp | 4 ++++
.../LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp | 9 +++++++--
.../LegacyShaderDecompiler/LatteDecompilerInternal.h | 1 +
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp
index 30e3d7a2..cf88b901 100644
--- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp
+++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.cpp
@@ -666,6 +666,9 @@ void LatteDecompiler_ParseTEXClause(LatteDecompilerShader* shaderContext, LatteD
uint32 offsetY = (word2 >> 5) & 0x1F;
uint32 offsetZ = (word2 >> 10) & 0x1F;
+ sint8 lodBias = (word2 >> 21) & 0x7F;
+ if ((lodBias&0x40) != 0)
+ lodBias |= 0x80;
// bufferID -> Texture index
// samplerId -> Sampler index
sint32 textureIndex = bufferId - 0x00;
@@ -693,6 +696,7 @@ void LatteDecompiler_ParseTEXClause(LatteDecompilerShader* shaderContext, LatteD
texInstruction.textureFetch.unnormalized[1] = coordTypeY == 0;
texInstruction.textureFetch.unnormalized[2] = coordTypeZ == 0;
texInstruction.textureFetch.unnormalized[3] = coordTypeW == 0;
+ texInstruction.textureFetch.lodBias = (sint8)lodBias;
cfInstruction->instructionsTEX.emplace_back(texInstruction);
}
else if( inst0_4 == GPU7_TEX_INST_SET_CUBEMAP_INDEX )
diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp
index a37ba011..aa7b7162 100644
--- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp
+++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp
@@ -2561,8 +2561,13 @@ void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContext, Latt
// lod or lod bias parameter
if( texOpcode == GPU7_TEX_INST_SAMPLE_L || texOpcode == GPU7_TEX_INST_SAMPLE_LB || texOpcode == GPU7_TEX_INST_SAMPLE_C_L)
{
- src->add(",");
- _emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 3, LATTE_DECOMPILER_DTYPE_FLOAT);
+ if(texOpcode == GPU7_TEX_INST_SAMPLE_LB)
+ src->addFmt("{}", (float)texInstruction->textureFetch.lodBias / 16.0f);
+ else
+ {
+ src->add(",");
+ _emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 3, LATTE_DECOMPILER_DTYPE_FLOAT);
+ }
}
else if( texOpcode == GPU7_TEX_INST_SAMPLE_LZ || texOpcode == GPU7_TEX_INST_SAMPLE_C_LZ )
{
diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h
index 54112ddf..ac2a1fe1 100644
--- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h
+++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h
@@ -57,6 +57,7 @@ struct LatteDecompilerTEXInstruction
sint8 offsetY{};
sint8 offsetZ{};
bool unnormalized[4]{}; // set if texture coordinates are in [0,dim] range instead of [0,1]
+ sint8 lodBias{}; // divide by 16 to get actual value
}textureFetch;
// memRead
struct
From d2ba4e65c5d7802e53faac21922be1bf9347f325 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Wed, 13 Dec 2023 18:09:30 +0100
Subject: [PATCH 014/319] Latte: 1D views are compatible with 1D textures
---
src/Cafe/HW/Latte/Core/LatteTexture.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.cpp b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
index 06afed60..d38af8ec 100644
--- a/src/Cafe/HW/Latte/Core/LatteTexture.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
@@ -795,6 +795,8 @@ bool IsDimensionCompatibleForView(Latte::E_DIM baseDim, Latte::E_DIM viewDim)
bool incompatibleDim = false;
if (baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_2D)
;
+ else if (baseDim == Latte::E_DIM::DIM_1D && viewDim == Latte::E_DIM::DIM_1D)
+ ;
else if (baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_2D_ARRAY)
;
else if (baseDim == Latte::E_DIM::DIM_CUBEMAP && viewDim == Latte::E_DIM::DIM_CUBEMAP)
From bab1616565b8fab99c52e0bedb275ae90a7b53df Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Wed, 13 Dec 2023 22:43:37 +0100
Subject: [PATCH 015/319] nsysnet: Add support for SO_BIO and handle
SO_ENOTCONN
---
.../libs/nn_olv/nn_olv_UploadCommunityTypes.h | 6 ++----
src/Cafe/OS/libs/nsysnet/nsysnet.cpp | 19 +++++++++++++------
2 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/src/Cafe/OS/libs/nn_olv/nn_olv_UploadCommunityTypes.h b/src/Cafe/OS/libs/nn_olv/nn_olv_UploadCommunityTypes.h
index 16ebd29a..2c53f118 100644
--- a/src/Cafe/OS/libs/nn_olv/nn_olv_UploadCommunityTypes.h
+++ b/src/Cafe/OS/libs/nn_olv/nn_olv_UploadCommunityTypes.h
@@ -256,10 +256,8 @@ namespace nn
this->flags = 0;
memset(this->titleText, 0, sizeof(this->titleText));
memset(this->description, 0, sizeof(this->description));
- int v2 = 0;
- do
- memset(this->searchKeys[v2++], 0, sizeof(this->searchKeys[v2++]));
- while (v2 < 5);
+ for (int i = 0; i < 5; i++)
+ memset(this->searchKeys[i], 0, sizeof(this->searchKeys[0]));
}
static UploadCommunityDataParam* __ctor(UploadCommunityDataParam* _this)
{
diff --git a/src/Cafe/OS/libs/nsysnet/nsysnet.cpp b/src/Cafe/OS/libs/nsysnet/nsysnet.cpp
index e0224148..128c19a5 100644
--- a/src/Cafe/OS/libs/nsysnet/nsysnet.cpp
+++ b/src/Cafe/OS/libs/nsysnet/nsysnet.cpp
@@ -13,6 +13,7 @@
#define WSAESHUTDOWN ESHUTDOWN
#define WSAECONNABORTED ECONNABORTED
#define WSAHOST_NOT_FOUND EAI_NONAME
+#define WSAENOTCONN ENOTCONN
#define GETLASTERR errno
@@ -40,6 +41,7 @@
#define WU_SO_RCVBUF 0x1002
#define WU_SO_LASTERROR 0x1007
#define WU_SO_NBIO 0x1014
+#define WU_SO_BIO 0x1015
#define WU_SO_NONBLOCK 0x1016
#define WU_TCP_NODELAY 0x2004
@@ -53,6 +55,7 @@
#define WU_SO_SUCCESS 0x0000
#define WU_SO_EWOULDBLOCK 0x0006
#define WU_SO_ECONNRESET 0x0008
+#define WU_SO_ENOTCONN 0x0009
#define WU_SO_EINVAL 0x000B
#define WU_SO_EINPROGRESS 0x0016
#define WU_SO_EAFNOSUPPORT 0x0021
@@ -148,8 +151,11 @@ sint32 _translateError(sint32 returnCode, sint32 wsaError, sint32 mode = _ERROR_
case WSAESHUTDOWN:
_setSockError(WU_SO_ESHUTDOWN);
break;
+ case WSAENOTCONN:
+ _setSockError(WU_SO_ENOTCONN);
+ break;
default:
- cemuLog_logDebug(LogType::Force, "Unhandled wsaError {}\n", wsaError);
+ cemuLog_logDebug(LogType::Force, "Unhandled wsaError {}", wsaError);
_setSockError(99999); // unhandled error
}
return -1;
@@ -157,7 +163,7 @@ sint32 _translateError(sint32 returnCode, sint32 wsaError, sint32 mode = _ERROR_
void nsysnetExport_socketlasterr(PPCInterpreter_t* hCPU)
{
- cemuLog_log(LogType::Socket, "socketlasterr() -> {}", _getSockError());
+ cemuLog_logDebug(LogType::Socket, "socketlasterr() -> {}", _getSockError());
osLib_returnFromFunction(hCPU, _getSockError());
}
@@ -485,9 +491,9 @@ void nsysnetExport_setsockopt(PPCInterpreter_t* hCPU)
if (r != 0)
cemu_assert_suspicious();
}
- else if (optname == WU_SO_NBIO)
+ else if (optname == WU_SO_NBIO || optname == WU_SO_BIO)
{
- // similar to WU_SO_NONBLOCK but always sets non-blocking mode regardless of option value
+ // similar to WU_SO_NONBLOCK but always sets blocking (_BIO) or non-blocking (_NBIO) mode regardless of option value
if (optlen == 4)
{
sint32 optvalLE = _swapEndianU32(*(uint32*)optval);
@@ -498,9 +504,10 @@ void nsysnetExport_setsockopt(PPCInterpreter_t* hCPU)
}
else
cemu_assert_suspicious();
- u_long mode = 1;
+ bool setNonBlocking = optname == WU_SO_NBIO;
+ u_long mode = setNonBlocking ? 1 : 0;
_socket_nonblock(vs->s, mode);
- vs->isNonBlocking = true;
+ vs->isNonBlocking = setNonBlocking;
}
else if (optname == WU_SO_NONBLOCK)
{
From 4405116324fda4895ccdc1ec6bc32ee253b16261 Mon Sep 17 00:00:00 2001
From: GaryOderNichts <12049776+GaryOderNichts@users.noreply.github.com>
Date: Sun, 24 Dec 2023 00:25:01 +0100
Subject: [PATCH 016/319] GDBStub: Support watchpoints on linux (#1030)
* GDBStub: Support watchpoints on linux
* GDBStub: Use `TCP_NODELAY`
---
src/Cafe/CMakeLists.txt | 1 +
.../HW/Espresso/Debugger/GDBBreakpoints.cpp | 304 ++++++++++++++++++
.../HW/Espresso/Debugger/GDBBreakpoints.h | 211 +-----------
src/Cafe/HW/Espresso/Debugger/GDBStub.cpp | 8 +
src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp | 31 +-
.../ExceptionHandler_posix.cpp | 13 +
6 files changed, 371 insertions(+), 197 deletions(-)
create mode 100644 src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.cpp
diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt
index 29c5a0b3..9e20bb33 100644
--- a/src/Cafe/CMakeLists.txt
+++ b/src/Cafe/CMakeLists.txt
@@ -40,6 +40,7 @@ add_library(CemuCafe
HW/Espresso/Debugger/DebugSymbolStorage.h
HW/Espresso/Debugger/GDBStub.h
HW/Espresso/Debugger/GDBStub.cpp
+ HW/Espresso/Debugger/GDBBreakpoints.cpp
HW/Espresso/Debugger/GDBBreakpoints.h
HW/Espresso/EspressoISA.h
HW/Espresso/Interpreter/PPCInterpreterALU.hpp
diff --git a/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.cpp b/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.cpp
new file mode 100644
index 00000000..675050d3
--- /dev/null
+++ b/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.cpp
@@ -0,0 +1,304 @@
+#include "GDBBreakpoints.h"
+#include "Debugger.h"
+#include "Cafe/HW/Espresso/Recompiler/PPCRecompiler.h"
+
+#if defined(ARCH_X86_64) && BOOST_OS_LINUX
+#include
+#include
+#include
+
+DRType _GetDR(pid_t tid, int drIndex)
+{
+ size_t drOffset = offsetof(struct user, u_debugreg) + drIndex * sizeof(user::u_debugreg[0]);
+
+ long v;
+ v = ptrace(PTRACE_PEEKUSER, tid, drOffset, nullptr);
+ if (v == -1)
+ perror("ptrace(PTRACE_PEEKUSER)");
+
+ return (DRType)v;
+}
+
+void _SetDR(pid_t tid, int drIndex, DRType newValue)
+{
+ size_t drOffset = offsetof(struct user, u_debugreg) + drIndex * sizeof(user::u_debugreg[0]);
+
+ long rc = ptrace(PTRACE_POKEUSER, tid, drOffset, newValue);
+ if (rc == -1)
+ perror("ptrace(PTRACE_POKEUSER)");
+}
+
+DRType _ReadDR6()
+{
+ pid_t tid = gettid();
+
+ // linux doesn't let us attach to the current thread / threads in the current thread group
+ // we have to create a child process which then modifies the debug registers and quits
+ pid_t child = fork();
+ if (child == -1)
+ {
+ perror("fork");
+ return 0;
+ }
+
+ if (child == 0)
+ {
+ if (ptrace(PTRACE_ATTACH, tid, nullptr, nullptr))
+ {
+ perror("attach");
+ _exit(0);
+ }
+
+ waitpid(tid, NULL, 0);
+
+ uint64_t dr6 = _GetDR(tid, 6);
+
+ if (ptrace(PTRACE_DETACH, tid, nullptr, nullptr))
+ perror("detach");
+
+ // since the status code only uses the lower 8 bits, we have to discard the rest of DR6
+ // this should be fine though, since the lower 4 bits of DR6 contain all the bp conditions
+ _exit(dr6 & 0xff);
+ }
+
+ // wait for child process
+ int wstatus;
+ waitpid(child, &wstatus, 0);
+
+ return (DRType)WEXITSTATUS(wstatus);
+}
+#endif
+
+GDBServer::ExecutionBreakpoint::ExecutionBreakpoint(MPTR address, BreakpointType type, bool visible, std::string reason)
+ : m_address(address), m_removedAfterInterrupt(false), m_reason(std::move(reason))
+{
+ if (type == BreakpointType::BP_SINGLE)
+ {
+ this->m_pauseThreads = true;
+ this->m_restoreAfterInterrupt = false;
+ this->m_deleteAfterAnyInterrupt = false;
+ this->m_pauseOnNextInterrupt = false;
+ this->m_visible = visible;
+ }
+ else if (type == BreakpointType::BP_PERSISTENT)
+ {
+ this->m_pauseThreads = true;
+ this->m_restoreAfterInterrupt = true;
+ this->m_deleteAfterAnyInterrupt = false;
+ this->m_pauseOnNextInterrupt = false;
+ this->m_visible = visible;
+ }
+ else if (type == BreakpointType::BP_RESTORE_POINT)
+ {
+ this->m_pauseThreads = false;
+ this->m_restoreAfterInterrupt = false;
+ this->m_deleteAfterAnyInterrupt = false;
+ this->m_pauseOnNextInterrupt = false;
+ this->m_visible = false;
+ }
+ else if (type == BreakpointType::BP_STEP_POINT)
+ {
+ this->m_pauseThreads = false;
+ this->m_restoreAfterInterrupt = false;
+ this->m_deleteAfterAnyInterrupt = true;
+ this->m_pauseOnNextInterrupt = true;
+ this->m_visible = false;
+ }
+
+ this->m_origOpCode = memory_readU32(address);
+ memory_writeU32(address, DEBUGGER_BP_T_GDBSTUB_TW);
+ PPCRecompiler_invalidateRange(address, address + 4);
+}
+
+GDBServer::ExecutionBreakpoint::~ExecutionBreakpoint()
+{
+ memory_writeU32(this->m_address, this->m_origOpCode);
+ PPCRecompiler_invalidateRange(this->m_address, this->m_address + 4);
+}
+
+uint32 GDBServer::ExecutionBreakpoint::GetVisibleOpCode() const
+{
+ if (this->m_visible)
+ return memory_readU32(this->m_address);
+ else
+ return this->m_origOpCode;
+}
+
+void GDBServer::ExecutionBreakpoint::RemoveTemporarily()
+{
+ memory_writeU32(this->m_address, this->m_origOpCode);
+ PPCRecompiler_invalidateRange(this->m_address, this->m_address + 4);
+ this->m_restoreAfterInterrupt = true;
+}
+
+void GDBServer::ExecutionBreakpoint::Restore()
+{
+ memory_writeU32(this->m_address, DEBUGGER_BP_T_GDBSTUB_TW);
+ PPCRecompiler_invalidateRange(this->m_address, this->m_address + 4);
+ this->m_restoreAfterInterrupt = false;
+}
+
+namespace coreinit
+{
+#if BOOST_OS_LINUX
+ std::vector& OSGetSchedulerThreadIds();
+#endif
+
+ std::vector& OSGetSchedulerThreads();
+}
+
+GDBServer::AccessBreakpoint::AccessBreakpoint(MPTR address, AccessPointType type)
+ : m_address(address), m_type(type)
+{
+#if defined(ARCH_X86_64) && BOOST_OS_WINDOWS
+ for (auto& hThreadNH : coreinit::OSGetSchedulerThreads())
+ {
+ HANDLE hThread = (HANDLE)hThreadNH;
+ CONTEXT ctx{};
+ ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ SuspendThread(hThread);
+ GetThreadContext(hThread, &ctx);
+
+ // use BP 2/3 for gdb stub since cemu's internal debugger uses BP 0/1 already
+ ctx.Dr2 = (DWORD64)memory_getPointerFromVirtualOffset(address);
+ ctx.Dr3 = (DWORD64)memory_getPointerFromVirtualOffset(address);
+ // breakpoint 2
+ SetBits(ctx.Dr7, 4, 1, 1); // breakpoint #3 enabled: true
+ SetBits(ctx.Dr7, 24, 2, 1); // breakpoint #3 condition: 1 (write)
+ SetBits(ctx.Dr7, 26, 2, 3); // breakpoint #3 length: 3 (4 bytes)
+ // breakpoint 3
+ SetBits(ctx.Dr7, 6, 1, 1); // breakpoint #4 enabled: true
+ SetBits(ctx.Dr7, 28, 2, 3); // breakpoint #4 condition: 3 (read & write)
+ SetBits(ctx.Dr7, 30, 2, 3); // breakpoint #4 length: 3 (4 bytes)
+
+ SetThreadContext(hThread, &ctx);
+ ResumeThread(hThread);
+ }
+#elif defined(ARCH_X86_64) && BOOST_OS_LINUX
+ // linux doesn't let us attach to threads which are in the same thread group as our current thread
+ // we have to create a child process which then modifies the debug registers and quits
+ pid_t child = fork();
+ if (child == -1)
+ {
+ perror("fork");
+ return;
+ }
+
+ if (child == 0)
+ {
+ for (pid_t tid : coreinit::OSGetSchedulerThreadIds())
+ {
+ long rc = ptrace(PTRACE_ATTACH, tid, nullptr, nullptr);
+ if (rc == -1)
+ perror("ptrace(PTRACE_ATTACH)");
+
+ waitpid(tid, nullptr, 0);
+
+ DRType dr7 = _GetDR(tid, 7);
+ // use BP 2/3 for gdb stub since cemu's internal debugger uses BP 0/1 already
+ DRType dr2 = (uint64)memory_getPointerFromVirtualOffset(address);
+ DRType dr3 = (uint64)memory_getPointerFromVirtualOffset(address);
+ // breakpoint 2
+ SetBits(dr7, 4, 1, 1); // breakpoint #3 enabled: true
+ SetBits(dr7, 24, 2, 1); // breakpoint #3 condition: 1 (write)
+ SetBits(dr7, 26, 2, 3); // breakpoint #3 length: 3 (4 bytes)
+ // breakpoint 3
+ SetBits(dr7, 6, 1, 1); // breakpoint #4 enabled: true
+ SetBits(dr7, 28, 2, 3); // breakpoint #4 condition: 3 (read & write)
+ SetBits(dr7, 30, 2, 3); // breakpoint #4 length: 3 (4 bytes)
+
+ _SetDR(tid, 2, dr2);
+ _SetDR(tid, 3, dr3);
+ _SetDR(tid, 7, dr7);
+
+ rc = ptrace(PTRACE_DETACH, tid, nullptr, nullptr);
+ if (rc == -1)
+ perror("ptrace(PTRACE_DETACH)");
+ }
+
+ // exit child process
+ _exit(0);
+ }
+
+ // wait for child process
+ waitpid(child, nullptr, 0);
+#else
+ cemuLog_log(LogType::Force, "Debugger read/write breakpoints are not supported on non-x86 CPUs yet.");
+#endif
+}
+
+GDBServer::AccessBreakpoint::~AccessBreakpoint()
+{
+#if defined(ARCH_X86_64) && BOOST_OS_WINDOWS
+ for (auto& hThreadNH : coreinit::OSGetSchedulerThreads())
+ {
+ HANDLE hThread = (HANDLE)hThreadNH;
+ CONTEXT ctx{};
+ ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ SuspendThread(hThread);
+ GetThreadContext(hThread, &ctx);
+
+ // reset BP 2/3 to zero
+ ctx.Dr2 = (DWORD64)0;
+ ctx.Dr3 = (DWORD64)0;
+ // breakpoint 2
+ SetBits(ctx.Dr7, 4, 1, 0);
+ SetBits(ctx.Dr7, 24, 2, 0);
+ SetBits(ctx.Dr7, 26, 2, 0);
+ // breakpoint 3
+ SetBits(ctx.Dr7, 6, 1, 0);
+ SetBits(ctx.Dr7, 28, 2, 0);
+ SetBits(ctx.Dr7, 30, 2, 0);
+ SetThreadContext(hThread, &ctx);
+ ResumeThread(hThread);
+ }
+#elif defined(ARCH_X86_64) && BOOST_OS_LINUX
+ // linux doesn't let us attach to threads which are in the same thread group as our current thread
+ // we have to create a child process which then modifies the debug registers and quits
+ pid_t child = fork();
+ if (child == -1)
+ {
+ perror("fork");
+ return;
+ }
+
+ if (child == 0)
+ {
+ for (pid_t tid : coreinit::OSGetSchedulerThreadIds())
+ {
+ long rc = ptrace(PTRACE_ATTACH, tid, nullptr, nullptr);
+ if (rc == -1)
+ perror("ptrace(PTRACE_ATTACH)");
+
+ waitpid(tid, nullptr, 0);
+
+ DRType dr7 = _GetDR(tid, 7);
+ // reset BP 2/3 to zero
+ DRType dr2 = 0;
+ DRType dr3 = 0;
+ // breakpoint 2
+ SetBits(dr7, 4, 1, 0);
+ SetBits(dr7, 24, 2, 0);
+ SetBits(dr7, 26, 2, 0);
+ // breakpoint 3
+ SetBits(dr7, 6, 1, 0);
+ SetBits(dr7, 28, 2, 0);
+ SetBits(dr7, 30, 2, 0);
+
+ _SetDR(tid, 2, dr2);
+ _SetDR(tid, 3, dr3);
+ _SetDR(tid, 7, dr7);
+
+ rc = ptrace(PTRACE_DETACH, tid, nullptr, nullptr);
+ if (rc == -1)
+ perror("ptrace(PTRACE_DETACH)");
+ }
+
+ // exit child process
+ _exit(0);
+ }
+
+ // wait for child process
+ waitpid(child, nullptr, 0);
+#endif
+}
diff --git a/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.h b/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.h
index b86bd9a6..f94365c2 100644
--- a/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.h
+++ b/src/Cafe/HW/Espresso/Debugger/GDBBreakpoints.h
@@ -1,33 +1,18 @@
+#pragma once
+#include "GDBStub.h"
#include
-#if defined(ARCH_X86_64) && BOOST_OS_LINUX && FALSE
-#include
-#include
-#include
+#if defined(ARCH_X86_64) && BOOST_OS_LINUX
+#include
// helpers for accessing debug register
typedef unsigned long DRType;
-DRType _GetDR(pid_t tid, int drIndex)
-{
- unsigned long v;
- v = ptrace (PTRACE_PEEKUSER, tid, offsetof (struct user, u_debugreg[drIndex]), 0);
- return (DRType)v;
-}
-
-void _SetDR(pid_t tid, int drIndex, DRType newValue)
-{
- unsigned long v = newValue;
- ptrace (PTRACE_POKEUSER, tid, offsetof (struct user, u_debugreg[drIndex]), v);
-}
-
+DRType _GetDR(pid_t tid, int drIndex);
+void _SetDR(pid_t tid, int drIndex, DRType newValue);
+DRType _ReadDR6();
#endif
-namespace coreinit
-{
- std::vector& OSGetSchedulerThreads();
-}
-
enum class BreakpointType
{
BP_SINGLE,
@@ -38,59 +23,10 @@ enum class BreakpointType
class GDBServer::ExecutionBreakpoint {
public:
- ExecutionBreakpoint(MPTR address, BreakpointType type, bool visible, std::string reason)
- : m_address(address), m_removedAfterInterrupt(false), m_reason(std::move(reason))
- {
- if (type == BreakpointType::BP_SINGLE)
- {
- this->m_pauseThreads = true;
- this->m_restoreAfterInterrupt = false;
- this->m_deleteAfterAnyInterrupt = false;
- this->m_pauseOnNextInterrupt = false;
- this->m_visible = visible;
- }
- else if (type == BreakpointType::BP_PERSISTENT)
- {
- this->m_pauseThreads = true;
- this->m_restoreAfterInterrupt = true;
- this->m_deleteAfterAnyInterrupt = false;
- this->m_pauseOnNextInterrupt = false;
- this->m_visible = visible;
- }
- else if (type == BreakpointType::BP_RESTORE_POINT)
- {
- this->m_pauseThreads = false;
- this->m_restoreAfterInterrupt = false;
- this->m_deleteAfterAnyInterrupt = false;
- this->m_pauseOnNextInterrupt = false;
- this->m_visible = false;
- }
- else if (type == BreakpointType::BP_STEP_POINT)
- {
- this->m_pauseThreads = false;
- this->m_restoreAfterInterrupt = false;
- this->m_deleteAfterAnyInterrupt = true;
- this->m_pauseOnNextInterrupt = true;
- this->m_visible = false;
- }
+ ExecutionBreakpoint(MPTR address, BreakpointType type, bool visible, std::string reason);
+ ~ExecutionBreakpoint();
- this->m_origOpCode = memory_readU32(address);
- memory_writeU32(address, DEBUGGER_BP_T_GDBSTUB_TW);
- PPCRecompiler_invalidateRange(address, address + 4);
- };
- ~ExecutionBreakpoint()
- {
- memory_writeU32(this->m_address, this->m_origOpCode);
- PPCRecompiler_invalidateRange(this->m_address, this->m_address + 4);
- };
-
- [[nodiscard]] uint32 GetVisibleOpCode() const
- {
- if (this->m_visible)
- return memory_readU32(this->m_address);
- else
- return this->m_origOpCode;
- };
+ [[nodiscard]] uint32 GetVisibleOpCode() const;
[[nodiscard]] bool ShouldBreakThreads() const
{
return this->m_pauseThreads;
@@ -118,18 +54,8 @@ public:
return m_reason;
};
- void RemoveTemporarily()
- {
- memory_writeU32(this->m_address, this->m_origOpCode);
- PPCRecompiler_invalidateRange(this->m_address, this->m_address + 4);
- this->m_restoreAfterInterrupt = true;
- };
- void Restore()
- {
- memory_writeU32(this->m_address, DEBUGGER_BP_T_GDBSTUB_TW);
- PPCRecompiler_invalidateRange(this->m_address, this->m_address + 4);
- this->m_restoreAfterInterrupt = false;
- };
+ void RemoveTemporarily();
+ void Restore();
void PauseOnNextInterrupt()
{
this->m_pauseOnNextInterrupt = true;
@@ -162,115 +88,8 @@ enum class AccessPointType
class GDBServer::AccessBreakpoint {
public:
- AccessBreakpoint(MPTR address, AccessPointType type)
- : m_address(address), m_type(type)
- {
-#if defined(ARCH_X86_64) && BOOST_OS_WINDOWS
- for (auto& hThreadNH : coreinit::OSGetSchedulerThreads())
- {
- HANDLE hThread = (HANDLE)hThreadNH;
- CONTEXT ctx{};
- ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
- SuspendThread(hThread);
- GetThreadContext(hThread, &ctx);
-
- // use BP 2/3 for gdb stub since cemu's internal debugger uses BP 0/1 already
- ctx.Dr2 = (DWORD64)memory_getPointerFromVirtualOffset(address);
- ctx.Dr3 = (DWORD64)memory_getPointerFromVirtualOffset(address);
- // breakpoint 2
- SetBits(ctx.Dr7, 4, 1, 1); // breakpoint #3 enabled: true
- SetBits(ctx.Dr7, 24, 2, 1); // breakpoint #3 condition: 1 (write)
- SetBits(ctx.Dr7, 26, 2, 3); // breakpoint #3 length: 3 (4 bytes)
- // breakpoint 3
- SetBits(ctx.Dr7, 6, 1, 1); // breakpoint #4 enabled: true
- SetBits(ctx.Dr7, 28, 2, 3); // breakpoint #4 condition: 3 (read & write)
- SetBits(ctx.Dr7, 30, 2, 3); // breakpoint #4 length: 3 (4 bytes)
-
- SetThreadContext(hThread, &ctx);
- ResumeThread(hThread);
- }
- // todo: port the following code to all unix platforms, they seem to differ quite a bit
-#elif defined(ARCH_X86_64) && BOOST_OS_LINUX && FALSE
- for (auto& hThreadNH : coreinit::OSGetSchedulerThreads())
- {
- pid_t pid = (pid_t)(uintptr_t)hThreadNH;
- ptrace(PTRACE_ATTACH, pid, nullptr, nullptr);
- waitpid(pid, nullptr, 0);
-
- DRType dr7 = _GetDR(pid, 7);
- // use BP 2/3 for gdb stub since cemu's internal debugger uses BP 0/1 already
- DRType dr2 = (uint64)memory_getPointerFromVirtualOffset(address);
- DRType dr3 = (uint64)memory_getPointerFromVirtualOffset(address);
- // breakpoint 2
- SetBits(dr7, 4, 1, 1); // breakpoint #3 enabled: true
- SetBits(dr7, 24, 2, 1); // breakpoint #3 condition: 1 (write)
- SetBits(dr7, 26, 2, 3); // breakpoint #3 length: 3 (4 bytes)
- // breakpoint 3
- SetBits(dr7, 6, 1, 1); // breakpoint #4 enabled: true
- SetBits(dr7, 28, 2, 3); // breakpoint #4 condition: 3 (read & write)
- SetBits(dr7, 30, 2, 3); // breakpoint #4 length: 3 (4 bytes)
-
- _SetDR(pid, 2, dr2);
- _SetDR(pid, 3, dr3);
- _SetDR(pid, 7, dr7);
- ptrace(PTRACE_DETACH, pid, nullptr, nullptr);
- }
-#else
- cemuLog_log(LogType::Force, "Debugger read/write breakpoints are not supported on non-x86 CPUs yet.");
-#endif
- };
- ~AccessBreakpoint()
- {
-#if defined(ARCH_X86_64) && BOOST_OS_WINDOWS
- for (auto& hThreadNH : coreinit::OSGetSchedulerThreads())
- {
- HANDLE hThread = (HANDLE)hThreadNH;
- CONTEXT ctx{};
- ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
- SuspendThread(hThread);
- GetThreadContext(hThread, &ctx);
-
- // reset BP 2/3 to zero
- ctx.Dr2 = (DWORD64)0;
- ctx.Dr3 = (DWORD64)0;
- // breakpoint 2
- SetBits(ctx.Dr7, 4, 1, 0);
- SetBits(ctx.Dr7, 24, 2, 0);
- SetBits(ctx.Dr7, 26, 2, 0);
- // breakpoint 3
- SetBits(ctx.Dr7, 6, 1, 0);
- SetBits(ctx.Dr7, 28, 2, 0);
- SetBits(ctx.Dr7, 30, 2, 0);
- SetThreadContext(hThread, &ctx);
- ResumeThread(hThread);
- }
-#elif defined(ARCH_X86_64) && BOOST_OS_LINUX && FALSE
- for (auto& hThreadNH : coreinit::OSGetSchedulerThreads())
- {
- pid_t pid = (pid_t)(uintptr_t)hThreadNH;
- ptrace(PTRACE_ATTACH, pid, nullptr, nullptr);
- waitpid(pid, nullptr, 0);
-
- DRType dr7 = _GetDR(pid, 7);
- // reset BP 2/3 to zero
- DRType dr2 = 0;
- DRType dr3 = 0;
- // breakpoint 2
- SetBits(dr7, 4, 1, 0);
- SetBits(dr7, 24, 2, 0);
- SetBits(dr7, 26, 2, 0);
- // breakpoint 3
- SetBits(dr7, 6, 1, 0);
- SetBits(dr7, 28, 2, 0);
- SetBits(dr7, 30, 2, 0);
-
- _SetDR(pid, 2, dr2);
- _SetDR(pid, 3, dr3);
- _SetDR(pid, 7, dr7);
- ptrace(PTRACE_DETACH, pid, nullptr, nullptr);
- }
-#endif
- };
+ AccessBreakpoint(MPTR address, AccessPointType type);
+ ~AccessBreakpoint();
MPTR GetAddress() const
{
@@ -284,4 +103,4 @@ public:
private:
const MPTR m_address;
const AccessPointType m_type;
-};
\ No newline at end of file
+};
diff --git a/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp b/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp
index c8308594..6cddae01 100644
--- a/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp
+++ b/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp
@@ -263,6 +263,14 @@ bool GDBServer::Initialize()
return false;
}
+ int nodelayEnabled = TRUE;
+ if (setsockopt(m_server_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&nodelayEnabled, sizeof(nodelayEnabled)) == SOCKET_ERROR)
+ {
+ closesocket(m_server_socket);
+ m_server_socket = INVALID_SOCKET;
+ return false;
+ }
+
memset(&m_server_addr, 0, sizeof(m_server_addr));
m_server_addr.sin_family = AF_INET;
m_server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp
index d9b33dca..3701a4d7 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp
@@ -5,6 +5,7 @@
#include "Cafe/OS/libs/coreinit/coreinit_Time.h"
#include "Cafe/OS/libs/coreinit/coreinit_Alarm.h"
#include "Cafe/OS/libs/snd_core/ax.h"
+#include "Cafe/HW/Espresso/Debugger/GDBStub.h"
#include "Cafe/HW/Espresso/Interpreter/PPCInterpreterInternal.h"
#include "Cafe/HW/Espresso/Recompiler/PPCRecompiler.h"
@@ -1153,6 +1154,18 @@ namespace coreinit
}
}
+#if BOOST_OS_LINUX
+ #include
+ #include
+
+ std::vector g_schedulerThreadIds;
+
+ std::vector& OSGetSchedulerThreadIds()
+ {
+ return g_schedulerThreadIds;
+ }
+#endif
+
void OSSchedulerCoreEmulationThread(void* _assignedCoreIndex)
{
SetThreadName(fmt::format("OSSchedulerThread[core={}]", (uintptr_t)_assignedCoreIndex).c_str());
@@ -1160,8 +1173,21 @@ namespace coreinit
#if defined(ARCH_X86_64)
_mm_setcsr(_mm_getcsr() | 0x8000); // flush denormals to zero
#endif
+
+#if BOOST_OS_LINUX
+ if (g_gdbstub)
+ {
+ // need to allow the GDBStub to attach to our thread
+ prctl(PR_SET_DUMPABLE, (unsigned long)1);
+ prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY);
+ }
+
+ pid_t tid = gettid();
+ g_schedulerThreadIds.emplace_back(tid);
+#endif
+
t_schedulerFiber = Fiber::PrepareCurrentThread();
-
+
// create scheduler idle fiber and switch to it
g_idleLoopFiber[t_assignedCoreIndex] = new Fiber(__OSThreadCoreIdle, nullptr, nullptr);
cemu_assert_debug(PPCInterpreter_getCurrentInstance() == nullptr);
@@ -1211,6 +1237,9 @@ namespace coreinit
threadItr.join();
sSchedulerThreads.clear();
g_schedulerThreadHandles.clear();
+#if BOOST_OS_LINUX
+ g_schedulerThreadIds.clear();
+#endif
// clean up all fibers
for (auto& it : g_idleLoopFiber)
{
diff --git a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp
index 34430e37..cf547110 100644
--- a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp
+++ b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp
@@ -6,6 +6,9 @@
#include "util/helpers/StringHelpers.h"
#include "ExceptionHandler.h"
+#include "Cafe/HW/Espresso/Debugger/GDBStub.h"
+#include "Cafe/HW/Espresso/Debugger/GDBBreakpoints.h"
+
#if BOOST_OS_LINUX
#include "ELFSymbolTable.h"
#endif
@@ -61,6 +64,16 @@ void DemangleAndPrintBacktrace(char** backtrace, size_t size)
// handle signals that would dump core, print stacktrace and then dump depending on config
void handlerDumpingSignal(int sig, siginfo_t *info, void *context)
{
+#if defined(ARCH_X86_64) && BOOST_OS_LINUX
+ // Check for hardware breakpoints
+ if (info->si_signo == SIGTRAP && info->si_code == TRAP_HWBKPT)
+ {
+ uint64 dr6 = _ReadDR6();
+ g_gdbstub->HandleAccessException(dr6);
+ return;
+ }
+#endif
+
if(!CrashLog_Create())
return; // give up if crashlog was already created
From 223833cac4512c41a9d53ef630c1bd7b1bb1960c Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Sat, 13 Jan 2024 20:37:10 +0100
Subject: [PATCH 017/319] Update libraries
---
dependencies/vcpkg | 2 +-
.../vcpkg_overlay_ports/sdl2/deps.patch | 13 --
.../vcpkg_overlay_ports/sdl2/portfile.cmake | 130 ------------------
dependencies/vcpkg_overlay_ports/sdl2/usage | 8 --
.../vcpkg_overlay_ports/sdl2/vcpkg.json | 58 --------
.../vcpkg_overlay_ports_linux/sdl2/deps.patch | 13 --
.../sdl2/portfile.cmake | 130 ------------------
.../vcpkg_overlay_ports_linux/sdl2/usage | 8 --
.../vcpkg_overlay_ports_linux/sdl2/vcpkg.json | 58 --------
src/Cafe/CMakeLists.txt | 6 +-
vcpkg.json | 2 +-
11 files changed, 5 insertions(+), 423 deletions(-)
delete mode 100644 dependencies/vcpkg_overlay_ports/sdl2/deps.patch
delete mode 100644 dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake
delete mode 100644 dependencies/vcpkg_overlay_ports/sdl2/usage
delete mode 100644 dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json
delete mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/deps.patch
delete mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/portfile.cmake
delete mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/usage
delete mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/vcpkg.json
diff --git a/dependencies/vcpkg b/dependencies/vcpkg
index b81bc3a8..53bef899 160000
--- a/dependencies/vcpkg
+++ b/dependencies/vcpkg
@@ -1 +1 @@
-Subproject commit b81bc3a83fdbdffe80325eeabb2ec735a1f3c29d
+Subproject commit 53bef8994c541b6561884a8395ea35715ece75db
diff --git a/dependencies/vcpkg_overlay_ports/sdl2/deps.patch b/dependencies/vcpkg_overlay_ports/sdl2/deps.patch
deleted file mode 100644
index a8637d8c..00000000
--- a/dependencies/vcpkg_overlay_ports/sdl2/deps.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
-index 65a98efbe..2f99f28f1 100644
---- a/cmake/sdlchecks.cmake
-+++ b/cmake/sdlchecks.cmake
-@@ -352,7 +352,7 @@ endmacro()
- # - HAVE_SDL_LOADSO opt
- macro(CheckLibSampleRate)
- if(SDL_LIBSAMPLERATE)
-- find_package(SampleRate QUIET)
-+ find_package(SampleRate CONFIG REQUIRED)
- if(SampleRate_FOUND AND TARGET SampleRate::samplerate)
- set(HAVE_LIBSAMPLERATE TRUE)
- set(HAVE_LIBSAMPLERATE_H TRUE)
diff --git a/dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake b/dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake
deleted file mode 100644
index 39a724c5..00000000
--- a/dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake
+++ /dev/null
@@ -1,130 +0,0 @@
-vcpkg_from_github(
- OUT_SOURCE_PATH SOURCE_PATH
- REPO libsdl-org/SDL
- REF "release-${VERSION}"
- SHA512 90858ae8c5fdddd5e13724e05ad0970e11bbab1df8a0201c3f4ce354dc6018e5d4ab7279402a263c716aacdaa52745f78531dc225d48d790ee9307e2f6198695
- HEAD_REF main
- PATCHES
- deps.patch
-)
-
-string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC)
-string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED)
-string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT)
-
-vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
- FEATURES
- vulkan SDL_VULKAN
- x11 SDL_X11
- wayland SDL_WAYLAND
- samplerate SDL_LIBSAMPLERATE
- ibus SDL_IBUS
-)
-
-if ("x11" IN_LIST FEATURES)
- message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n")
-endif()
-if ("wayland" IN_LIST FEATURES)
- message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n")
-endif()
-if ("ibus" IN_LIST FEATURES)
- message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n")
-endif()
-
-if(VCPKG_TARGET_IS_UWP)
- set(configure_opts WINDOWS_USE_MSBUILD)
-endif()
-
-vcpkg_cmake_configure(
- SOURCE_PATH "${SOURCE_PATH}"
- ${configure_opts}
- OPTIONS ${FEATURE_OPTIONS}
- -DSDL_STATIC=${SDL_STATIC}
- -DSDL_SHARED=${SDL_SHARED}
- -DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT}
- -DSDL_LIBC=ON
- -DSDL_TEST=OFF
- -DSDL_INSTALL_CMAKEDIR="cmake"
- -DCMAKE_DISABLE_FIND_PACKAGE_Git=ON
- -DSDL_LIBSAMPLERATE_SHARED=OFF
- MAYBE_UNUSED_VARIABLES
- SDL_FORCE_STATIC_VCRT
-)
-
-vcpkg_cmake_install()
-vcpkg_cmake_config_fixup(CONFIG_PATH cmake)
-
-file(REMOVE_RECURSE
- "${CURRENT_PACKAGES_DIR}/debug/include"
- "${CURRENT_PACKAGES_DIR}/debug/share"
- "${CURRENT_PACKAGES_DIR}/bin/sdl2-config"
- "${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config"
- "${CURRENT_PACKAGES_DIR}/SDL2.framework"
- "${CURRENT_PACKAGES_DIR}/debug/SDL2.framework"
- "${CURRENT_PACKAGES_DIR}/share/licenses"
- "${CURRENT_PACKAGES_DIR}/share/aclocal"
-)
-
-file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*")
-if(NOT BINS)
- file(REMOVE_RECURSE
- "${CURRENT_PACKAGES_DIR}/bin"
- "${CURRENT_PACKAGES_DIR}/debug/bin"
- )
-endif()
-
-if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW)
- if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
- file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link")
- file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib")
- endif()
- if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
- file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link")
- file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib")
- endif()
-
- file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake")
- foreach(SHARE_FILE ${SHARE_FILES})
- vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main")
- endforeach()
-endif()
-
-vcpkg_copy_pdbs()
-
-set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)")
-set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)")
-file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX})
-file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX})
-string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}")
-string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}")
-
-if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ")
-endif()
-
-if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
- if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ")
- endif()
- if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ")
- endif()
-endif()
-
-if(VCPKG_TARGET_IS_UWP)
- if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
- endif()
- if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "d")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
- endif()
-endif()
-
-vcpkg_fixup_pkgconfig()
-
-file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
-vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt")
diff --git a/dependencies/vcpkg_overlay_ports/sdl2/usage b/dependencies/vcpkg_overlay_ports/sdl2/usage
deleted file mode 100644
index 1cddcd46..00000000
--- a/dependencies/vcpkg_overlay_ports/sdl2/usage
+++ /dev/null
@@ -1,8 +0,0 @@
-sdl2 provides CMake targets:
-
- find_package(SDL2 CONFIG REQUIRED)
- target_link_libraries(main
- PRIVATE
- $
- $,SDL2::SDL2,SDL2::SDL2-static>
- )
diff --git a/dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json b/dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json
deleted file mode 100644
index de2eb9b9..00000000
--- a/dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json
+++ /dev/null
@@ -1,58 +0,0 @@
-{
- "name": "sdl2",
- "version": "2.26.5",
- "description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.",
- "homepage": "https://www.libsdl.org/download-2.0.php",
- "license": "Zlib",
- "dependencies": [
- {
- "name": "vcpkg-cmake",
- "host": true
- },
- {
- "name": "vcpkg-cmake-config",
- "host": true
- }
- ],
- "default-features": [
- "base"
- ],
- "features": {
- "base": {
- "description": "Base functionality for SDL",
- "dependencies": [
- {
- "name": "sdl2",
- "default-features": false,
- "features": [
- "ibus",
- "wayland",
- "x11"
- ],
- "platform": "linux"
- }
- ]
- },
- "ibus": {
- "description": "Build with ibus IME support",
- "supports": "linux"
- },
- "samplerate": {
- "description": "Use libsamplerate for audio rate conversion",
- "dependencies": [
- "libsamplerate"
- ]
- },
- "vulkan": {
- "description": "Vulkan functionality for SDL"
- },
- "wayland": {
- "description": "Build with Wayland support",
- "supports": "linux"
- },
- "x11": {
- "description": "Build with X11 support",
- "supports": "!windows"
- }
- }
-}
diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/deps.patch b/dependencies/vcpkg_overlay_ports_linux/sdl2/deps.patch
deleted file mode 100644
index a8637d8c..00000000
--- a/dependencies/vcpkg_overlay_ports_linux/sdl2/deps.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
-index 65a98efbe..2f99f28f1 100644
---- a/cmake/sdlchecks.cmake
-+++ b/cmake/sdlchecks.cmake
-@@ -352,7 +352,7 @@ endmacro()
- # - HAVE_SDL_LOADSO opt
- macro(CheckLibSampleRate)
- if(SDL_LIBSAMPLERATE)
-- find_package(SampleRate QUIET)
-+ find_package(SampleRate CONFIG REQUIRED)
- if(SampleRate_FOUND AND TARGET SampleRate::samplerate)
- set(HAVE_LIBSAMPLERATE TRUE)
- set(HAVE_LIBSAMPLERATE_H TRUE)
diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/portfile.cmake b/dependencies/vcpkg_overlay_ports_linux/sdl2/portfile.cmake
deleted file mode 100644
index 39a724c5..00000000
--- a/dependencies/vcpkg_overlay_ports_linux/sdl2/portfile.cmake
+++ /dev/null
@@ -1,130 +0,0 @@
-vcpkg_from_github(
- OUT_SOURCE_PATH SOURCE_PATH
- REPO libsdl-org/SDL
- REF "release-${VERSION}"
- SHA512 90858ae8c5fdddd5e13724e05ad0970e11bbab1df8a0201c3f4ce354dc6018e5d4ab7279402a263c716aacdaa52745f78531dc225d48d790ee9307e2f6198695
- HEAD_REF main
- PATCHES
- deps.patch
-)
-
-string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC)
-string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED)
-string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT)
-
-vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
- FEATURES
- vulkan SDL_VULKAN
- x11 SDL_X11
- wayland SDL_WAYLAND
- samplerate SDL_LIBSAMPLERATE
- ibus SDL_IBUS
-)
-
-if ("x11" IN_LIST FEATURES)
- message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n")
-endif()
-if ("wayland" IN_LIST FEATURES)
- message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n")
-endif()
-if ("ibus" IN_LIST FEATURES)
- message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n")
-endif()
-
-if(VCPKG_TARGET_IS_UWP)
- set(configure_opts WINDOWS_USE_MSBUILD)
-endif()
-
-vcpkg_cmake_configure(
- SOURCE_PATH "${SOURCE_PATH}"
- ${configure_opts}
- OPTIONS ${FEATURE_OPTIONS}
- -DSDL_STATIC=${SDL_STATIC}
- -DSDL_SHARED=${SDL_SHARED}
- -DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT}
- -DSDL_LIBC=ON
- -DSDL_TEST=OFF
- -DSDL_INSTALL_CMAKEDIR="cmake"
- -DCMAKE_DISABLE_FIND_PACKAGE_Git=ON
- -DSDL_LIBSAMPLERATE_SHARED=OFF
- MAYBE_UNUSED_VARIABLES
- SDL_FORCE_STATIC_VCRT
-)
-
-vcpkg_cmake_install()
-vcpkg_cmake_config_fixup(CONFIG_PATH cmake)
-
-file(REMOVE_RECURSE
- "${CURRENT_PACKAGES_DIR}/debug/include"
- "${CURRENT_PACKAGES_DIR}/debug/share"
- "${CURRENT_PACKAGES_DIR}/bin/sdl2-config"
- "${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config"
- "${CURRENT_PACKAGES_DIR}/SDL2.framework"
- "${CURRENT_PACKAGES_DIR}/debug/SDL2.framework"
- "${CURRENT_PACKAGES_DIR}/share/licenses"
- "${CURRENT_PACKAGES_DIR}/share/aclocal"
-)
-
-file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*")
-if(NOT BINS)
- file(REMOVE_RECURSE
- "${CURRENT_PACKAGES_DIR}/bin"
- "${CURRENT_PACKAGES_DIR}/debug/bin"
- )
-endif()
-
-if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW)
- if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
- file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link")
- file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib")
- endif()
- if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
- file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link")
- file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib")
- endif()
-
- file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake")
- foreach(SHARE_FILE ${SHARE_FILES})
- vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main")
- endforeach()
-endif()
-
-vcpkg_copy_pdbs()
-
-set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)")
-set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)")
-file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX})
-file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX})
-string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}")
-string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}")
-
-if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ")
-endif()
-
-if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
- if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ")
- endif()
- if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ")
- endif()
-endif()
-
-if(VCPKG_TARGET_IS_UWP)
- if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
- endif()
- if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "d")
- vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
- endif()
-endif()
-
-vcpkg_fixup_pkgconfig()
-
-file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
-vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt")
diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/usage b/dependencies/vcpkg_overlay_ports_linux/sdl2/usage
deleted file mode 100644
index 1cddcd46..00000000
--- a/dependencies/vcpkg_overlay_ports_linux/sdl2/usage
+++ /dev/null
@@ -1,8 +0,0 @@
-sdl2 provides CMake targets:
-
- find_package(SDL2 CONFIG REQUIRED)
- target_link_libraries(main
- PRIVATE
- $
- $,SDL2::SDL2,SDL2::SDL2-static>
- )
diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/vcpkg.json b/dependencies/vcpkg_overlay_ports_linux/sdl2/vcpkg.json
deleted file mode 100644
index de2eb9b9..00000000
--- a/dependencies/vcpkg_overlay_ports_linux/sdl2/vcpkg.json
+++ /dev/null
@@ -1,58 +0,0 @@
-{
- "name": "sdl2",
- "version": "2.26.5",
- "description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.",
- "homepage": "https://www.libsdl.org/download-2.0.php",
- "license": "Zlib",
- "dependencies": [
- {
- "name": "vcpkg-cmake",
- "host": true
- },
- {
- "name": "vcpkg-cmake-config",
- "host": true
- }
- ],
- "default-features": [
- "base"
- ],
- "features": {
- "base": {
- "description": "Base functionality for SDL",
- "dependencies": [
- {
- "name": "sdl2",
- "default-features": false,
- "features": [
- "ibus",
- "wayland",
- "x11"
- ],
- "platform": "linux"
- }
- ]
- },
- "ibus": {
- "description": "Build with ibus IME support",
- "supports": "linux"
- },
- "samplerate": {
- "description": "Use libsamplerate for audio rate conversion",
- "dependencies": [
- "libsamplerate"
- ]
- },
- "vulkan": {
- "description": "Vulkan functionality for SDL"
- },
- "wayland": {
- "description": "Build with Wayland support",
- "supports": "linux"
- },
- "x11": {
- "description": "Build with X11 support",
- "supports": "!windows"
- }
- }
-}
diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt
index 9e20bb33..20853789 100644
--- a/src/Cafe/CMakeLists.txt
+++ b/src/Cafe/CMakeLists.txt
@@ -535,9 +535,9 @@ endif()
if (ENABLE_NSYSHID_LIBUSB)
if (ENABLE_VCPKG)
- find_package(libusb CONFIG REQUIRED)
- target_include_directories(CemuCafe PRIVATE ${LIBUSB_INCLUDE_DIRS})
- target_link_libraries(CemuCafe PRIVATE ${LIBUSB_LIBRARIES})
+ find_package(PkgConfig REQUIRED)
+ pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0)
+ target_link_libraries(CemuCafe PRIVATE PkgConfig::libusb)
else ()
find_package(libusb MODULE REQUIRED)
target_link_libraries(CemuCafe PRIVATE libusb::libusb)
diff --git a/vcpkg.json b/vcpkg.json
index d14a1a8a..48742b4a 100644
--- a/vcpkg.json
+++ b/vcpkg.json
@@ -1,7 +1,7 @@
{
"name": "cemu",
"version-string": "1.0",
- "builtin-baseline": "b81bc3a83fdbdffe80325eeabb2ec735a1f3c29d",
+ "builtin-baseline": "53bef8994c541b6561884a8395ea35715ece75db",
"dependencies": [
"pugixml",
"zlib",
From 9b0a1d53dc449fedebd5eb6255a312aa334ffad9 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Sun, 14 Jan 2024 23:40:29 +0100
Subject: [PATCH 018/319] Latte: Fix syntax error in generated GLSL
---
.../LatteDecompilerEmitGLSL.cpp | 32 +++++++++++--------
1 file changed, 19 insertions(+), 13 deletions(-)
diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp
index aa7b7162..f3d2c7a8 100644
--- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp
+++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp
@@ -246,6 +246,22 @@ static void _appendPVPS(LatteDecompilerShaderContext* shaderContext, StringBuf*
_appendChannel(src, aluUnit);
}
+std::string _FormatFloatAsGLSLConstant(float f)
+{
+ char floatAsStr[64];
+ size_t floatAsStrLen = fmt::format_to_n(floatAsStr, 64, "{:#}", f).size;
+ size_t floatAsStrLenOrg = floatAsStrLen;
+ if(floatAsStrLen > 0 && floatAsStr[floatAsStrLen-1] == '.')
+ {
+ floatAsStr[floatAsStrLen] = '0';
+ floatAsStrLen++;
+ }
+ cemu_assert(floatAsStrLen < 50); // constant suspiciously long?
+ floatAsStr[floatAsStrLen] = '\0';
+ cemu_assert_debug(floatAsStrLen >= 3); // shortest possible form is "0.0"
+ return floatAsStr;
+}
+
// tracks PV/PS and register backups
struct ALUClauseTemporariesState
{
@@ -926,15 +942,7 @@ void _emitOperandInputCode(LatteDecompilerShaderContext* shaderContext, LatteDec
exponent -= 127;
if ((constVal & 0xFF) == 0 && exponent >= -10 && exponent <= 10)
{
- char floatAsStr[32];
- size_t floatAsStrLen = fmt::format_to_n(floatAsStr, 32, "{:#}", *(float*)&constVal).size;
- if(floatAsStrLen > 0 && floatAsStr[floatAsStrLen-1] == '.')
- {
- floatAsStr[floatAsStrLen] = '0';
- floatAsStrLen++;
- }
- cemu_assert_debug(floatAsStrLen >= 3); // shortest possible form is "0.0"
- src->add(std::string_view(floatAsStr, floatAsStrLen));
+ src->add(_FormatFloatAsGLSLConstant(*(float*)&constVal));
}
else
src->addFmt("intBitsToFloat(0x{:08x})", constVal);
@@ -2561,13 +2569,11 @@ void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContext, Latt
// lod or lod bias parameter
if( texOpcode == GPU7_TEX_INST_SAMPLE_L || texOpcode == GPU7_TEX_INST_SAMPLE_LB || texOpcode == GPU7_TEX_INST_SAMPLE_C_L)
{
+ src->add(",");
if(texOpcode == GPU7_TEX_INST_SAMPLE_LB)
- src->addFmt("{}", (float)texInstruction->textureFetch.lodBias / 16.0f);
+ src->add(_FormatFloatAsGLSLConstant((float)texInstruction->textureFetch.lodBias / 16.0f));
else
- {
- src->add(",");
_emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 3, LATTE_DECOMPILER_DTYPE_FLOAT);
- }
}
else if( texOpcode == GPU7_TEX_INST_SAMPLE_LZ || texOpcode == GPU7_TEX_INST_SAMPLE_C_LZ )
{
From f39a5e757b1d82c509c12ba67e88916cf7341573 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Mon, 15 Jan 2024 15:14:42 +0100
Subject: [PATCH 019/319] Add "Open MLC folder" option
Also updated Patron supporter list
---
src/gui/MainWindow.cpp | 14 ++++++++++----
src/gui/MainWindow.h | 2 +-
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index 92594d00..dc9ff0a8 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -75,6 +75,7 @@ enum
MAINFRAME_MENU_ID_FILE_LOAD = 20100,
MAINFRAME_MENU_ID_FILE_INSTALL_UPDATE,
MAINFRAME_MENU_ID_FILE_OPEN_CEMU_FOLDER,
+ MAINFRAME_MENU_ID_FILE_OPEN_MLC_FOLDER,
MAINFRAME_MENU_ID_FILE_EXIT,
MAINFRAME_MENU_ID_FILE_END_EMULATION,
MAINFRAME_MENU_ID_FILE_RECENT_0,
@@ -166,7 +167,8 @@ EVT_MOVE(MainWindow::OnMove)
// file menu
EVT_MENU(MAINFRAME_MENU_ID_FILE_LOAD, MainWindow::OnFileMenu)
EVT_MENU(MAINFRAME_MENU_ID_FILE_INSTALL_UPDATE, MainWindow::OnInstallUpdate)
-EVT_MENU(MAINFRAME_MENU_ID_FILE_OPEN_CEMU_FOLDER, MainWindow::OnOpenCemuFolder)
+EVT_MENU(MAINFRAME_MENU_ID_FILE_OPEN_CEMU_FOLDER, MainWindow::OnOpenFolder)
+EVT_MENU(MAINFRAME_MENU_ID_FILE_OPEN_MLC_FOLDER, MainWindow::OnOpenFolder)
EVT_MENU(MAINFRAME_MENU_ID_FILE_EXIT, MainWindow::OnFileExit)
EVT_MENU(MAINFRAME_MENU_ID_FILE_END_EMULATION, MainWindow::OnFileMenu)
EVT_MENU_RANGE(MAINFRAME_MENU_ID_FILE_RECENT_0 + 0, MAINFRAME_MENU_ID_FILE_RECENT_LAST, MainWindow::OnFileMenu)
@@ -684,9 +686,12 @@ void MainWindow::OnFileMenu(wxCommandEvent& event)
}
}
-void MainWindow::OnOpenCemuFolder(wxCommandEvent& event)
+void MainWindow::OnOpenFolder(wxCommandEvent& event)
{
- wxLaunchDefaultApplication(wxHelper::FromPath(ActiveSettings::GetUserDataPath()));
+ if(event.GetId() == MAINFRAME_MENU_ID_FILE_OPEN_CEMU_FOLDER)
+ wxLaunchDefaultApplication(wxHelper::FromPath(ActiveSettings::GetUserDataPath()));
+ else if(event.GetId() == MAINFRAME_MENU_ID_FILE_OPEN_MLC_FOLDER)
+ wxLaunchDefaultApplication(wxHelper::FromPath(ActiveSettings::GetMlcPath()));
}
void MainWindow::OnInstallUpdate(wxCommandEvent& event)
@@ -2015,7 +2020,7 @@ public:
, "Faris Leonhart", "MahvZero", "PlaguedGuardian", "Stuffie", "CaptainLester", "Qtech", "Zaurexus", "Leonidas", "Artifesto"
, "Alca259", "SirWestofAsh", "Loli Co.", "The Technical Revolutionary", "MegaYama", "mitori", "Seymordius", "Adrian Josh Cruz", "Manuel Hoenings", "Just A Jabb"
, "pgantonio", "CannonXIII", "Lonewolf00708", "AlexsDesign.com", "NoskLo", "MrSirHaku", "xElite_V AKA William H. Johnson", "Zalnor", "Pig", "James \"SE4LS\"", "DairyOrange", "Horoko Lawrence", "bloodmc", "Officer Jenny", "Quasar", "Postposterous", "Jake Jackson", "Kaydax", "CthePredatorG"
- , "Hengi", "Pyrochaser"};
+ , "Hengi", "Pyrochaser", "luma.x3"};
wxString nameListLeft, nameListRight;
for (size_t i = 0; i < patreonSupporterNames.size(); i++)
@@ -2107,6 +2112,7 @@ void MainWindow::RecreateMenu()
}
m_fileMenu->Append(MAINFRAME_MENU_ID_FILE_OPEN_CEMU_FOLDER, _("&Open Cemu folder"));
+ m_fileMenu->Append(MAINFRAME_MENU_ID_FILE_OPEN_MLC_FOLDER, _("&Open MLC folder"));
m_fileMenu->AppendSeparator();
m_exitMenuItem = m_fileMenu->Append(MAINFRAME_MENU_ID_FILE_EXIT, _("&Exit"));
diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h
index 07189b52..25100b72 100644
--- a/src/gui/MainWindow.h
+++ b/src/gui/MainWindow.h
@@ -92,7 +92,7 @@ public:
void OnMouseWheel(wxMouseEvent& event);
void OnClose(wxCloseEvent& event);
void OnFileMenu(wxCommandEvent& event);
- void OnOpenCemuFolder(wxCommandEvent& event);
+ void OnOpenFolder(wxCommandEvent& event);
void OnLaunchFromFile(wxLaunchGameEvent& event);
void OnInstallUpdate(wxCommandEvent& event);
void OnFileExit(wxCommandEvent& event);
From f58b260cbd566f1f76506246b3b9cd247b1ca511 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Mon, 15 Jan 2024 16:31:59 +0100
Subject: [PATCH 020/319] Fix macos missing dylib file
---
src/CMakeLists.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index de9a6600..b7711018 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -78,7 +78,7 @@ if (MACOS_BUNDLE)
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 © 2023 Cemu Project")
+ set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2024 Cemu Project")
set(MACOSX_BUNDLE_CATEGORY "public.app-category.games")
set(MACOSX_MINIMUM_SYSTEM_VERSION "12.0")
@@ -100,6 +100,9 @@ if (MACOS_BUNDLE)
add_custom_command (TARGET CemuBin POST_BUILD
COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}")
+
+ add_custom_command (TARGET CemuBin POST_BUILD
+ COMMAND bash -c "install_name_tool -change /usr/local/opt/libusb/lib/libusb-1.0.0.dylib @executable_path/../Frameworks/libusb-1.0.0.dylib ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}")
endif()
set_target_properties(CemuBin PROPERTIES
From 7e778042ee0aa053f6daa6a0c23f7ff0c74b5f6e Mon Sep 17 00:00:00 2001
From: Live session user
Date: Mon, 15 Jan 2024 17:46:56 -0800
Subject: [PATCH 021/319] Fix macos missing dylib file
---
CMakeLists.txt | 2 +
dependencies/vcpkg_overlay_ports_mac/.gitkeep | 0
.../libusb/portfile.cmake | 71 +++++++++++++++++++
.../vcpkg_overlay_ports_mac/libusb/usage | 5 ++
.../vcpkg_overlay_ports_mac/libusb/vcpkg.json | 8 +++
src/CMakeLists.txt | 11 ++-
6 files changed, 90 insertions(+), 7 deletions(-)
create mode 100644 dependencies/vcpkg_overlay_ports_mac/.gitkeep
create mode 100644 dependencies/vcpkg_overlay_ports_mac/libusb/portfile.cmake
create mode 100644 dependencies/vcpkg_overlay_ports_mac/libusb/usage
create mode 100644 dependencies/vcpkg_overlay_ports_mac/libusb/vcpkg.json
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c988508c..ec6abedc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,6 +19,8 @@ endif()
if (ENABLE_VCPKG)
if(UNIX AND NOT APPLE)
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_linux")
+ elseif(APPLE)
+ set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_mac")
else()
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports")
endif()
diff --git a/dependencies/vcpkg_overlay_ports_mac/.gitkeep b/dependencies/vcpkg_overlay_ports_mac/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/dependencies/vcpkg_overlay_ports_mac/libusb/portfile.cmake b/dependencies/vcpkg_overlay_ports_mac/libusb/portfile.cmake
new file mode 100644
index 00000000..7b76bba0
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_mac/libusb/portfile.cmake
@@ -0,0 +1,71 @@
+set(VCPKG_LIBRARY_LINKAGE dynamic)
+
+if(VCPKG_TARGET_IS_LINUX)
+ message("${PORT} currently requires the following tools and libraries from the system package manager:\n autoreconf\n libudev\n\nThese can be installed on Ubuntu systems via apt-get install autoconf libudev-dev")
+endif()
+
+set(VERSION 1.0.26)
+vcpkg_from_github(
+ OUT_SOURCE_PATH SOURCE_PATH
+ REPO libusb/libusb
+ REF fcf0c710ef5911ae37fbbf1b39d48a89f6f14e8a # v1.0.26.11791 2023-03-12
+ SHA512 0aa6439f7988487adf2a3bff473fec80b5c722a47f117a60696d2aa25c87cc3f20fb6aaca7c66e49be25db6a35eb0bb5f71ed7b211d1b8ee064c5d7f1b985c73
+ HEAD_REF master
+)
+
+if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
+
+ if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic")
+ set(LIBUSB_PROJECT_TYPE dll)
+ else()
+ set(LIBUSB_PROJECT_TYPE static)
+ endif()
+
+ # The README.md file in the archive is a symlink to README
+ # which causes issues with the windows MSBUILD process
+ file(REMOVE "${SOURCE_PATH}/README.md")
+
+ vcpkg_msbuild_install(
+ SOURCE_PATH "${SOURCE_PATH}"
+ PROJECT_SUBPATH msvc/libusb_${LIBUSB_PROJECT_TYPE}.vcxproj
+ )
+
+ file(INSTALL "${SOURCE_PATH}/libusb/libusb.h" DESTINATION "${CURRENT_PACKAGES_DIR}/include/libusb-1.0")
+ set(prefix "")
+ set(exec_prefix [[${prefix}]])
+ set(libdir [[${prefix}/lib]])
+ set(includedir [[${prefix}/include]])
+ configure_file("${SOURCE_PATH}/libusb-1.0.pc.in" "${CURRENT_PACKAGES_DIR}/lib/pkgconfig/libusb-1.0.pc" @ONLY)
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/libusb-1.0.pc" " -lusb-1.0" " -llibusb-1.0")
+ if(NOT VCPKG_BUILD_TYPE)
+ set(includedir [[${prefix}/../include]])
+ configure_file("${SOURCE_PATH}/libusb-1.0.pc.in" "${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libusb-1.0.pc" @ONLY)
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libusb-1.0.pc" " -lusb-1.0" " -llibusb-1.0")
+ endif()
+else()
+ vcpkg_list(SET MAKE_OPTIONS)
+ vcpkg_list(SET LIBUSB_LINK_LIBRARIES)
+ if(VCPKG_TARGET_IS_EMSCRIPTEN)
+ vcpkg_list(APPEND MAKE_OPTIONS BUILD_TRIPLET --host=wasm32)
+ endif()
+ if("udev" IN_LIST FEATURES)
+ vcpkg_list(APPEND MAKE_OPTIONS "--enable-udev")
+ vcpkg_list(APPEND LIBUSB_LINK_LIBRARIES udev)
+ else()
+ vcpkg_list(APPEND MAKE_OPTIONS "--disable-udev")
+ endif()
+ vcpkg_configure_make(
+ SOURCE_PATH "${SOURCE_PATH}"
+ AUTOCONFIG
+ OPTIONS
+ ${MAKE_OPTIONS}
+ "--enable-examples-build=no"
+ "--enable-tests-build=no"
+ )
+ vcpkg_install_make()
+endif()
+
+vcpkg_fixup_pkgconfig()
+
+file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
+vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/COPYING")
diff --git a/dependencies/vcpkg_overlay_ports_mac/libusb/usage b/dependencies/vcpkg_overlay_ports_mac/libusb/usage
new file mode 100644
index 00000000..87e6e860
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_mac/libusb/usage
@@ -0,0 +1,5 @@
+libusb can be imported via CMake FindPkgConfig module:
+ find_package(PkgConfig REQUIRED)
+ pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0)
+
+ target_link_libraries(main PRIVATE PkgConfig::libusb)
diff --git a/dependencies/vcpkg_overlay_ports_mac/libusb/vcpkg.json b/dependencies/vcpkg_overlay_ports_mac/libusb/vcpkg.json
new file mode 100644
index 00000000..efc70f3d
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_mac/libusb/vcpkg.json
@@ -0,0 +1,8 @@
+{
+ "name": "libusb",
+ "version": "1.0.26.11791",
+ "port-version": 7,
+ "description": "a cross-platform library to access USB devices",
+ "homepage": "https://github.com/libusb/libusb",
+ "license": "LGPL-2.1-or-later"
+}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b7711018..7442e37c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -96,13 +96,10 @@ if (MACOS_BUNDLE)
endforeach(folder)
add_custom_command (TARGET CemuBin POST_BUILD
- COMMAND ${CMAKE_COMMAND} ARGS -E copy "/usr/local/lib/libMoltenVK.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib")
-
- add_custom_command (TARGET CemuBin POST_BUILD
- COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}")
-
- add_custom_command (TARGET CemuBin POST_BUILD
- COMMAND bash -c "install_name_tool -change /usr/local/opt/libusb/lib/libusb-1.0.0.dylib @executable_path/../Frameworks/libusb-1.0.0.dylib ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}")
+ COMMAND ${CMAKE_COMMAND} ARGS -E copy "/usr/local/lib/libMoltenVK.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libMoltenVK.dylib"
+ COMMAND ${CMAKE_COMMAND} ARGS -E copy "${CMAKE_BINARY_DIR}/vcpkg_installed/x64-osx/lib/libusb-1.0.0.dylib" "${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/Frameworks/libusb-1.0.0.dylib"
+ COMMAND bash -c "install_name_tool -add_rpath @executable_path/../Frameworks ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}"
+ COMMAND bash -c "install_name_tool -change /usr/local/opt/libusb/lib/libusb-1.0.0.dylib @executable_path/../Frameworks/libusb-1.0.0.dylib ${CMAKE_SOURCE_DIR}/bin/${OUTPUT_NAME}.app/Contents/MacOS/${OUTPUT_NAME}")
endif()
set_target_properties(CemuBin PROPERTIES
From f899ab7c34035bc3746112b6459bd15a4a181dd4 Mon Sep 17 00:00:00 2001
From: Colin Kinloch
Date: Wed, 17 Jan 2024 01:09:56 +0000
Subject: [PATCH 022/319] Vulkan: Check for 0 size before wayland resize
Fixes "Launching games directly with the --title-id argument doesn't work
in Wayland" (#999)
---
src/gui/canvas/VulkanCanvas.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/gui/canvas/VulkanCanvas.cpp b/src/gui/canvas/VulkanCanvas.cpp
index eb56b3c4..8b0c8506 100644
--- a/src/gui/canvas/VulkanCanvas.cpp
+++ b/src/gui/canvas/VulkanCanvas.cpp
@@ -66,6 +66,10 @@ void VulkanCanvas::OnPaint(wxPaintEvent& event)
void VulkanCanvas::OnResize(wxSizeEvent& event)
{
+ const wxSize size = GetSize();
+ if (size.GetWidth() == 0 || size.GetHeight() == 0)
+ return;
+
#if BOOST_OS_LINUX && HAS_WAYLAND
if(m_subsurface)
{
@@ -73,9 +77,6 @@ void VulkanCanvas::OnResize(wxSizeEvent& event)
m_subsurface->setSize(sRect.GetX(), sRect.GetY(), sRect.GetWidth(), sRect.GetHeight());
}
#endif
- const wxSize size = GetSize();
- if (size.GetWidth() == 0 || size.GetHeight() == 0)
- return;
const wxRect refreshRect(size);
RefreshRect(refreshRect, false);
From e53c63b828e856cb4bf11729cdf90fe12544ac9f Mon Sep 17 00:00:00 2001
From: Colin Kinloch
Date: Wed, 17 Jan 2024 01:18:07 +0000
Subject: [PATCH 023/319] Flatpak: Create shortcuts that launch flatpak
---
src/gui/components/wxGameList.cpp | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/gui/components/wxGameList.cpp b/src/gui/components/wxGameList.cpp
index 2c78ea3c..5ceaf71f 100644
--- a/src/gui/components/wxGameList.cpp
+++ b/src/gui/components/wxGameList.cpp
@@ -1235,6 +1235,7 @@ void wxGameList::CreateShortcut(GameInfo2& gameInfo) {
const auto title_id = gameInfo.GetBaseTitleId();
const auto title_name = gameInfo.GetTitleName();
auto exe_path = ActiveSettings::GetExecutablePath();
+ const char *flatpak_id = getenv("FLATPAK_ID");
// GetExecutablePath returns the AppImage's temporary mount location, instead of its actual path
wxString appimage_path;
@@ -1292,22 +1293,31 @@ void wxGameList::CreateShortcut(GameInfo2& gameInfo) {
}
}
}
+
+ std::string desktop_exec_entry;
+ if (flatpak_id)
+ desktop_exec_entry = fmt::format("/usr/bin/flatpak run {0} --title-id {1:016x}", flatpak_id, title_id);
+ else
+ desktop_exec_entry = fmt::format("{0:?} --title-id {1:016x}", _pathToUtf8(exe_path), title_id);
+
// 'Icon' accepts spaces in file name, does not accept quoted file paths
// 'Exec' does not accept non-escaped spaces, and can accept quoted file paths
- const auto desktop_entry_string =
+ auto desktop_entry_string =
fmt::format("[Desktop Entry]\n"
"Name={0}\n"
"Comment=Play {0} on Cemu\n"
- "Exec={1:?} --title-id {2:016x}\n"
- "Icon={3}\n"
+ "Exec={1}\n"
+ "Icon={2}\n"
"Terminal=false\n"
"Type=Application\n"
- "Categories=Game;",
+ "Categories=Game;\n",
title_name,
- _pathToUtf8(exe_path),
- title_id,
+ desktop_exec_entry,
_pathToUtf8(icon_path.value_or("")));
+ if (flatpak_id)
+ desktop_entry_string += fmt::format("X-Flatpak={}\n", flatpak_id);
+
std::ofstream output_stream(output_path);
if (!output_stream.good())
{
From 72aacbdcecc064ea7c3b158c433e4803496ac296 Mon Sep 17 00:00:00 2001
From: Mike Lothian
Date: Fri, 19 Jan 2024 01:03:57 +0000
Subject: [PATCH 024/319] Vulkan: Don't use glslang internal headers
Signed-off-by: Mike Lothian
---
src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp | 3 +--
src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp
index e9936c43..72a1be4c 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp
@@ -3,7 +3,6 @@
#include "Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h"
-#include
#include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h"
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
@@ -91,4 +90,4 @@ PipelineInfo::~PipelineInfo()
// remove from cache
VulkanRenderer::GetInstance()->unregisterGraphicsPipeline(this);
-}
\ No newline at end of file
+}
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index 44214606..616f57e2 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -26,7 +26,7 @@
#include "Cafe/HW/Latte/Core/LatteTiming.h" // vsync control
-#include
+#include
#include
From 18679af4ec641a4c59753d54751dcab257777eef Mon Sep 17 00:00:00 2001
From: capitalistspz
Date: Fri, 19 Jan 2024 14:07:17 +0000
Subject: [PATCH 025/319] Ignore Wii U pro controller
---
src/input/api/Wiimote/hidapi/HidapiWiimote.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp
index a5701f56..db185675 100644
--- a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp
+++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp
@@ -1,9 +1,11 @@
#include "HidapiWiimote.h"
+#include
static constexpr uint16 WIIMOTE_VENDOR_ID = 0x057e;
static constexpr uint16 WIIMOTE_PRODUCT_ID = 0x0306;
static constexpr uint16 WIIMOTE_MP_PRODUCT_ID = 0x0330;
static constexpr uint16 WIIMOTE_MAX_INPUT_REPORT_LENGTH = 22;
+static constexpr auto PRO_CONTROLLER_NAME = L"Nintendo RVL-CNT-01-UC";
HidapiWiimote::HidapiWiimote(hid_device* dev, std::string_view path)
: m_handle(dev), m_path(path) {
@@ -30,6 +32,8 @@ std::vector HidapiWiimote::get_devices() {
for (auto it = device_enumeration; it != nullptr; it = it->next){
if (it->product_id != WIIMOTE_PRODUCT_ID && it->product_id != WIIMOTE_MP_PRODUCT_ID)
continue;
+ if (std::wcscmp(it->product_string, PRO_CONTROLLER_NAME) == 0)
+ continue;
auto dev = hid_open_path(it->path);
if (!dev){
cemuLog_logDebug(LogType::Force, "Unable to open Wiimote device at {}: {}", it->path, boost::nowide::narrow(hid_error(nullptr)));
From 4e4ac0de51b82c455aec71060c109f9e5a1888d9 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Fri, 19 Jan 2024 23:32:24 +0100
Subject: [PATCH 026/319] CI: For the Windows build use as many cores as
available
---
.github/workflows/build.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d23faa31..3c01ba7a 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -183,7 +183,7 @@ jobs:
- name: "Build Cemu"
run: |
cd build
- cmake --build . --config ${{ env.BUILD_MODE }} -j 2
+ cmake --build . --config ${{ env.BUILD_MODE }}
- name: Prepare artifact
if: ${{ inputs.deploymode == 'release' }}
From ca01e923bf03573d5023feb0f4464ce015910ea6 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Sat, 20 Jan 2024 00:33:36 +0100
Subject: [PATCH 027/319] Update issue templates
---
.../bug-report-feature-request.md | 34 ---------
.github/ISSUE_TEMPLATE/config.yml | 2 +-
.../ISSUE_TEMPLATE/emulation_bug_report.yaml | 69 +++++++++++++++++++
.github/ISSUE_TEMPLATE/feature_report.yaml | 28 ++++++++
4 files changed, 98 insertions(+), 35 deletions(-)
delete mode 100644 .github/ISSUE_TEMPLATE/bug-report-feature-request.md
create mode 100644 .github/ISSUE_TEMPLATE/emulation_bug_report.yaml
create mode 100644 .github/ISSUE_TEMPLATE/feature_report.yaml
diff --git a/.github/ISSUE_TEMPLATE/bug-report-feature-request.md b/.github/ISSUE_TEMPLATE/bug-report-feature-request.md
deleted file mode 100644
index 61bd5d06..00000000
--- a/.github/ISSUE_TEMPLATE/bug-report-feature-request.md
+++ /dev/null
@@ -1,34 +0,0 @@
----
-name: Bug Report / Feature Request
-about: Tech support does not belong here. You should only file an issue here if you think you have experienced an actual bug with Cemu or you are requesting a feature you believe would make Cemu better.
-title: ''
-labels: ''
-assignees: ''
-
----
-
-
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index d33d87ed..d71e22d0 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -2,4 +2,4 @@ blank_issues_enabled: false
contact_links:
- name: Cemu Discord
url: https://discord.com/invite/5psYsup
- about: If you are experiencing an issue with Cemu, and you need tech support, or if you have a general question, try asking in the official Cemu Discord linked here. Piracy is not allowed.
+ about: If you need technical support with Cemu or have other questions the best place to ask is on the official Cemu Discord linked here
diff --git a/.github/ISSUE_TEMPLATE/emulation_bug_report.yaml b/.github/ISSUE_TEMPLATE/emulation_bug_report.yaml
new file mode 100644
index 00000000..75928607
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/emulation_bug_report.yaml
@@ -0,0 +1,69 @@
+# Docs - https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
+name: Bug Report
+description: Report an issue with Cemu emulator
+title: "Enter a title for the bug report here"
+labels: bug
+body:
+ - type: markdown
+ id: md_readme
+ attributes:
+ value: |
+ ## Important: Read First
+
+ If you discovered a bug you can report it here. Please make sure of the following first:
+ - That you are using the latest version of Cemu
+ - Only report something if you are sure it's a bug and not any technical issue on your end. For troubleshooting help see the [links page](https://github.com/cemu-project/Cemu#links)
+ - Problems specific to a single game should be reported on the [compatibility wiki](https://wiki.cemu.info/wiki/Main_Page) instead
+ - Verify that your problem isn't already mentioned on the [issue tracker](https://github.com/cemu-project/Cemu/issues)
+
+ Additionally, be aware that graphic packs can also causes issues. There is a separate issue tracker for graphic pack bugs over at the [graphic pack repository](https://github.com/cemu-project/cemu_graphic_packs)
+ - type: textarea
+ id: current_behavior
+ attributes:
+ label: Current Behavior
+ description: "What the bug is, in a brief description"
+ validations:
+ required: true
+ - type: textarea
+ id: expected_behavior
+ attributes:
+ label: Expected Behavior
+ description: "What did you expect to happen?"
+ validations:
+ required: true
+
+ - type: textarea
+ id: steps_to_reproduce
+ attributes:
+ label: Steps to Reproduce
+ description: "How to reproduce the issue"
+ validations:
+ required: true
+ - type: textarea
+ id: sys_info
+ attributes:
+ label: System Info (Optional)
+ description: "Your PC specifications. Usually only the operating system and graphics card is important. But feel free to add more info."
+ placeholder: |
+ Info
+ OS: Windows 10
+ GPU: NVIDIA GeForce RTX 4090
+ value: |
+ OS:
+ GPU:
+ - type: textarea
+ id: emulation_settings
+ attributes:
+ label: Emulation Settings (Optional)
+ description: |
+ Any non-default settings. You can leave this empty if you didn't change anything other than input settings.
+ validations:
+ required: false
+ - type: textarea
+ id: logs_files
+ attributes:
+ label: "Logs (Optional)"
+ description: |
+ "Attach `log.txt` from your Cemu folder (*File > Open Cemu folder*)".
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/feature_report.yaml b/.github/ISSUE_TEMPLATE/feature_report.yaml
new file mode 100644
index 00000000..a5d8705c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_report.yaml
@@ -0,0 +1,28 @@
+# Docs - https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
+name: Feature suggestion
+description: Suggest a new feature
+title: "Enter a title for the suggestion here"
+labels: feature request
+body:
+ - type: markdown
+ id: md_readme
+ attributes:
+ value: |
+ ## Important: Read First
+
+ While we appreciate suggestions, it is important to note that we are a very small team and there are already many more ideas than we could ever implement in the near future. Therefore, please only suggest something if you believe it is a great addition and the idea is reasonably unique.
+
+ *Avoid* to create suggestions for:
+ - Overly obvious features ("Game xyz does not work and should be fixed", "Wiimote support should be improved", "You should add an Android port", "Copy feature xyz from another emulator", "A button to pause/stop emulation")
+ - Niche features which are only interesting to a tiny percentage of users
+ - Large scale features ("Add a Metal backend for MacOS", "Add ARM support", "Add savestates")
+
+ Note that this doesn't mean we aren't interested in these ideas, but rather we likely have them planned anyway and it's mostly up to finding the time to implement them.
+ If you believe your idea is worthwhile even if it doesn't meet all the criteria above, you can still try suggesting it but we might close it.
+ - type: textarea
+ id: idea_suggestion
+ attributes:
+ label: Your suggestion
+ description: "Describe what your suggestion is in as much detail as possible"
+ validations:
+ required: true
From 81acd80a97faa3905d27ad170f16244e17581d2d Mon Sep 17 00:00:00 2001
From: Squall Leonhart
Date: Sun, 18 Feb 2024 15:51:00 +1100
Subject: [PATCH 028/319] Cubeb: Add a default device to the selection (#1017)
---
src/audio/CubebAPI.cpp | 13 +++++++++----
src/audio/CubebInputAPI.cpp | 13 +++++++++----
2 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/src/audio/CubebAPI.cpp b/src/audio/CubebAPI.cpp
index 09e45011..2b4aec41 100644
--- a/src/audio/CubebAPI.cpp
+++ b/src/audio/CubebAPI.cpp
@@ -188,15 +188,20 @@ std::vector CubebAPI::GetDevices()
return {};
std::vector result;
- result.reserve(devices.count);
+ result.reserve(devices.count + 1); // Reserve space for the default device
+
+ // Add the default device to the list
+ auto defaultDevice = std::make_shared(nullptr, "default", L"Default Device");
+ result.emplace_back(defaultDevice);
+
for (size_t i = 0; i < devices.count; ++i)
{
- //const auto& device = devices.device[i];
+ // const auto& device = devices.device[i];
if (devices.device[i].state == CUBEB_DEVICE_STATE_ENABLED)
{
auto device = std::make_shared(devices.device[i].devid, devices.device[i].device_id,
- boost::nowide::widen(
- devices.device[i].friendly_name));
+ boost::nowide::widen(
+ devices.device[i].friendly_name));
result.emplace_back(device);
}
}
diff --git a/src/audio/CubebInputAPI.cpp b/src/audio/CubebInputAPI.cpp
index de030fdc..c0fa73f4 100644
--- a/src/audio/CubebInputAPI.cpp
+++ b/src/audio/CubebInputAPI.cpp
@@ -180,15 +180,20 @@ std::vector CubebInputAPI::GetDevices()
return {};
std::vector result;
- result.reserve(devices.count);
+ result.reserve(devices.count + 1); // Reserve space for the default device
+
+ // Add the default device to the list
+ auto defaultDevice = std::make_shared(nullptr, "default", L"Default Device");
+ result.emplace_back(defaultDevice);
+
for (size_t i = 0; i < devices.count; ++i)
{
- //const auto& device = devices.device[i];
+ // const auto& device = devices.device[i];
if (devices.device[i].state == CUBEB_DEVICE_STATE_ENABLED)
{
auto device = std::make_shared(devices.device[i].devid, devices.device[i].device_id,
- boost::nowide::widen(
- devices.device[i].friendly_name));
+ boost::nowide::widen(
+ devices.device[i].friendly_name));
result.emplace_back(device);
}
}
From 6a08d04af9c22d2b6ec432b9ac48a299abcfb9f8 Mon Sep 17 00:00:00 2001
From: Squall Leonhart
Date: Sun, 18 Feb 2024 15:52:11 +1100
Subject: [PATCH 029/319] UI: Make Alt+F4/Ctrl+Q more reliable (#1035)
---
src/gui/MainWindow.cpp | 14 ++++++++++++++
src/gui/MainWindow.h | 1 +
2 files changed, 15 insertions(+)
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index dc9ff0a8..d271ca3a 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -1485,6 +1485,19 @@ void MainWindow::OnKeyUp(wxKeyEvent& event)
g_window_info.has_screenshot_request = true; // async screenshot request
}
+void MainWindow::OnKeyDown(wxKeyEvent& event)
+{
+ if ((event.AltDown() && event.GetKeyCode() == WXK_F4) ||
+ (event.CmdDown() && event.GetKeyCode() == 'Q'))
+ {
+ Close(true);
+ }
+ else
+ {
+ event.Skip();
+ }
+}
+
void MainWindow::OnChar(wxKeyEvent& event)
{
if (swkbd_hasKeyboardInputHook())
@@ -1590,6 +1603,7 @@ void MainWindow::CreateCanvas()
// key events
m_render_canvas->Bind(wxEVT_KEY_UP, &MainWindow::OnKeyUp, this);
+ m_render_canvas->Bind(wxEVT_KEY_DOWN, &MainWindow::OnKeyDown, this);
m_render_canvas->Bind(wxEVT_CHAR, &MainWindow::OnChar, this);
m_render_canvas->SetDropTarget(new wxAmiiboDropTarget(this));
diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h
index 25100b72..88d2a1d3 100644
--- a/src/gui/MainWindow.h
+++ b/src/gui/MainWindow.h
@@ -124,6 +124,7 @@ public:
void OnSetWindowTitle(wxCommandEvent& event);
void OnKeyUp(wxKeyEvent& event);
+ void OnKeyDown(wxKeyEvent& event);
void OnChar(wxKeyEvent& event);
void OnToolsInput(wxCommandEvent& event);
From 9bbb7c8b97ff6e5a080984c818b1e66b0f2ce609 Mon Sep 17 00:00:00 2001
From: Steveice10 <1269164+Steveice10@users.noreply.github.com>
Date: Sat, 17 Feb 2024 20:54:41 -0800
Subject: [PATCH 030/319] Add support for portable directory without build flag
(#1071)
---
.github/workflows/build.yml | 3 +-
CMakeLists.txt | 5 ----
src/gui/CemuApp.cpp | 59 ++++++++++++++++++++++---------------
3 files changed, 36 insertions(+), 31 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 3c01ba7a..00aac0fe 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -75,7 +75,7 @@ jobs:
- name: "cmake"
run: |
- cmake -S . -B build ${{ env.BUILD_FLAGS }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} -DPORTABLE=OFF -DCMAKE_C_COMPILER=/usr/bin/clang-15 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-15 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja
+ cmake -S . -B build ${{ env.BUILD_FLAGS }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} -DCMAKE_C_COMPILER=/usr/bin/clang-15 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-15 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja
- name: "Build Cemu"
run: |
@@ -258,7 +258,6 @@ jobs:
cd build
cmake .. ${{ env.BUILD_FLAGS }} \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} \
- -DPORTABLE=OFF \
-DMACOS_BUNDLE=ON \
-DCMAKE_C_COMPILER=/usr/local/opt/llvm@15/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@15/bin/clang++ \
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ec6abedc..6b5f3881 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,6 @@
cmake_minimum_required(VERSION 3.21.1)
option(ENABLE_VCPKG "Enable the vcpkg package manager" ON)
-option(PORTABLE "All data created and maintained by Cemu will be in the directory where the executable file is located" ON)
option(MACOS_BUNDLE "The executable when built on macOS will be created as an application bundle" OFF)
set(EXPERIMENTAL_VERSION "" CACHE STRING "") # used by CI script to set experimental version
@@ -45,10 +44,6 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_compile_definitions($<$:CEMU_DEBUG_ASSERT>) # if build type is debug, set CEMU_DEBUG_ASSERT
-if(PORTABLE)
- add_compile_definitions(PORTABLE)
-endif()
-
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# enable link time optimization for release builds
diff --git a/src/gui/CemuApp.cpp b/src/gui/CemuApp.cpp
index 4acc1cf5..fde4bcc0 100644
--- a/src/gui/CemuApp.cpp
+++ b/src/gui/CemuApp.cpp
@@ -59,33 +59,44 @@ bool CemuApp::OnInit()
fs::path user_data_path, config_path, cache_path, data_path;
auto standardPaths = wxStandardPaths::Get();
fs::path exePath(wxHelper::MakeFSPath(standardPaths.GetExecutablePath()));
-#ifdef PORTABLE
-#if MACOS_BUNDLE
- exePath = exePath.parent_path().parent_path().parent_path();
+
+ // Try a portable path first, if it exists.
+ user_data_path = config_path = cache_path = data_path = exePath.parent_path() / "portable";
+#if BOOST_OS_MACOS
+ // If run from an app bundle, use its parent directory.
+ fs::path appPath = exePath.parent_path().parent_path().parent_path();
+ if (appPath.extension() == ".app")
+ user_data_path = config_path = cache_path = data_path = appPath.parent_path() / "portable";
#endif
- user_data_path = config_path = cache_path = data_path = exePath.parent_path();
-#else
- SetAppName("Cemu");
- wxString appName=GetAppName();
- #if BOOST_OS_LINUX
- standardPaths.SetFileLayout(wxStandardPaths::FileLayout::FileLayout_XDG);
- auto getEnvDir = [&](const wxString& varName, const wxString& defaultValue)
+
+ if (!fs::exists(user_data_path))
{
- wxString dir;
- if (!wxGetEnv(varName, &dir) || dir.empty())
- return defaultValue;
- return dir;
- };
- wxString homeDir=wxFileName::GetHomeDir();
- user_data_path = (getEnvDir(wxS("XDG_DATA_HOME"), homeDir + wxS("/.local/share")) + "/" + appName).ToStdString();
- config_path = (getEnvDir(wxS("XDG_CONFIG_HOME"), homeDir + wxS("/.config")) + "/" + appName).ToStdString();
- #else
- user_data_path = config_path = standardPaths.GetUserDataDir().ToStdString();
- #endif
- data_path = standardPaths.GetDataDir().ToStdString();
- cache_path = standardPaths.GetUserDir(wxStandardPaths::Dir::Dir_Cache).ToStdString();
- cache_path /= appName.ToStdString();
+#if BOOST_OS_WINDOWS
+ user_data_path = config_path = cache_path = data_path = exePath.parent_path();
+#else
+ SetAppName("Cemu");
+ wxString appName=GetAppName();
+#if BOOST_OS_LINUX
+ standardPaths.SetFileLayout(wxStandardPaths::FileLayout::FileLayout_XDG);
+ auto getEnvDir = [&](const wxString& varName, const wxString& defaultValue)
+ {
+ wxString dir;
+ if (!wxGetEnv(varName, &dir) || dir.empty())
+ return defaultValue;
+ return dir;
+ };
+ wxString homeDir=wxFileName::GetHomeDir();
+ user_data_path = (getEnvDir(wxS("XDG_DATA_HOME"), homeDir + wxS("/.local/share")) + "/" + appName).ToStdString();
+ config_path = (getEnvDir(wxS("XDG_CONFIG_HOME"), homeDir + wxS("/.config")) + "/" + appName).ToStdString();
+#else
+ user_data_path = config_path = standardPaths.GetUserDataDir().ToStdString();
#endif
+ data_path = standardPaths.GetDataDir().ToStdString();
+ cache_path = standardPaths.GetUserDir(wxStandardPaths::Dir::Dir_Cache).ToStdString();
+ cache_path /= appName.ToStdString();
+#endif
+ }
+
auto failed_write_access = ActiveSettings::LoadOnce(exePath, user_data_path, config_path, cache_path, data_path);
for (auto&& path : failed_write_access)
wxMessageBox(formatWxString(_("Cemu can't write to {}!"), wxString::FromUTF8(_pathToUtf8(path))),
From ed01eaf5f949847d8be16d271abdeafe901e3971 Mon Sep 17 00:00:00 2001
From: capitalistspz
Date: Sun, 18 Feb 2024 04:56:36 +0000
Subject: [PATCH 031/319] Gamelist: Add right-click actions for copying title
ID, name, and icon (#1089)
---
src/gui/components/wxGameList.cpp | 51 +++++++++++++++++++++++++++++--
1 file changed, 48 insertions(+), 3 deletions(-)
diff --git a/src/gui/components/wxGameList.cpp b/src/gui/components/wxGameList.cpp
index 5ceaf71f..88934cd8 100644
--- a/src/gui/components/wxGameList.cpp
+++ b/src/gui/components/wxGameList.cpp
@@ -17,6 +17,8 @@
#include
#include
#include
+#include
+
#include
#include
@@ -546,7 +548,12 @@ enum ContextMenuEntries
kContextMenuStyleList,
kContextMenuStyleIcon,
kContextMenuStyleIconSmall,
- kContextMenuCreateShortcut
+
+ kContextMenuCreateShortcut,
+
+ kContextMenuCopyTitleName,
+ kContextMenuCopyTitleId,
+ kContextMenuCopyTitleImage
};
void wxGameList::OnContextMenu(wxContextMenuEvent& event)
{
@@ -591,6 +598,10 @@ void wxGameList::OnContextMenu(wxContextMenuEvent& event)
#if BOOST_OS_LINUX || BOOST_OS_WINDOWS
menu.Append(kContextMenuCreateShortcut, _("&Create shortcut"));
#endif
+ menu.AppendSeparator();
+ menu.Append(kContextMenuCopyTitleName, _("&Copy Title Name"));
+ menu.Append(kContextMenuCopyTitleId, _("&Copy Title ID"));
+ menu.Append(kContextMenuCopyTitleImage, _("&Copy Title Image"));
menu.AppendSeparator();
}
}
@@ -711,10 +722,44 @@ void wxGameList::OnContextMenuSelected(wxCommandEvent& event)
break;
}
case kContextMenuCreateShortcut:
+ {
#if BOOST_OS_LINUX || BOOST_OS_WINDOWS
- CreateShortcut(gameInfo);
+ CreateShortcut(gameInfo);
#endif
break;
+ }
+ case kContextMenuCopyTitleName:
+ {
+ if (wxTheClipboard->Open())
+ {
+ wxTheClipboard->SetData(new wxTextDataObject(gameInfo.GetTitleName()));
+ wxTheClipboard->Close();
+ }
+ break;
+ }
+ case kContextMenuCopyTitleId:
+ {
+ if (wxTheClipboard->Open())
+ {
+ wxTheClipboard->SetData(new wxTextDataObject(fmt::format("{:016x}", gameInfo.GetBaseTitleId())));
+ wxTheClipboard->Close();
+ }
+ break;
+ }
+ case kContextMenuCopyTitleImage:
+ {
+ if (wxTheClipboard->Open())
+ {
+ int icon_large;
+ int icon_small;
+ if (!QueryIconForTitle(title_id, icon_large, icon_small))
+ break;
+ auto icon = m_image_list->GetBitmap(icon_large);
+ wxTheClipboard->SetData(new wxBitmapDataObject(icon));
+ wxTheClipboard->Close();
+ }
+ break;
+ }
}
}
}
@@ -1042,7 +1087,7 @@ void wxGameList::OnGameEntryUpdatedByTitleId(wxTitleIdEvent& event)
const auto region_text = fmt::format("{}", gameInfo.GetRegion());
SetItem(index, ColumnRegion, wxGetTranslation(region_text));
- SetItem(index, ColumnTitleID, fmt::format("{:016x}", titleId));
+ SetItem(index, ColumnTitleID, fmt::format("{:016x}", baseTitleId));
}
else if (m_style == Style::kIcons)
{
From 8d7fc98275f3eae1f2e105df678956b7540e65eb Mon Sep 17 00:00:00 2001
From: rawdatafeel <108900299+rawdatafeel@users.noreply.github.com>
Date: Sat, 17 Feb 2024 23:59:00 -0500
Subject: [PATCH 032/319] Improve BUILD.md (#1093)
---
BUILD.md | 153 +++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 114 insertions(+), 39 deletions(-)
diff --git a/BUILD.md b/BUILD.md
index e4993ca1..034000ac 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -1,4 +1,26 @@
-# Build instructions
+# Build Instructions
+
+## Table of Contents
+
+- [Windows](#windows)
+- [Linux](#linux)
+ - [Dependencies](#dependencies)
+ - [For Arch and derivatives:](#for-arch-and-derivatives)
+ - [For Fedora and derivatives:](#for-fedora-and-derivatives)
+ - [For Ubuntu and derivatives](#for-ubuntu-and-derivatives)
+ - [Build Cemu](#build-cemu)
+ - [CMake and Clang](#cmake-and-clang)
+ - [GCC](#gcc)
+ - [Debug Build](#debug-build)
+ - [Troubleshooting Steps](#troubleshooting-steps)
+ - [Compiling Errors](#compiling-errors)
+ - [Building Errors](#building-errors)
+- [macOS](#macos)
+ - [On Apple Silicon Macs, Rosetta 2 and the x86_64 version of Homebrew must be used](#on-apple-silicon-macs-rosetta-2-and-the-x86_64-version-of-homebrew-must-be-used)
+ - [Installing brew](#installing-brew)
+ - [Installing Dependencies](#installing-dependencies)
+ - [Build Cemu using CMake and Clang](#build-cemu-using-cmake-and-clang)
+ - [Updating Cemu and source code](#updating-cemu-and-source-code)
## Windows
@@ -19,17 +41,9 @@ Any other IDE should also work as long as it has CMake and MSVC support. CLion a
## Linux
-To compile Cemu, a recent enough compiler and STL with C++20 support is required! clang-15 or higher is what we recommend.
+To compile Cemu, a recent enough compiler and STL with C++20 support is required! Clang-15 or higher is what we recommend.
-### Installing dependencies
-
-#### For Ubuntu and derivatives:
-`sudo apt install -y cmake curl clang-15 freeglut3-dev git libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build`
-
-You may also need to install `libusb-1.0-0-dev` as a workaround for an issue with the vcpkg hidapi package.
-
-At step 3 while building, use:
- `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang-15 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-15 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja`
+### Dependencies
#### For Arch and derivatives:
`sudo pacman -S --needed base-devel clang cmake freeglut git glm gtk3 libgcrypt libpulse libsecret linux-headers llvm nasm ninja systemd unzip zip`
@@ -37,39 +51,99 @@ At step 3 while building, use:
#### For Fedora and derivatives:
`sudo dnf install clang cmake cubeb-devel freeglut-devel git glm-devel gtk3-devel kernel-headers libgcrypt-devel libsecret-devel libtool libusb1-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`
-2. `cd Cemu`
-3. `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -G Ninja`
-4. `cmake --build build`
-5. You should now have a Cemu executable file in the /bin folder, which you can run using `./bin/Cemu_release`.
+#### For Ubuntu and derivatives:
+`sudo apt install -y cmake curl clang-15 freeglut3-dev git libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libtool nasm ninja-build`
-#### Using GCC
-While we build and test Cemu using clang, using GCC might work better with your distro (they should be fairly similar performance/issues wise and should only be considered if compilation is the issue).
+You may also need to install `libusb-1.0-0-dev` as a workaround for an issue with the vcpkg hidapi package.
-You can use GCC by doing the following:
-- make sure you have g++ installed in your system
- - installation for Ubuntu and derivatives: `sudo apt install g++`
- - installation for Fedora and derivatives: `sudo dnf install gcc-c++`
-- replace the step 3 with the following:
-`cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/gcc -DCMAKE_CXX_COMPILER=/usr/bin/g++ -G Ninja`
+At Step 3 in [Build Cemu using cmake and clang](#build-cemu-using-cmake-and-clang), use the following command instead:
+ `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang-15 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-15 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja`
-#### Troubleshooting steps
- - If step 3 gives you an error about not being able to find ninja, try appending `-DCMAKE_MAKE_PROGRAM=/usr/bin/ninja` to the command and running it again.
- - If step 3 fails while compiling the boost-build dependency, it means you don't have a working/good standard library installation. Check the integrity of your system headers and making sure that C++ related packages are installed and intact.
- - If step 3 gives a random error, read the `[package-name-and-platform]-out.log` and `[package-name-and-platform]-err.log` for the actual reason to see if you might be lacking the headers from a dependency.
- - 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 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`
- - 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 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 `fatal error: 'span' file not found`, then you're either missing `libstdc++` or are using a version that's too old. Install at least v10 with your package manager, eg `sudo apt install libstdc++-10-dev`. See #644.
+### Build Cemu
+
+#### CMake and Clang
+
+```
+git clone --recursive https://github.com/cemu-project/Cemu
+cd Cemu
+cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -G Ninja
+cmake --build build
+```
+
+#### GCC
+
+If you are building using GCC, make sure you have g++ installed:
+- Installation for Arch and derivatives: `sudo pacman -S gcc`
+- Installation for Fedora and derivatives: `sudo dnf install gcc-c++`
+- Installation for Ubuntu and derivatives: `sudo apt install g++`
+
+```
+git clone --recursive https://github.com/cemu-project/Cemu
+cd Cemu
+cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/gcc -DCMAKE_CXX_COMPILER=/usr/bin/g++ -G Ninja
+cmake --build build
+```
+
+#### Debug Build
+
+```
+git clone --recursive https://github.com/cemu-project/Cemu
+cd Cemu
+cmake -S . -B build -DCMAKE_BUILD_TYPE=debug -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -G Ninja
+cmake --build build
+```
+
+If you are using GCC, replace `cmake -S . -B build -DCMAKE_BUILD_TYPE=debug -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -G Ninja` with `cmake -S . -B build -DCMAKE_BUILD_TYPE=debug -DCMAKE_C_COMPILER=/usr/bin/gcc -DCMAKE_CXX_COMPILER=/usr/bin/g++ -G Ninja`
+
+#### Troubleshooting Steps
+
+##### Compiling Errors
+
+This section refers to running `cmake -S...` (truncated).
+
+* `vcpkg install failed`
+ * Run the following in the root directory and try running the command again (don't forget to change directories afterwards):
+ * `cd dependencies/vcpkg && git fetch --unshallow`
+* `Please ensure you're using the latest port files with git pull and vcpkg update.`
+ * Either:
+ * Update vcpkg by running by the following command:
+ * `git submodule update --remote dependencies/vcpkg`
+ * If you are sure vcpkg is up to date, check the following logs:
+ * `Cemu/dependencies/vcpkg/buildtrees/wxwidgets/config-x64-linux-out.log`
+ * `Cemu/dependencies/vcpkg/buildtrees/libsystemd/config-x64-linux-dbg-meson-log.txt.log`
+ * `Cemu/dependencies/vcpkg/buildtrees/libsystemd/config-x64-linux-dbg-out.log`
+* Not able to find Ninja.
+ * Add the following and try running the command again:
+ * `-DCMAKE_MAKE_PROGRAM=/usr/bin/ninja`
+* Compiling failed during the boost-build dependency.
+ * It means you don't have a working/good standard library installation. Check the integrity of your system headers and making sure that C++ related packages are installed and intact.
+* Compiling failed during rebuild after `git pull` with an error that mentions RPATH
+ * Add the following and try running the command again:
+ * `-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON`
+* If you are getting a random error, read the [package-name-and-platform]-out.log and [package-name-and-platform]-err.log for the actual reason to see if you might be lacking the headers from a dependency.
+
+
+If you are getting a different error than any of the errors listed above, you may either open an issue in this repo or try using [GCC](#gcc). Make sure your standard library and compilers are updated since Cemu uses a lot of modern features!
+
+
+##### Building Errors
+
+This section refers to running `cmake --build build`.
+
+* `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 [GCC](#gcc).
+* `fatal error: 'span' file not found`
+ * You're either missing `libstdc++` or are using a version that's too old. Install at least v10 with your package manager, eg `sudo apt install libstdc++-10-dev`. See [#644](https://github.com/cemu-project/Cemu/issues/644).
+* `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 you are getting a different error than any of the errors listed above, you may either open an issue in this repo or try using [GCC](#gcc). Make sure your standard library and compilers are updated since Cemu uses a lot of modern features!
## 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. 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
### On Apple Silicon Macs, Rosetta 2 and the x86_64 version of Homebrew must be used
@@ -84,11 +158,11 @@ You can skip this section if you have an Intel Mac. Every time you compile, you
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 boost git cmake llvm ninja nasm molten-vk automake libtool`
-### Build Cemu using cmake and clang
+### Build Cemu using CMake and Clang
1. `git clone --recursive https://github.com/cemu-project/Cemu`
2. `cd Cemu`
3. `cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/local/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/usr/local/opt/llvm/bin/clang++ -G Ninja`
@@ -104,3 +178,4 @@ You can skip this section if you have an Intel Mac. Every time you compile, you
2. Then, you can rebuild Cemu using the steps listed above, according to whether you use Linux or Windows.
If CMake complains about Cemu already being compiled or another similar error, try deleting the `CMakeCache.txt` file inside the `build` folder and retry building.
+
From 3a02490a1f37c7f437b99a2ef459ab886d08d79f Mon Sep 17 00:00:00 2001
From: MoonlightWave-12 <123384363+MoonlightWave-12@users.noreply.github.com>
Date: Sun, 18 Feb 2024 17:12:09 +0100
Subject: [PATCH 033/319] BUILD.md: Mention Debian in the build-instructions
for Ubuntu (#1096)
---
BUILD.md | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/BUILD.md b/BUILD.md
index 034000ac..9f3a35be 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -6,8 +6,8 @@
- [Linux](#linux)
- [Dependencies](#dependencies)
- [For Arch and derivatives:](#for-arch-and-derivatives)
+ - [For Debian, Ubuntu and derivatives](#for-debian-ubuntu-and-derivatives)
- [For Fedora and derivatives:](#for-fedora-and-derivatives)
- - [For Ubuntu and derivatives](#for-ubuntu-and-derivatives)
- [Build Cemu](#build-cemu)
- [CMake and Clang](#cmake-and-clang)
- [GCC](#gcc)
@@ -48,10 +48,7 @@ To compile Cemu, a recent enough compiler and STL with C++20 support is required
#### For Arch and derivatives:
`sudo pacman -S --needed base-devel clang cmake freeglut git glm gtk3 libgcrypt libpulse libsecret linux-headers llvm nasm ninja systemd unzip zip`
-#### For Fedora and derivatives:
-`sudo dnf install clang cmake cubeb-devel freeglut-devel git glm-devel gtk3-devel kernel-headers libgcrypt-devel libsecret-devel libtool libusb1-devel nasm ninja-build perl-core systemd-devel zlib-devel`
-
-#### For Ubuntu and derivatives:
+#### For Debian, Ubuntu and derivatives:
`sudo apt install -y cmake curl clang-15 freeglut3-dev git libgcrypt20-dev libglm-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev libtool nasm ninja-build`
You may also need to install `libusb-1.0-0-dev` as a workaround for an issue with the vcpkg hidapi package.
@@ -59,6 +56,9 @@ You may also need to install `libusb-1.0-0-dev` as a workaround for an issue wit
At Step 3 in [Build Cemu using cmake and clang](#build-cemu-using-cmake-and-clang), use the following command instead:
`cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang-15 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-15 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja`
+#### For Fedora and derivatives:
+`sudo dnf install clang cmake cubeb-devel freeglut-devel git glm-devel gtk3-devel kernel-headers libgcrypt-devel libsecret-devel libtool libusb1-devel nasm ninja-build perl-core systemd-devel zlib-devel`
+
### Build Cemu
#### CMake and Clang
@@ -74,8 +74,8 @@ cmake --build build
If you are building using GCC, make sure you have g++ installed:
- Installation for Arch and derivatives: `sudo pacman -S gcc`
+- Installation for Debian, Ubuntu and derivatives: `sudo apt install g++`
- Installation for Fedora and derivatives: `sudo dnf install gcc-c++`
-- Installation for Ubuntu and derivatives: `sudo apt install g++`
```
git clone --recursive https://github.com/cemu-project/Cemu
From 96bbd3bd259eccb767be3a8a3dd406cdbff4b905 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Mon, 19 Feb 2024 12:03:16 +0100
Subject: [PATCH 034/319] Latte: Avoid assert in texture view check
---
src/Cafe/HW/Latte/Core/LatteTexture.cpp | 101 ++++++------------------
1 file changed, 25 insertions(+), 76 deletions(-)
diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.cpp b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
index d38af8ec..707428af 100644
--- a/src/Cafe/HW/Latte/Core/LatteTexture.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
@@ -790,81 +790,30 @@ enum VIEWCOMPATIBILITY
VIEW_NOT_COMPATIBLE,
};
-bool IsDimensionCompatibleForView(Latte::E_DIM baseDim, Latte::E_DIM viewDim)
+bool IsDimensionCompatibleForGX2View(Latte::E_DIM baseDim, Latte::E_DIM viewDim)
{
- bool incompatibleDim = false;
- if (baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_2D)
- ;
- else if (baseDim == Latte::E_DIM::DIM_1D && viewDim == Latte::E_DIM::DIM_1D)
- ;
- else if (baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_2D_ARRAY)
- ;
- else if (baseDim == Latte::E_DIM::DIM_CUBEMAP && viewDim == Latte::E_DIM::DIM_CUBEMAP)
- ;
- else if (baseDim == Latte::E_DIM::DIM_CUBEMAP && viewDim == Latte::E_DIM::DIM_2D_ARRAY)
- ;
- else if (baseDim == Latte::E_DIM::DIM_2D_ARRAY && viewDim == Latte::E_DIM::DIM_2D_ARRAY)
- ;
- else if (baseDim == Latte::E_DIM::DIM_2D_ARRAY && viewDim == Latte::E_DIM::DIM_2D)
- ;
- else if (baseDim == Latte::E_DIM::DIM_2D_ARRAY && viewDim == Latte::E_DIM::DIM_CUBEMAP)
- ;
- else if (baseDim == Latte::E_DIM::DIM_3D && viewDim == Latte::E_DIM::DIM_2D_ARRAY)
- ;
- else if (baseDim == Latte::E_DIM::DIM_2D_MSAA && viewDim == Latte::E_DIM::DIM_2D_MSAA)
- ;
- else if (baseDim == Latte::E_DIM::DIM_2D_ARRAY && viewDim == Latte::E_DIM::DIM_3D)
- {
- // not compatible on OpenGL
- incompatibleDim = true;
- }
- else if (baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_2D_MSAA)
- {
- // not compatible
- incompatibleDim = true;
- }
- else if (baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_1D)
- {
- // not compatible
- incompatibleDim = true;
- }
- else if (baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_3D)
- {
- // not compatible
- incompatibleDim = true;
- }
- else if (baseDim == Latte::E_DIM::DIM_3D && viewDim == Latte::E_DIM::DIM_2D)
- {
- // not compatible
- incompatibleDim = true;
- }
- else if (baseDim == Latte::E_DIM::DIM_3D && viewDim == Latte::E_DIM::DIM_3D)
- {
- // incompatible by default, but may be compatible if the view matches the depth of the base texture and starts at mip/slice 0
- incompatibleDim = true;
- }
- else if ((baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_CUBEMAP) ||
- (baseDim == Latte::E_DIM::DIM_CUBEMAP && viewDim == Latte::E_DIM::DIM_2D))
- {
- // not compatible
- incompatibleDim = true;
- }
- else if (baseDim == Latte::E_DIM::DIM_2D_MSAA && viewDim == Latte::E_DIM::DIM_2D)
- {
- // not compatible
- incompatibleDim = true;
- }
- else if (baseDim == Latte::E_DIM::DIM_1D && viewDim == Latte::E_DIM::DIM_2D)
- {
- // not compatible (probably?)
- incompatibleDim = true;
- }
- else
- {
- cemu_assert_debug(false);
- incompatibleDim = true;
- }
- return !incompatibleDim;
+ // Note that some combinations depend on the exact view/slice index and count which we currently ignore (like a 3D view of a 3D texture)
+ bool isCompatible =
+ (baseDim == viewDim) ||
+ (baseDim == Latte::E_DIM::DIM_CUBEMAP && viewDim == Latte::E_DIM::DIM_2D) ||
+ (baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_2D_ARRAY) ||
+ (baseDim == Latte::E_DIM::DIM_2D_ARRAY && viewDim == Latte::E_DIM::DIM_2D) ||
+ (baseDim == Latte::E_DIM::DIM_CUBEMAP && viewDim == Latte::E_DIM::DIM_2D_ARRAY) ||
+ (baseDim == Latte::E_DIM::DIM_2D_ARRAY && viewDim == Latte::E_DIM::DIM_CUBEMAP) ||
+ (baseDim == Latte::E_DIM::DIM_3D && viewDim == Latte::E_DIM::DIM_2D_ARRAY);
+ if(isCompatible)
+ return true;
+ // these combinations have been seen in use by games and are considered incompatible:
+ // (baseDim == Latte::E_DIM::DIM_2D_ARRAY && viewDim == Latte::E_DIM::DIM_3D) -> Not allowed on OpenGL
+ // (baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_2D_MSAA)
+ // (baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_1D)
+ // (baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_3D)
+ // (baseDim == Latte::E_DIM::DIM_3D && viewDim == Latte::E_DIM::DIM_2D)
+ // (baseDim == Latte::E_DIM::DIM_3D && viewDim == Latte::E_DIM::DIM_3D) -> Only compatible if the same depth and shared at mip/slice 0
+ // (baseDim == Latte::E_DIM::DIM_2D && viewDim == Latte::E_DIM::DIM_CUBEMAP)
+ // (baseDim == Latte::E_DIM::DIM_2D_MSAA && viewDim == Latte::E_DIM::DIM_2D)
+ // (baseDim == Latte::E_DIM::DIM_1D && viewDim == Latte::E_DIM::DIM_2D)
+ return false;
}
VIEWCOMPATIBILITY LatteTexture_CanTextureBeRepresentedAsView(LatteTexture* baseTexture, uint32 physAddr, sint32 width, sint32 height, sint32 pitch, Latte::E_DIM dimView, Latte::E_GX2SURFFMT format, bool isDepth, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, sint32& relativeMipIndex, sint32& relativeSliceIndex)
@@ -881,7 +830,7 @@ VIEWCOMPATIBILITY LatteTexture_CanTextureBeRepresentedAsView(LatteTexture* baseT
return VIEW_NOT_COMPATIBLE;
// 3D views are only compatible on Vulkan if they match the base texture in regards to mip and slice count
bool isCompatible3DView = dimView == Latte::E_DIM::DIM_3D && baseTexture->dim == dimView && firstSlice == 0 && firstMip == 0 && baseTexture->mipLevels == numMip && baseTexture->depth == numSlice;
- if (!isCompatible3DView && !IsDimensionCompatibleForView(baseTexture->dim, dimView))
+ if (!isCompatible3DView && !IsDimensionCompatibleForGX2View(baseTexture->dim, dimView))
return VIEW_NOT_COMPATIBLE;
if (baseTexture->isDepth && baseTexture->format != format)
{
@@ -933,7 +882,7 @@ VIEWCOMPATIBILITY LatteTexture_CanTextureBeRepresentedAsView(LatteTexture* baseT
if (!LatteTexture_IsTexelSizeCompatibleFormat(baseTexture->format, format) )
return VIEW_NOT_COMPATIBLE;
- if (!IsDimensionCompatibleForView(baseTexture->dim, dimView))
+ if (!IsDimensionCompatibleForGX2View(baseTexture->dim, dimView))
return VIEW_NOT_COMPATIBLE;
if (baseTexture->isDepth && baseTexture->format != format)
{
From 72ce4838ea79252f9ec0df3f3eeb5959ca6616e6 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Mon, 19 Feb 2024 12:07:03 +0100
Subject: [PATCH 035/319] Latte: Optimize uniform register array size for known
shaders
---
src/Cafe/HW/Latte/Core/LatteShader.cpp | 2 +-
.../LatteDecompilerAnalyzer.cpp | 2 +-
.../LatteDecompilerEmitGLSLHeader.hpp | 4 ++--
.../LatteDecompilerInternal.h | 18 +++++++++++-------
4 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/src/Cafe/HW/Latte/Core/LatteShader.cpp b/src/Cafe/HW/Latte/Core/LatteShader.cpp
index 503fb664..b59702cd 100644
--- a/src/Cafe/HW/Latte/Core/LatteShader.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteShader.cpp
@@ -652,7 +652,7 @@ LatteDecompilerShader* LatteShader_CreateShaderFromDecompilerOutput(LatteDecompi
}
else
{
- shader->uniform.count_uniformRegister = decompilerOutput.uniformOffsetsVK.count_uniformRegister;
+ shader->uniform.count_uniformRegister = decompilerOutput.uniformOffsetsGL.count_uniformRegister;
}
// calculate aux hash
if (calculateAuxHash)
diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp
index 2e837198..cf22f05d 100644
--- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp
+++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp
@@ -787,7 +787,7 @@ void LatteDecompiler_analyze(LatteDecompilerShaderContext* shaderContext, LatteD
continue;
LatteDecompilerShader::QuickBufferEntry entry;
entry.index = i;
- entry.size = shaderContext->analyzer.uniformBufferAccessTracker[i].DetermineSize(LATTE_GLSL_DYNAMIC_UNIFORM_BLOCK_SIZE) * 16;
+ entry.size = shaderContext->analyzer.uniformBufferAccessTracker[i].DetermineSize(shaderContext->shaderBaseHash, LATTE_GLSL_DYNAMIC_UNIFORM_BLOCK_SIZE) * 16;
shader->list_quickBufferList.push_back(entry);
}
// get dimension of each used texture
diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSLHeader.hpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSLHeader.hpp
index 21cae093..428f8647 100644
--- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSLHeader.hpp
+++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSLHeader.hpp
@@ -37,7 +37,7 @@ namespace LatteDecompiler
}
else if (decompilerContext->shader->uniformMode == LATTE_DECOMPILER_UNIFORM_MODE_FULL_CFILE)
{
- uint32 cfileSize = decompilerContext->analyzer.uniformRegisterAccessTracker.DetermineSize(256);
+ uint32 cfileSize = decompilerContext->analyzer.uniformRegisterAccessTracker.DetermineSize(decompilerContext->shaderBaseHash, 256);
// full or partial uniform register file has to be present
if (shaderType == LatteConst::ShaderType::Vertex)
shaderSrc->addFmt("uniform ivec4 uf_uniformRegisterVS[{}];" _CRLF, cfileSize);
@@ -156,7 +156,7 @@ namespace LatteDecompiler
shaderSrc->addFmt("uniform {}{}" _CRLF, _getShaderUniformBlockInterfaceName(decompilerContext->shaderType), i);
shaderSrc->add("{" _CRLF);
- shaderSrc->addFmt("vec4 {}{}[{}];" _CRLF, _getShaderUniformBlockVariableName(decompilerContext->shaderType), i, decompilerContext->analyzer.uniformBufferAccessTracker[i].DetermineSize(LATTE_GLSL_DYNAMIC_UNIFORM_BLOCK_SIZE));
+ shaderSrc->addFmt("vec4 {}{}[{}];" _CRLF, _getShaderUniformBlockVariableName(decompilerContext->shaderType), i, decompilerContext->analyzer.uniformBufferAccessTracker[i].DetermineSize(decompilerContext->shaderBaseHash, LATTE_GLSL_DYNAMIC_UNIFORM_BLOCK_SIZE));
shaderSrc->add("};" _CRLF _CRLF);
shaderSrc->add(_CRLF);
}
diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h
index ac2a1fe1..ed1858ba 100644
--- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h
+++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerInternal.h
@@ -157,19 +157,23 @@ struct LatteDecompilerBufferAccessTracker
}
}
- sint32 DetermineSize(sint32 maximumSize) const
+ sint32 DetermineSize(uint64 shaderBaseHash, sint32 maximumSize) const
{
- // here we try to predict the accessed range so we dont have to upload the whole buffer
- // potential risky optimization: assume that if there is a fixed-index access on an index higher than any other non-zero relative accesses, it bounds the prior relative access
+ // here we try to predict the accessed byte range so we dont have to upload the whole buffer
+ // if no bound can be determined then return maximumSize
+ // for some known shaders we use hand-tuned values instead of the maximumSize fallback value that those shaders would normally use
+ if(shaderBaseHash == 0x8ff56afdf1a2f837) // XCX text rendering
+ return 24;
+ if(shaderBaseHash == 0x37b9100c1310d3bb) // BotW UI backdrops 1
+ return 24;
+ if(shaderBaseHash == 0xf7ba548c1fefe24a) // BotW UI backdrops 2
+ return 30;
+
sint32 highestAccessIndex = -1;
if(hasStaticIndexAccess)
- {
highestAccessIndex = highestAccessStaticIndex;
- }
if(hasDynamicIndexAccess)
- {
return maximumSize; // dynamic index exists and no bound can be determined
- }
if (highestAccessIndex < 0)
return 1; // no access at all? But avoid zero as a size
return highestAccessIndex + 1;
From a63678c1f40c21151c6daa6f20cbb8fc600ae92a Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Tue, 20 Feb 2024 11:10:35 +0100
Subject: [PATCH 036/319] Update SDL2 vcpkg port to 2.30.0
---
.../sdl2/alsa-dep-fix.patch | 13 ++
.../vcpkg_overlay_ports/sdl2/deps.patch | 13 ++
.../vcpkg_overlay_ports/sdl2/portfile.cmake | 137 ++++++++++++++++++
dependencies/vcpkg_overlay_ports/sdl2/usage | 8 +
.../vcpkg_overlay_ports/sdl2/vcpkg.json | 68 +++++++++
.../sdl2/alsa-dep-fix.patch | 13 ++
.../vcpkg_overlay_ports_linux/sdl2/deps.patch | 13 ++
.../sdl2/portfile.cmake | 137 ++++++++++++++++++
.../vcpkg_overlay_ports_linux/sdl2/usage | 8 +
.../vcpkg_overlay_ports_linux/sdl2/vcpkg.json | 68 +++++++++
.../sdl2/alsa-dep-fix.patch | 13 ++
.../vcpkg_overlay_ports_mac/sdl2/deps.patch | 13 ++
.../sdl2/portfile.cmake | 137 ++++++++++++++++++
.../vcpkg_overlay_ports_mac/sdl2/usage | 8 +
.../vcpkg_overlay_ports_mac/sdl2/vcpkg.json | 68 +++++++++
15 files changed, 717 insertions(+)
create mode 100644 dependencies/vcpkg_overlay_ports/sdl2/alsa-dep-fix.patch
create mode 100644 dependencies/vcpkg_overlay_ports/sdl2/deps.patch
create mode 100644 dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake
create mode 100644 dependencies/vcpkg_overlay_ports/sdl2/usage
create mode 100644 dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json
create mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/alsa-dep-fix.patch
create mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/deps.patch
create mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/portfile.cmake
create mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/usage
create mode 100644 dependencies/vcpkg_overlay_ports_linux/sdl2/vcpkg.json
create mode 100644 dependencies/vcpkg_overlay_ports_mac/sdl2/alsa-dep-fix.patch
create mode 100644 dependencies/vcpkg_overlay_ports_mac/sdl2/deps.patch
create mode 100644 dependencies/vcpkg_overlay_ports_mac/sdl2/portfile.cmake
create mode 100644 dependencies/vcpkg_overlay_ports_mac/sdl2/usage
create mode 100644 dependencies/vcpkg_overlay_ports_mac/sdl2/vcpkg.json
diff --git a/dependencies/vcpkg_overlay_ports/sdl2/alsa-dep-fix.patch b/dependencies/vcpkg_overlay_ports/sdl2/alsa-dep-fix.patch
new file mode 100644
index 00000000..5b2c77b9
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports/sdl2/alsa-dep-fix.patch
@@ -0,0 +1,13 @@
+diff --git a/SDL2Config.cmake.in b/SDL2Config.cmake.in
+index cc8bcf26d..ead829767 100644
+--- a/SDL2Config.cmake.in
++++ b/SDL2Config.cmake.in
+@@ -35,7 +35,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/sdlfind.cmake")
+
+ set(SDL_ALSA @SDL_ALSA@)
+ set(SDL_ALSA_SHARED @SDL_ALSA_SHARED@)
+-if(SDL_ALSA AND NOT SDL_ALSA_SHARED AND TARGET SDL2::SDL2-static)
++if(SDL_ALSA)
+ sdlFindALSA()
+ endif()
+ unset(SDL_ALSA)
diff --git a/dependencies/vcpkg_overlay_ports/sdl2/deps.patch b/dependencies/vcpkg_overlay_ports/sdl2/deps.patch
new file mode 100644
index 00000000..a8637d8c
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports/sdl2/deps.patch
@@ -0,0 +1,13 @@
+diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
+index 65a98efbe..2f99f28f1 100644
+--- a/cmake/sdlchecks.cmake
++++ b/cmake/sdlchecks.cmake
+@@ -352,7 +352,7 @@ endmacro()
+ # - HAVE_SDL_LOADSO opt
+ macro(CheckLibSampleRate)
+ if(SDL_LIBSAMPLERATE)
+- find_package(SampleRate QUIET)
++ find_package(SampleRate CONFIG REQUIRED)
+ if(SampleRate_FOUND AND TARGET SampleRate::samplerate)
+ set(HAVE_LIBSAMPLERATE TRUE)
+ set(HAVE_LIBSAMPLERATE_H TRUE)
diff --git a/dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake b/dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake
new file mode 100644
index 00000000..22685e6a
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports/sdl2/portfile.cmake
@@ -0,0 +1,137 @@
+vcpkg_from_github(
+ OUT_SOURCE_PATH SOURCE_PATH
+ REPO libsdl-org/SDL
+ REF "release-${VERSION}"
+ SHA512 c7635a83a52f3970a372b804a8631f0a7e6b8d89aed1117bcc54a2040ad0928122175004cf2b42cf84a4fd0f86236f779229eaa63dfa6ca9c89517f999c5ff1c
+ HEAD_REF main
+ PATCHES
+ deps.patch
+ alsa-dep-fix.patch
+)
+
+string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC)
+string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED)
+string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT)
+
+vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
+ FEATURES
+ alsa SDL_ALSA
+ alsa CMAKE_REQUIRE_FIND_PACKAGE_ALSA
+ ibus SDL_IBUS
+ samplerate SDL_LIBSAMPLERATE
+ vulkan SDL_VULKAN
+ wayland SDL_WAYLAND
+ x11 SDL_X11
+ INVERTED_FEATURES
+ alsa CMAKE_DISABLE_FIND_PACKAGE_ALSA
+)
+
+if ("x11" IN_LIST FEATURES)
+ message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n")
+endif()
+if ("wayland" IN_LIST FEATURES)
+ message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n")
+endif()
+if ("ibus" IN_LIST FEATURES)
+ message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n")
+endif()
+
+if(VCPKG_TARGET_IS_UWP)
+ set(configure_opts WINDOWS_USE_MSBUILD)
+endif()
+
+vcpkg_cmake_configure(
+ SOURCE_PATH "${SOURCE_PATH}"
+ ${configure_opts}
+ OPTIONS ${FEATURE_OPTIONS}
+ -DSDL_STATIC=${SDL_STATIC}
+ -DSDL_SHARED=${SDL_SHARED}
+ -DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT}
+ -DSDL_LIBC=ON
+ -DSDL_TEST=OFF
+ -DSDL_INSTALL_CMAKEDIR="cmake"
+ -DCMAKE_DISABLE_FIND_PACKAGE_Git=ON
+ -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=ON
+ -DSDL_LIBSAMPLERATE_SHARED=OFF
+ MAYBE_UNUSED_VARIABLES
+ SDL_FORCE_STATIC_VCRT
+ PKG_CONFIG_USE_CMAKE_PREFIX_PATH
+)
+
+vcpkg_cmake_install()
+vcpkg_cmake_config_fixup(CONFIG_PATH cmake)
+
+file(REMOVE_RECURSE
+ "${CURRENT_PACKAGES_DIR}/debug/include"
+ "${CURRENT_PACKAGES_DIR}/debug/share"
+ "${CURRENT_PACKAGES_DIR}/bin/sdl2-config"
+ "${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config"
+ "${CURRENT_PACKAGES_DIR}/SDL2.framework"
+ "${CURRENT_PACKAGES_DIR}/debug/SDL2.framework"
+ "${CURRENT_PACKAGES_DIR}/share/licenses"
+ "${CURRENT_PACKAGES_DIR}/share/aclocal"
+)
+
+file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*")
+if(NOT BINS)
+ file(REMOVE_RECURSE
+ "${CURRENT_PACKAGES_DIR}/bin"
+ "${CURRENT_PACKAGES_DIR}/debug/bin"
+ )
+endif()
+
+if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW)
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
+ file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link")
+ file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib")
+ endif()
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
+ file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link")
+ file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib")
+ endif()
+
+ file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake")
+ foreach(SHARE_FILE ${SHARE_FILES})
+ vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main")
+ endforeach()
+endif()
+
+vcpkg_copy_pdbs()
+
+set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)")
+set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)")
+file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX})
+file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX})
+string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}")
+string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}")
+
+if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ")
+endif()
+
+if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ")
+ endif()
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ")
+ endif()
+endif()
+
+if(VCPKG_TARGET_IS_UWP)
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
+ endif()
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "d")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
+ endif()
+endif()
+
+vcpkg_fixup_pkgconfig()
+
+file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
+vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt")
diff --git a/dependencies/vcpkg_overlay_ports/sdl2/usage b/dependencies/vcpkg_overlay_ports/sdl2/usage
new file mode 100644
index 00000000..1cddcd46
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports/sdl2/usage
@@ -0,0 +1,8 @@
+sdl2 provides CMake targets:
+
+ find_package(SDL2 CONFIG REQUIRED)
+ target_link_libraries(main
+ PRIVATE
+ $
+ $,SDL2::SDL2,SDL2::SDL2-static>
+ )
diff --git a/dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json b/dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json
new file mode 100644
index 00000000..1f460375
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports/sdl2/vcpkg.json
@@ -0,0 +1,68 @@
+{
+ "name": "sdl2",
+ "version": "2.30.0",
+ "description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.",
+ "homepage": "https://www.libsdl.org/download-2.0.php",
+ "license": "Zlib",
+ "dependencies": [
+ {
+ "name": "dbus",
+ "default-features": false,
+ "platform": "linux"
+ },
+ {
+ "name": "vcpkg-cmake",
+ "host": true
+ },
+ {
+ "name": "vcpkg-cmake-config",
+ "host": true
+ }
+ ],
+ "default-features": [
+ {
+ "name": "ibus",
+ "platform": "linux"
+ },
+ {
+ "name": "wayland",
+ "platform": "linux"
+ },
+ {
+ "name": "x11",
+ "platform": "linux"
+ }
+ ],
+ "features": {
+ "alsa": {
+ "description": "Support for alsa audio",
+ "dependencies": [
+ {
+ "name": "alsa",
+ "platform": "linux"
+ }
+ ]
+ },
+ "ibus": {
+ "description": "Build with ibus IME support",
+ "supports": "linux"
+ },
+ "samplerate": {
+ "description": "Use libsamplerate for audio rate conversion",
+ "dependencies": [
+ "libsamplerate"
+ ]
+ },
+ "vulkan": {
+ "description": "Vulkan functionality for SDL"
+ },
+ "wayland": {
+ "description": "Build with Wayland support",
+ "supports": "linux"
+ },
+ "x11": {
+ "description": "Build with X11 support",
+ "supports": "!windows"
+ }
+ }
+}
diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/alsa-dep-fix.patch b/dependencies/vcpkg_overlay_ports_linux/sdl2/alsa-dep-fix.patch
new file mode 100644
index 00000000..5b2c77b9
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_linux/sdl2/alsa-dep-fix.patch
@@ -0,0 +1,13 @@
+diff --git a/SDL2Config.cmake.in b/SDL2Config.cmake.in
+index cc8bcf26d..ead829767 100644
+--- a/SDL2Config.cmake.in
++++ b/SDL2Config.cmake.in
+@@ -35,7 +35,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/sdlfind.cmake")
+
+ set(SDL_ALSA @SDL_ALSA@)
+ set(SDL_ALSA_SHARED @SDL_ALSA_SHARED@)
+-if(SDL_ALSA AND NOT SDL_ALSA_SHARED AND TARGET SDL2::SDL2-static)
++if(SDL_ALSA)
+ sdlFindALSA()
+ endif()
+ unset(SDL_ALSA)
diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/deps.patch b/dependencies/vcpkg_overlay_ports_linux/sdl2/deps.patch
new file mode 100644
index 00000000..a8637d8c
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_linux/sdl2/deps.patch
@@ -0,0 +1,13 @@
+diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
+index 65a98efbe..2f99f28f1 100644
+--- a/cmake/sdlchecks.cmake
++++ b/cmake/sdlchecks.cmake
+@@ -352,7 +352,7 @@ endmacro()
+ # - HAVE_SDL_LOADSO opt
+ macro(CheckLibSampleRate)
+ if(SDL_LIBSAMPLERATE)
+- find_package(SampleRate QUIET)
++ find_package(SampleRate CONFIG REQUIRED)
+ if(SampleRate_FOUND AND TARGET SampleRate::samplerate)
+ set(HAVE_LIBSAMPLERATE TRUE)
+ set(HAVE_LIBSAMPLERATE_H TRUE)
diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/portfile.cmake b/dependencies/vcpkg_overlay_ports_linux/sdl2/portfile.cmake
new file mode 100644
index 00000000..22685e6a
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_linux/sdl2/portfile.cmake
@@ -0,0 +1,137 @@
+vcpkg_from_github(
+ OUT_SOURCE_PATH SOURCE_PATH
+ REPO libsdl-org/SDL
+ REF "release-${VERSION}"
+ SHA512 c7635a83a52f3970a372b804a8631f0a7e6b8d89aed1117bcc54a2040ad0928122175004cf2b42cf84a4fd0f86236f779229eaa63dfa6ca9c89517f999c5ff1c
+ HEAD_REF main
+ PATCHES
+ deps.patch
+ alsa-dep-fix.patch
+)
+
+string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC)
+string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED)
+string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT)
+
+vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
+ FEATURES
+ alsa SDL_ALSA
+ alsa CMAKE_REQUIRE_FIND_PACKAGE_ALSA
+ ibus SDL_IBUS
+ samplerate SDL_LIBSAMPLERATE
+ vulkan SDL_VULKAN
+ wayland SDL_WAYLAND
+ x11 SDL_X11
+ INVERTED_FEATURES
+ alsa CMAKE_DISABLE_FIND_PACKAGE_ALSA
+)
+
+if ("x11" IN_LIST FEATURES)
+ message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n")
+endif()
+if ("wayland" IN_LIST FEATURES)
+ message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n")
+endif()
+if ("ibus" IN_LIST FEATURES)
+ message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n")
+endif()
+
+if(VCPKG_TARGET_IS_UWP)
+ set(configure_opts WINDOWS_USE_MSBUILD)
+endif()
+
+vcpkg_cmake_configure(
+ SOURCE_PATH "${SOURCE_PATH}"
+ ${configure_opts}
+ OPTIONS ${FEATURE_OPTIONS}
+ -DSDL_STATIC=${SDL_STATIC}
+ -DSDL_SHARED=${SDL_SHARED}
+ -DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT}
+ -DSDL_LIBC=ON
+ -DSDL_TEST=OFF
+ -DSDL_INSTALL_CMAKEDIR="cmake"
+ -DCMAKE_DISABLE_FIND_PACKAGE_Git=ON
+ -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=ON
+ -DSDL_LIBSAMPLERATE_SHARED=OFF
+ MAYBE_UNUSED_VARIABLES
+ SDL_FORCE_STATIC_VCRT
+ PKG_CONFIG_USE_CMAKE_PREFIX_PATH
+)
+
+vcpkg_cmake_install()
+vcpkg_cmake_config_fixup(CONFIG_PATH cmake)
+
+file(REMOVE_RECURSE
+ "${CURRENT_PACKAGES_DIR}/debug/include"
+ "${CURRENT_PACKAGES_DIR}/debug/share"
+ "${CURRENT_PACKAGES_DIR}/bin/sdl2-config"
+ "${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config"
+ "${CURRENT_PACKAGES_DIR}/SDL2.framework"
+ "${CURRENT_PACKAGES_DIR}/debug/SDL2.framework"
+ "${CURRENT_PACKAGES_DIR}/share/licenses"
+ "${CURRENT_PACKAGES_DIR}/share/aclocal"
+)
+
+file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*")
+if(NOT BINS)
+ file(REMOVE_RECURSE
+ "${CURRENT_PACKAGES_DIR}/bin"
+ "${CURRENT_PACKAGES_DIR}/debug/bin"
+ )
+endif()
+
+if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW)
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
+ file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link")
+ file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib")
+ endif()
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
+ file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link")
+ file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib")
+ endif()
+
+ file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake")
+ foreach(SHARE_FILE ${SHARE_FILES})
+ vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main")
+ endforeach()
+endif()
+
+vcpkg_copy_pdbs()
+
+set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)")
+set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)")
+file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX})
+file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX})
+string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}")
+string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}")
+
+if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ")
+endif()
+
+if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ")
+ endif()
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ")
+ endif()
+endif()
+
+if(VCPKG_TARGET_IS_UWP)
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
+ endif()
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "d")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
+ endif()
+endif()
+
+vcpkg_fixup_pkgconfig()
+
+file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
+vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt")
diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/usage b/dependencies/vcpkg_overlay_ports_linux/sdl2/usage
new file mode 100644
index 00000000..1cddcd46
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_linux/sdl2/usage
@@ -0,0 +1,8 @@
+sdl2 provides CMake targets:
+
+ find_package(SDL2 CONFIG REQUIRED)
+ target_link_libraries(main
+ PRIVATE
+ $
+ $,SDL2::SDL2,SDL2::SDL2-static>
+ )
diff --git a/dependencies/vcpkg_overlay_ports_linux/sdl2/vcpkg.json b/dependencies/vcpkg_overlay_ports_linux/sdl2/vcpkg.json
new file mode 100644
index 00000000..1f460375
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_linux/sdl2/vcpkg.json
@@ -0,0 +1,68 @@
+{
+ "name": "sdl2",
+ "version": "2.30.0",
+ "description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.",
+ "homepage": "https://www.libsdl.org/download-2.0.php",
+ "license": "Zlib",
+ "dependencies": [
+ {
+ "name": "dbus",
+ "default-features": false,
+ "platform": "linux"
+ },
+ {
+ "name": "vcpkg-cmake",
+ "host": true
+ },
+ {
+ "name": "vcpkg-cmake-config",
+ "host": true
+ }
+ ],
+ "default-features": [
+ {
+ "name": "ibus",
+ "platform": "linux"
+ },
+ {
+ "name": "wayland",
+ "platform": "linux"
+ },
+ {
+ "name": "x11",
+ "platform": "linux"
+ }
+ ],
+ "features": {
+ "alsa": {
+ "description": "Support for alsa audio",
+ "dependencies": [
+ {
+ "name": "alsa",
+ "platform": "linux"
+ }
+ ]
+ },
+ "ibus": {
+ "description": "Build with ibus IME support",
+ "supports": "linux"
+ },
+ "samplerate": {
+ "description": "Use libsamplerate for audio rate conversion",
+ "dependencies": [
+ "libsamplerate"
+ ]
+ },
+ "vulkan": {
+ "description": "Vulkan functionality for SDL"
+ },
+ "wayland": {
+ "description": "Build with Wayland support",
+ "supports": "linux"
+ },
+ "x11": {
+ "description": "Build with X11 support",
+ "supports": "!windows"
+ }
+ }
+}
diff --git a/dependencies/vcpkg_overlay_ports_mac/sdl2/alsa-dep-fix.patch b/dependencies/vcpkg_overlay_ports_mac/sdl2/alsa-dep-fix.patch
new file mode 100644
index 00000000..5b2c77b9
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_mac/sdl2/alsa-dep-fix.patch
@@ -0,0 +1,13 @@
+diff --git a/SDL2Config.cmake.in b/SDL2Config.cmake.in
+index cc8bcf26d..ead829767 100644
+--- a/SDL2Config.cmake.in
++++ b/SDL2Config.cmake.in
+@@ -35,7 +35,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/sdlfind.cmake")
+
+ set(SDL_ALSA @SDL_ALSA@)
+ set(SDL_ALSA_SHARED @SDL_ALSA_SHARED@)
+-if(SDL_ALSA AND NOT SDL_ALSA_SHARED AND TARGET SDL2::SDL2-static)
++if(SDL_ALSA)
+ sdlFindALSA()
+ endif()
+ unset(SDL_ALSA)
diff --git a/dependencies/vcpkg_overlay_ports_mac/sdl2/deps.patch b/dependencies/vcpkg_overlay_ports_mac/sdl2/deps.patch
new file mode 100644
index 00000000..a8637d8c
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_mac/sdl2/deps.patch
@@ -0,0 +1,13 @@
+diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
+index 65a98efbe..2f99f28f1 100644
+--- a/cmake/sdlchecks.cmake
++++ b/cmake/sdlchecks.cmake
+@@ -352,7 +352,7 @@ endmacro()
+ # - HAVE_SDL_LOADSO opt
+ macro(CheckLibSampleRate)
+ if(SDL_LIBSAMPLERATE)
+- find_package(SampleRate QUIET)
++ find_package(SampleRate CONFIG REQUIRED)
+ if(SampleRate_FOUND AND TARGET SampleRate::samplerate)
+ set(HAVE_LIBSAMPLERATE TRUE)
+ set(HAVE_LIBSAMPLERATE_H TRUE)
diff --git a/dependencies/vcpkg_overlay_ports_mac/sdl2/portfile.cmake b/dependencies/vcpkg_overlay_ports_mac/sdl2/portfile.cmake
new file mode 100644
index 00000000..22685e6a
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_mac/sdl2/portfile.cmake
@@ -0,0 +1,137 @@
+vcpkg_from_github(
+ OUT_SOURCE_PATH SOURCE_PATH
+ REPO libsdl-org/SDL
+ REF "release-${VERSION}"
+ SHA512 c7635a83a52f3970a372b804a8631f0a7e6b8d89aed1117bcc54a2040ad0928122175004cf2b42cf84a4fd0f86236f779229eaa63dfa6ca9c89517f999c5ff1c
+ HEAD_REF main
+ PATCHES
+ deps.patch
+ alsa-dep-fix.patch
+)
+
+string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" SDL_STATIC)
+string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" SDL_SHARED)
+string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" FORCE_STATIC_VCRT)
+
+vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
+ FEATURES
+ alsa SDL_ALSA
+ alsa CMAKE_REQUIRE_FIND_PACKAGE_ALSA
+ ibus SDL_IBUS
+ samplerate SDL_LIBSAMPLERATE
+ vulkan SDL_VULKAN
+ wayland SDL_WAYLAND
+ x11 SDL_X11
+ INVERTED_FEATURES
+ alsa CMAKE_DISABLE_FIND_PACKAGE_ALSA
+)
+
+if ("x11" IN_LIST FEATURES)
+ message(WARNING "You will need to install Xorg dependencies to use feature x11:\nsudo apt install libx11-dev libxft-dev libxext-dev\n")
+endif()
+if ("wayland" IN_LIST FEATURES)
+ message(WARNING "You will need to install Wayland dependencies to use feature wayland:\nsudo apt install libwayland-dev libxkbcommon-dev libegl1-mesa-dev\n")
+endif()
+if ("ibus" IN_LIST FEATURES)
+ message(WARNING "You will need to install ibus dependencies to use feature ibus:\nsudo apt install libibus-1.0-dev\n")
+endif()
+
+if(VCPKG_TARGET_IS_UWP)
+ set(configure_opts WINDOWS_USE_MSBUILD)
+endif()
+
+vcpkg_cmake_configure(
+ SOURCE_PATH "${SOURCE_PATH}"
+ ${configure_opts}
+ OPTIONS ${FEATURE_OPTIONS}
+ -DSDL_STATIC=${SDL_STATIC}
+ -DSDL_SHARED=${SDL_SHARED}
+ -DSDL_FORCE_STATIC_VCRT=${FORCE_STATIC_VCRT}
+ -DSDL_LIBC=ON
+ -DSDL_TEST=OFF
+ -DSDL_INSTALL_CMAKEDIR="cmake"
+ -DCMAKE_DISABLE_FIND_PACKAGE_Git=ON
+ -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=ON
+ -DSDL_LIBSAMPLERATE_SHARED=OFF
+ MAYBE_UNUSED_VARIABLES
+ SDL_FORCE_STATIC_VCRT
+ PKG_CONFIG_USE_CMAKE_PREFIX_PATH
+)
+
+vcpkg_cmake_install()
+vcpkg_cmake_config_fixup(CONFIG_PATH cmake)
+
+file(REMOVE_RECURSE
+ "${CURRENT_PACKAGES_DIR}/debug/include"
+ "${CURRENT_PACKAGES_DIR}/debug/share"
+ "${CURRENT_PACKAGES_DIR}/bin/sdl2-config"
+ "${CURRENT_PACKAGES_DIR}/debug/bin/sdl2-config"
+ "${CURRENT_PACKAGES_DIR}/SDL2.framework"
+ "${CURRENT_PACKAGES_DIR}/debug/SDL2.framework"
+ "${CURRENT_PACKAGES_DIR}/share/licenses"
+ "${CURRENT_PACKAGES_DIR}/share/aclocal"
+)
+
+file(GLOB BINS "${CURRENT_PACKAGES_DIR}/debug/bin/*" "${CURRENT_PACKAGES_DIR}/bin/*")
+if(NOT BINS)
+ file(REMOVE_RECURSE
+ "${CURRENT_PACKAGES_DIR}/bin"
+ "${CURRENT_PACKAGES_DIR}/debug/bin"
+ )
+endif()
+
+if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_UWP AND NOT VCPKG_TARGET_IS_MINGW)
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
+ file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/lib/manual-link")
+ file(RENAME "${CURRENT_PACKAGES_DIR}/lib/SDL2main.lib" "${CURRENT_PACKAGES_DIR}/lib/manual-link/SDL2main.lib")
+ endif()
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
+ file(MAKE_DIRECTORY "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link")
+ file(RENAME "${CURRENT_PACKAGES_DIR}/debug/lib/SDL2maind.lib" "${CURRENT_PACKAGES_DIR}/debug/lib/manual-link/SDL2maind.lib")
+ endif()
+
+ file(GLOB SHARE_FILES "${CURRENT_PACKAGES_DIR}/share/sdl2/*.cmake")
+ foreach(SHARE_FILE ${SHARE_FILES})
+ vcpkg_replace_string("${SHARE_FILE}" "lib/SDL2main" "lib/manual-link/SDL2main")
+ endforeach()
+endif()
+
+vcpkg_copy_pdbs()
+
+set(DYLIB_COMPATIBILITY_VERSION_REGEX "set\\(DYLIB_COMPATIBILITY_VERSION (.+)\\)")
+set(DYLIB_CURRENT_VERSION_REGEX "set\\(DYLIB_CURRENT_VERSION (.+)\\)")
+file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_COMPATIBILITY_VERSION REGEX ${DYLIB_COMPATIBILITY_VERSION_REGEX})
+file(STRINGS "${SOURCE_PATH}/CMakeLists.txt" DYLIB_CURRENT_VERSION REGEX ${DYLIB_CURRENT_VERSION_REGEX})
+string(REGEX REPLACE ${DYLIB_COMPATIBILITY_VERSION_REGEX} "\\1" DYLIB_COMPATIBILITY_VERSION "${DYLIB_COMPATIBILITY_VERSION}")
+string(REGEX REPLACE ${DYLIB_CURRENT_VERSION_REGEX} "\\1" DYLIB_CURRENT_VERSION "${DYLIB_CURRENT_VERSION}")
+
+if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2main" "-lSDL2maind")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2 " "-lSDL2d ")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-static " "-lSDL2-staticd ")
+endif()
+
+if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic" AND VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW)
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-lSDL2-static " " ")
+ endif()
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-lSDL2-staticd " " ")
+ endif()
+endif()
+
+if(VCPKG_TARGET_IS_UWP)
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
+ endif()
+ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "$<$:d>.lib" "d")
+ vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/sdl2.pc" "-l-nodefaultlib:" "-nodefaultlib:")
+ endif()
+endif()
+
+vcpkg_fixup_pkgconfig()
+
+file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")
+vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE.txt")
diff --git a/dependencies/vcpkg_overlay_ports_mac/sdl2/usage b/dependencies/vcpkg_overlay_ports_mac/sdl2/usage
new file mode 100644
index 00000000..1cddcd46
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_mac/sdl2/usage
@@ -0,0 +1,8 @@
+sdl2 provides CMake targets:
+
+ find_package(SDL2 CONFIG REQUIRED)
+ target_link_libraries(main
+ PRIVATE
+ $
+ $,SDL2::SDL2,SDL2::SDL2-static>
+ )
diff --git a/dependencies/vcpkg_overlay_ports_mac/sdl2/vcpkg.json b/dependencies/vcpkg_overlay_ports_mac/sdl2/vcpkg.json
new file mode 100644
index 00000000..1f460375
--- /dev/null
+++ b/dependencies/vcpkg_overlay_ports_mac/sdl2/vcpkg.json
@@ -0,0 +1,68 @@
+{
+ "name": "sdl2",
+ "version": "2.30.0",
+ "description": "Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.",
+ "homepage": "https://www.libsdl.org/download-2.0.php",
+ "license": "Zlib",
+ "dependencies": [
+ {
+ "name": "dbus",
+ "default-features": false,
+ "platform": "linux"
+ },
+ {
+ "name": "vcpkg-cmake",
+ "host": true
+ },
+ {
+ "name": "vcpkg-cmake-config",
+ "host": true
+ }
+ ],
+ "default-features": [
+ {
+ "name": "ibus",
+ "platform": "linux"
+ },
+ {
+ "name": "wayland",
+ "platform": "linux"
+ },
+ {
+ "name": "x11",
+ "platform": "linux"
+ }
+ ],
+ "features": {
+ "alsa": {
+ "description": "Support for alsa audio",
+ "dependencies": [
+ {
+ "name": "alsa",
+ "platform": "linux"
+ }
+ ]
+ },
+ "ibus": {
+ "description": "Build with ibus IME support",
+ "supports": "linux"
+ },
+ "samplerate": {
+ "description": "Use libsamplerate for audio rate conversion",
+ "dependencies": [
+ "libsamplerate"
+ ]
+ },
+ "vulkan": {
+ "description": "Vulkan functionality for SDL"
+ },
+ "wayland": {
+ "description": "Build with Wayland support",
+ "supports": "linux"
+ },
+ "x11": {
+ "description": "Build with X11 support",
+ "supports": "!windows"
+ }
+ }
+}
From 8b37e316d0537da9c717cb0698c9141e668d6fff Mon Sep 17 00:00:00 2001
From: Leif Liddy
Date: Sat, 24 Feb 2024 20:47:06 +0100
Subject: [PATCH 037/319] BUILD.md: Add llvm package for Fedora (#1101)
---
BUILD.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/BUILD.md b/BUILD.md
index 9f3a35be..3ff2254f 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -57,7 +57,7 @@ At Step 3 in [Build Cemu using cmake and clang](#build-cemu-using-cmake-and-clan
`cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang-15 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-15 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja`
#### For Fedora and derivatives:
-`sudo dnf install clang cmake cubeb-devel freeglut-devel git glm-devel gtk3-devel kernel-headers libgcrypt-devel libsecret-devel libtool libusb1-devel nasm ninja-build perl-core systemd-devel zlib-devel`
+`sudo dnf install clang cmake cubeb-devel freeglut-devel git glm-devel gtk3-devel kernel-headers libgcrypt-devel libsecret-devel libtool libusb1-devel llvm nasm ninja-build perl-core systemd-devel zlib-devel`
### Build Cemu
@@ -128,7 +128,7 @@ If you are getting a different error than any of the errors listed above, you ma
##### Building Errors
-This section refers to running `cmake --build build`.
+This section refers to running `cmake --build build`.
* `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 [GCC](#gcc).
From 49c55a3f561eed2da750cbacfcef4fc5ffe1075e Mon Sep 17 00:00:00 2001
From: Simon <113838661+ssievert42@users.noreply.github.com>
Date: Wed, 6 Mar 2024 14:37:36 +0100
Subject: [PATCH 038/319] nsyshid: remove stray print statements (#1106)
---
src/Cafe/OS/libs/nsyshid/BackendWindowsHID.cpp | 1 -
src/Cafe/OS/libs/nsyshid/nsyshid.cpp | 1 -
2 files changed, 2 deletions(-)
diff --git a/src/Cafe/OS/libs/nsyshid/BackendWindowsHID.cpp b/src/Cafe/OS/libs/nsyshid/BackendWindowsHID.cpp
index 520a0d31..23da5798 100644
--- a/src/Cafe/OS/libs/nsyshid/BackendWindowsHID.cpp
+++ b/src/Cafe/OS/libs/nsyshid/BackendWindowsHID.cpp
@@ -446,7 +446,6 @@ namespace nsyshid::backend::windows
{
sprintf(debugOutput + i * 3, "%02x ", data[i]);
}
- fmt::print("{} Data: {}\n", prefix, debugOutput);
cemuLog_logDebug(LogType::Force, "[{}] Data: {}", prefix, debugOutput);
}
} // namespace nsyshid::backend::windows
diff --git a/src/Cafe/OS/libs/nsyshid/nsyshid.cpp b/src/Cafe/OS/libs/nsyshid/nsyshid.cpp
index b21e2a43..ba3e3b96 100644
--- a/src/Cafe/OS/libs/nsyshid/nsyshid.cpp
+++ b/src/Cafe/OS/libs/nsyshid/nsyshid.cpp
@@ -332,7 +332,6 @@ namespace nsyshid
{
sprintf(debugOutput + i * 3, "%02x ", data[i]);
}
- fmt::print("{} Data: {}\n", prefix, debugOutput);
cemuLog_logDebug(LogType::Force, "[{}] Data: {}", prefix, debugOutput);
}
From 8f1cd4f9255e16aeddb2e72d35a47f37e1e478bc Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Mon, 26 Feb 2024 23:52:33 +0100
Subject: [PATCH 039/319] Vulkan: Update some code to use
VK_KHR_synchronization2
---
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 30 ++-
.../HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 220 +++++++++---------
.../Renderer/Vulkan/VulkanRendererCore.cpp | 35 +--
3 files changed, 140 insertions(+), 145 deletions(-)
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index 616f57e2..631f1d0c 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -468,6 +468,15 @@ VulkanRenderer::VulkanRenderer()
void* deviceExtensionFeatures = nullptr;
+ // enable VK_KHR_synchonization_2
+ VkPhysicalDeviceSynchronization2FeaturesKHR sync2Feature{};
+ {
+ sync2Feature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR;
+ sync2Feature.pNext = deviceExtensionFeatures;
+ deviceExtensionFeatures = &sync2Feature;
+ sync2Feature.synchronization2 = VK_TRUE;
+ }
+
// enable VK_EXT_pipeline_creation_cache_control
VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT cacheControlFeature{};
if (m_featureControl.deviceExtensions.pipeline_creation_cache_control)
@@ -2852,13 +2861,20 @@ void VulkanRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
ClearColorbuffer(padView);
// barrier for input texture
- VkMemoryBarrier memoryBarrier{};
- memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
- VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
- VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
- memoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
- vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStage, dstStage, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
+ {
+ VkMemoryBarrier2 memoryBarrier2{};
+ memoryBarrier2.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2;
+ memoryBarrier2.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR | VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
+ memoryBarrier2.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR | VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR | VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR;
+ memoryBarrier2.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT;
+ memoryBarrier2.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT;
+ VkDependencyInfo dependencyInfo{};
+ dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
+ dependencyInfo.dependencyFlags = 0;
+ dependencyInfo.memoryBarrierCount = 1;
+ dependencyInfo.pMemoryBarriers = &memoryBarrier2;
+ vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &dependencyInfo);
+ }
auto pipeline = backbufferBlit_createGraphicsPipeline(m_swapchainDescriptorSetLayout, padView, shader);
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
index b61a0b40..7565d260 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
@@ -728,201 +728,192 @@ private:
IMAGE_READ = 0x20,
IMAGE_WRITE = 0x40,
-
};
template
- void barrier_calcStageAndMask(VkPipelineStageFlags& stages, VkAccessFlags& accessFlags)
+ void barrier_calcStageAndMask(VkPipelineStageFlags2& stages, VkAccessFlags2& accessFlags)
{
stages = 0;
accessFlags = 0;
if constexpr ((TSyncOp & BUFFER_SHADER_READ) != 0)
{
- // in theory: VK_ACCESS_INDEX_READ_BIT should be set here too but indices are currently separated
- stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- accessFlags |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
+ // in theory: VK_ACCESS_2_INDEX_READ_BIT should be set here too but indices are currently separated
+ stages |= VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
+ accessFlags |= VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_2_UNIFORM_READ_BIT | VK_ACCESS_2_SHADER_READ_BIT;
}
-
+
if constexpr ((TSyncOp & BUFFER_SHADER_WRITE) != 0)
{
- stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- accessFlags |= VK_ACCESS_SHADER_WRITE_BIT;
+ stages |= VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
+ accessFlags |= VK_ACCESS_2_SHADER_WRITE_BIT;
}
if constexpr ((TSyncOp & ANY_TRANSFER) != 0)
{
- //stages |= VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_HOST_BIT;
- //accessFlags |= VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT;
- stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
- accessFlags |= VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
-
- //accessFlags |= VK_ACCESS_MEMORY_READ_BIT;
- //accessFlags |= VK_ACCESS_MEMORY_WRITE_BIT;
+ stages |= VK_PIPELINE_STAGE_2_TRANSFER_BIT;
+ accessFlags |= VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT;
}
if constexpr ((TSyncOp & TRANSFER_READ) != 0)
{
- stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
- accessFlags |= VK_ACCESS_TRANSFER_READ_BIT;
-
- //accessFlags |= VK_ACCESS_MEMORY_READ_BIT;
+ stages |= VK_PIPELINE_STAGE_2_TRANSFER_BIT;
+ accessFlags |= VK_ACCESS_2_TRANSFER_READ_BIT;
}
if constexpr ((TSyncOp & TRANSFER_WRITE) != 0)
{
- stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
- accessFlags |= VK_ACCESS_TRANSFER_WRITE_BIT;
-
- //accessFlags |= VK_ACCESS_MEMORY_WRITE_BIT;
+ stages |= VK_PIPELINE_STAGE_2_TRANSFER_BIT;
+ accessFlags |= VK_ACCESS_2_TRANSFER_WRITE_BIT;
}
if constexpr ((TSyncOp & HOST_WRITE) != 0)
{
- stages |= VK_PIPELINE_STAGE_HOST_BIT;
- accessFlags |= VK_ACCESS_HOST_WRITE_BIT;
+ stages |= VK_PIPELINE_STAGE_2_HOST_BIT;
+ accessFlags |= VK_ACCESS_2_HOST_WRITE_BIT;
}
if constexpr ((TSyncOp & HOST_READ) != 0)
{
- stages |= VK_PIPELINE_STAGE_HOST_BIT;
- accessFlags |= VK_ACCESS_HOST_READ_BIT;
+ stages |= VK_PIPELINE_STAGE_2_HOST_BIT;
+ accessFlags |= VK_ACCESS_2_HOST_READ_BIT;
}
if constexpr ((TSyncOp & IMAGE_READ) != 0)
{
- stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- accessFlags |= VK_ACCESS_SHADER_READ_BIT;
+ stages |= VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
+ accessFlags |= VK_ACCESS_2_SHADER_READ_BIT;
- stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- accessFlags |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
+ stages |= VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
+ accessFlags |= VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT;
- stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
- accessFlags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
+ stages |= VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
+ accessFlags |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
}
if constexpr ((TSyncOp & IMAGE_WRITE) != 0)
{
- stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- accessFlags |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ stages |= VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
+ accessFlags |= VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
- stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
- accessFlags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+ stages |= VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
+ accessFlags |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
}
}
template
void barrier_bufferRange(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size)
{
- VkBufferMemoryBarrier bufMemBarrier{};
- bufMemBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+ VkBufferMemoryBarrier2 bufMemBarrier{};
+ bufMemBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2;
bufMemBarrier.pNext = nullptr;
bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- VkPipelineStageFlags srcStages = 0;
- VkPipelineStageFlags dstStages = 0;
-
- bufMemBarrier.srcAccessMask = 0;
- bufMemBarrier.dstAccessMask = 0;
-
- barrier_calcStageAndMask(srcStages, bufMemBarrier.srcAccessMask);
- barrier_calcStageAndMask(dstStages, bufMemBarrier.dstAccessMask);
+ barrier_calcStageAndMask(bufMemBarrier.srcStageMask, bufMemBarrier.srcAccessMask);
+ barrier_calcStageAndMask(bufMemBarrier.dstStageMask, bufMemBarrier.dstAccessMask);
bufMemBarrier.buffer = buffer;
bufMemBarrier.offset = offset;
bufMemBarrier.size = size;
- vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStages, dstStages, 0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
+
+ VkDependencyInfo depInfo{};
+ depInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
+ depInfo.pNext = nullptr;
+ depInfo.bufferMemoryBarrierCount = 1;
+ depInfo.pBufferMemoryBarriers = &bufMemBarrier;
+ vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &depInfo);
}
template
void barrier_bufferRange(VkBuffer bufferA, VkDeviceSize offsetA, VkDeviceSize sizeA,
VkBuffer bufferB, VkDeviceSize offsetB, VkDeviceSize sizeB)
{
- VkPipelineStageFlags srcStagesA = 0;
- VkPipelineStageFlags dstStagesA = 0;
- VkPipelineStageFlags srcStagesB = 0;
- VkPipelineStageFlags dstStagesB = 0;
+ VkBufferMemoryBarrier2 bufMemBarrier2[2] = {};
+ bufMemBarrier2[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR;
+ bufMemBarrier2[0].pNext = nullptr;
+ bufMemBarrier2[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier2[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier2[0].buffer = bufferA;
+ bufMemBarrier2[0].offset = offsetA;
+ bufMemBarrier2[0].size = sizeA;
+ barrier_calcStageAndMask(bufMemBarrier2[0].srcStageMask, bufMemBarrier2[0].srcAccessMask);
+ barrier_calcStageAndMask(bufMemBarrier2[0].dstStageMask, bufMemBarrier2[0].dstAccessMask);
- VkBufferMemoryBarrier bufMemBarrier[2];
+ bufMemBarrier2[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR;
+ bufMemBarrier2[1].pNext = nullptr;
+ bufMemBarrier2[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier2[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier2[1].buffer = bufferB;
+ bufMemBarrier2[1].offset = offsetB;
+ bufMemBarrier2[1].size = sizeB;
+ barrier_calcStageAndMask(bufMemBarrier2[1].srcStageMask, bufMemBarrier2[1].srcAccessMask);
+ barrier_calcStageAndMask(bufMemBarrier2[1].dstStageMask, bufMemBarrier2[1].dstAccessMask);
- bufMemBarrier[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
- bufMemBarrier[0].pNext = nullptr;
- bufMemBarrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- bufMemBarrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- bufMemBarrier[0].srcAccessMask = 0;
- bufMemBarrier[0].dstAccessMask = 0;
- barrier_calcStageAndMask(srcStagesA, bufMemBarrier[0].srcAccessMask);
- barrier_calcStageAndMask(dstStagesA, bufMemBarrier[0].dstAccessMask);
- bufMemBarrier[0].buffer = bufferA;
- bufMemBarrier[0].offset = offsetA;
- bufMemBarrier[0].size = sizeA;
-
- bufMemBarrier[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
- bufMemBarrier[1].pNext = nullptr;
- bufMemBarrier[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- bufMemBarrier[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- bufMemBarrier[1].srcAccessMask = 0;
- bufMemBarrier[1].dstAccessMask = 0;
- barrier_calcStageAndMask(srcStagesB, bufMemBarrier[1].srcAccessMask);
- barrier_calcStageAndMask(dstStagesB, bufMemBarrier[1].dstAccessMask);
- bufMemBarrier[1].buffer = bufferB;
- bufMemBarrier[1].offset = offsetB;
- bufMemBarrier[1].size = sizeB;
-
- vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStagesA|srcStagesB, dstStagesA|dstStagesB, 0, 0, nullptr, 2, bufMemBarrier, 0, nullptr);
+ VkDependencyInfo dependencyInfo = {};
+ dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
+ dependencyInfo.pNext = nullptr;
+ dependencyInfo.bufferMemoryBarrierCount = 2;
+ dependencyInfo.pBufferMemoryBarriers = bufMemBarrier2;
+ vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &dependencyInfo);
}
void barrier_sequentializeTransfer()
{
- VkMemoryBarrier memBarrier{};
- memBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
- memBarrier.pNext = nullptr;
+ VkMemoryBarrier2 memoryBarrier2{};
+ memoryBarrier2.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2;
+ memoryBarrier2.pNext = nullptr;
+ memoryBarrier2.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
+ memoryBarrier2.srcAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT;
+ memoryBarrier2.dstStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
+ memoryBarrier2.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT;
- VkPipelineStageFlags srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
- VkPipelineStageFlags dstStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
-
- memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
- memBarrier.dstAccessMask = 0;
-
- memBarrier.srcAccessMask |= (VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
- memBarrier.dstAccessMask |= (VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
-
- vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStages, dstStages, 0, 1, &memBarrier, 0, nullptr, 0, nullptr);
+ VkDependencyInfo dependencyInfo{};
+ dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
+ dependencyInfo.pNext = nullptr;
+ dependencyInfo.memoryBarrierCount = 1;
+ dependencyInfo.pMemoryBarriers = &memoryBarrier2;
+ dependencyInfo.bufferMemoryBarrierCount = 0;
+ dependencyInfo.imageMemoryBarrierCount = 0;
+ vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &dependencyInfo);
}
void barrier_sequentializeCommand()
{
- VkPipelineStageFlags srcStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
- VkPipelineStageFlags dstStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ VkMemoryBarrier2 memoryBarrier = {};
+ memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2;
+ memoryBarrier.srcStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR;
+ memoryBarrier.srcAccessMask = 0;
+ memoryBarrier.dstStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR;
+ memoryBarrier.dstAccessMask = 0;
- vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStages, dstStages, 0, 0, nullptr, 0, nullptr, 0, nullptr);
+ VkDependencyInfo dependencyInfo = {};
+ dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
+ dependencyInfo.dependencyFlags = 0;
+ dependencyInfo.memoryBarrierCount = 1;
+ dependencyInfo.pMemoryBarriers = &memoryBarrier;
+ vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &dependencyInfo);
}
template
void barrier_image(VkImage imageVk, VkImageSubresourceRange& subresourceRange, VkImageLayout oldLayout, VkImageLayout newLayout)
{
- VkPipelineStageFlags srcStages = 0;
- VkPipelineStageFlags dstStages = 0;
+ VkImageMemoryBarrier2 imageMemBarrier2{};
+ imageMemBarrier2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2;
+ imageMemBarrier2.oldLayout = oldLayout;
+ imageMemBarrier2.newLayout = newLayout;
+ imageMemBarrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ imageMemBarrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ imageMemBarrier2.image = imageVk;
+ imageMemBarrier2.subresourceRange = subresourceRange;
- VkImageMemoryBarrier imageMemBarrier{};
- imageMemBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- imageMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- imageMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- imageMemBarrier.srcAccessMask = 0;
- imageMemBarrier.dstAccessMask = 0;
- barrier_calcStageAndMask(srcStages, imageMemBarrier.srcAccessMask);
- barrier_calcStageAndMask(dstStages, imageMemBarrier.dstAccessMask);
- imageMemBarrier.image = imageVk;
- imageMemBarrier.subresourceRange = subresourceRange;
- imageMemBarrier.oldLayout = oldLayout;
- imageMemBarrier.newLayout = newLayout;
+ barrier_calcStageAndMask(imageMemBarrier2.srcStageMask, imageMemBarrier2.srcAccessMask);
+ barrier_calcStageAndMask(imageMemBarrier2.dstStageMask, imageMemBarrier2.dstAccessMask);
- vkCmdPipelineBarrier(m_state.currentCommandBuffer,
- srcStages, dstStages,
- 0,
- 0, NULL,
- 0, NULL,
- 1, &imageMemBarrier);
+ VkDependencyInfo dependencyInfo{};
+ dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
+ dependencyInfo.imageMemoryBarrierCount = 1;
+ dependencyInfo.pImageMemoryBarriers = &imageMemBarrier2;
+ vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &dependencyInfo);
}
template
@@ -942,7 +933,6 @@ private:
vkTexture->SetImageLayout(subresourceRange, newLayout);
}
-
public:
bool GetDisableMultithreadedCompilation() const { return m_featureControl.disableMultithreadedCompilation; }
bool UseTFViaSSBO() const { return m_featureControl.mode.useTFEmulationViaSSBO; }
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp
index 320357f1..b6cae7f7 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp
@@ -1033,29 +1033,18 @@ void VulkanRenderer::sync_inputTexturesChanged()
// barrier here
if (writeFlushRequired)
{
- VkMemoryBarrier memoryBarrier{};
- memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
- memoryBarrier.srcAccessMask = 0;
- memoryBarrier.dstAccessMask = 0;
-
- VkPipelineStageFlags srcStage = 0;
- VkPipelineStageFlags dstStage = 0;
-
- // src
- srcStage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- memoryBarrier.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
-
- srcStage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
- memoryBarrier.srcAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
-
- // dst
- dstStage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- memoryBarrier.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
-
- dstStage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- memoryBarrier.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
-
- vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStage, dstStage, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
+ VkMemoryBarrier2 memoryBarrier2{};
+ memoryBarrier2.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR;
+ memoryBarrier2.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR | VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR;
+ memoryBarrier2.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR;
+ memoryBarrier2.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR | VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR | VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR | VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR;
+ memoryBarrier2.dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR | VK_ACCESS_2_SHADER_READ_BIT_KHR;
+ VkDependencyInfo dependencyInfo{};
+ dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR;
+ dependencyInfo.dependencyFlags = 0;
+ dependencyInfo.memoryBarrierCount = 1;
+ dependencyInfo.pMemoryBarriers = &memoryBarrier2;
+ vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &dependencyInfo);
performanceMonitor.vk.numDrawBarriersPerFrame.increment();
From b8d81283e86f91238a166b25ac46281620a3260b Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Tue, 27 Feb 2024 00:15:43 +0100
Subject: [PATCH 040/319] Vulkan: Remove unnecessary index buffer for
backbuffer drawcall
---
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 18 +-----------------
.../HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 7 -------
2 files changed, 1 insertion(+), 24 deletions(-)
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index 631f1d0c..a86d3a1f 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -540,7 +540,6 @@ VulkanRenderer::VulkanRenderer()
QueryMemoryInfo();
QueryAvailableFormats();
- CreateBackbufferIndexBuffer();
CreateCommandPool();
CreateCommandBuffers();
CreateDescriptorPool();
@@ -624,7 +623,6 @@ VulkanRenderer::~VulkanRenderer()
DeleteNullObjects();
// delete buffers
- memoryManager->DeleteBuffer(m_indexBuffer, m_indexBufferMemory);
memoryManager->DeleteBuffer(m_uniformVarBuffer, m_uniformVarBufferMemory);
memoryManager->DeleteBuffer(m_textureReadbackBuffer, m_textureReadbackBufferMemory);
memoryManager->DeleteBuffer(m_xfbRingBuffer, m_xfbRingBufferMemory);
@@ -2836,18 +2834,6 @@ void VulkanRenderer::ClearColorImage(LatteTextureVk* vkTexture, uint32 sliceInde
vkTexture->SetImageLayout(subresourceRange, outputLayout);
}
-void VulkanRenderer::CreateBackbufferIndexBuffer()
-{
- const VkDeviceSize bufferSize = sizeof(uint16) * 6;
- memoryManager->CreateBuffer(bufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, m_indexBuffer, m_indexBufferMemory);
-
- uint16* data;
- vkMapMemory(m_logicalDevice, m_indexBufferMemory, 0, bufferSize, 0, (void**)&data);
- const uint16 tmp[] = { 0, 1, 2, 3, 4, 5 };
- std::copy(std::begin(tmp), std::end(tmp), data);
- vkUnmapMemory(m_logicalDevice, m_indexBufferMemory);
-}
-
void VulkanRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutputShader* shader, bool useLinearTexFilter, sint32 imageX, sint32 imageY, sint32 imageWidth, sint32 imageHeight, bool padView, bool clearBackground)
{
if(!AcquireNextSwapchainImage(!padView))
@@ -2906,11 +2892,9 @@ void VulkanRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
vkCmdBindPipeline(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
m_state.currentPipeline = pipeline;
- vkCmdBindIndexBuffer(m_state.currentCommandBuffer, m_indexBuffer, 0, VK_INDEX_TYPE_UINT16);
-
vkCmdBindDescriptorSets(m_state.currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, &descriptSet, 0, nullptr);
- vkCmdDrawIndexed(m_state.currentCommandBuffer, 6, 1, 0, 0, 0);
+ vkCmdDraw(m_state.currentCommandBuffer, 6, 1, 0, 0);
vkCmdEndRenderPass(m_state.currentCommandBuffer);
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
index 7565d260..3e55fc0c 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
@@ -548,15 +548,11 @@ private:
void sync_RenderPassStoreTextures(CachedFBOVk* fboVk);
// command buffer
-
VkCommandBuffer getCurrentCommandBuffer() const { return m_state.currentCommandBuffer; }
// uniform
void uniformData_updateUniformVars(uint32 shaderStageIndex, LatteDecompilerShader* shader);
- // indices
- void CreateBackbufferIndexBuffer();
-
// misc
void CreatePipelineCache();
VkPipelineShaderStageCreateInfo CreatePipelineShaderStageCreateInfo(VkShaderStageFlagBits stage, VkShaderModule& module, const char* entryName) const;
@@ -580,9 +576,6 @@ private:
void occlusionQuery_notifyBeginCommandBuffer();
private:
- VkBuffer m_indexBuffer = VK_NULL_HANDLE;
- VkDeviceMemory m_indexBufferMemory = VK_NULL_HANDLE;
-
std::vector m_layerNames;
VkInstance m_instance = VK_NULL_HANDLE;
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
From 9f9bc9865f23d3a1f07ce905003b7d5d640aab82 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Fri, 8 Mar 2024 03:12:26 +0100
Subject: [PATCH 041/319] Vulkan: Avoid calling vkCmdClearColorImage() on
compressed textures
This is not allowed according to the spec and can crash drivers. Fixes #1100
---
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 58 ++++++++++++-------
.../HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 1 -
2 files changed, 36 insertions(+), 23 deletions(-)
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index a86d3a1f..bb83607f 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -1412,8 +1412,7 @@ bool VulkanRenderer::IsSwapchainInfoValid(bool mainWindow) const
void VulkanRenderer::CreateNullTexture(NullTexture& nullTex, VkImageType imageType)
{
- // these are used when the game requests NULL ptr textures or buffers
- // texture
+ // these are used when the game requests NULL ptr textures
VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
if (imageType == VK_IMAGE_TYPE_1D)
@@ -2818,6 +2817,35 @@ void VulkanRenderer::ClearColorImageRaw(VkImage image, uint32 sliceIndex, uint32
void VulkanRenderer::ClearColorImage(LatteTextureVk* vkTexture, uint32 sliceIndex, uint32 mipIndex, const VkClearColorValue& color, VkImageLayout outputLayout)
{
+ if(vkTexture->isDepth)
+ {
+ cemu_assert_suspicious();
+ return;
+ }
+ if (vkTexture->IsCompressedFormat())
+ {
+ // vkCmdClearColorImage cannot be called on compressed formats
+ // for now we ignore affected clears but still transition the image to the correct layout
+ auto imageObj = vkTexture->GetImageObj();
+ imageObj->flagForCurrentCommandBuffer();
+ VkImageSubresourceLayers subresourceRange{};
+ subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ subresourceRange.mipLevel = mipIndex;
+ subresourceRange.baseArrayLayer = sliceIndex;
+ subresourceRange.layerCount = 1;
+ barrier_image(vkTexture, subresourceRange, outputLayout);
+ if(color.float32[0] == 0.0f && color.float32[1] == 0.0f && color.float32[2] == 0.0f && color.float32[3] == 0.0f)
+ {
+ static bool dbgMsgPrinted = false;
+ if(!dbgMsgPrinted)
+ {
+ cemuLog_logDebug(LogType::Force, "Unsupported compressed texture clear to zero");
+ dbgMsgPrinted = true;
+ }
+ }
+ return;
+ }
+
VkImageSubresourceRange subresourceRange;
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
@@ -3154,32 +3182,18 @@ void VulkanRenderer::texture_clearSlice(LatteTexture* hostTexture, sint32 sliceI
else
{
cemu_assert_debug(vkTexture->dim != Latte::E_DIM::DIM_3D);
- if (hostTexture->IsCompressedFormat())
- {
- auto imageObj = vkTexture->GetImageObj();
- imageObj->flagForCurrentCommandBuffer();
-
- cemuLog_logDebug(LogType::Force, "Compressed texture ({}/{} fmt {:04x}) unsupported clear", vkTexture->width, vkTexture->height, (uint32)vkTexture->format);
-
- VkImageSubresourceLayers subresourceRange{};
- subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- subresourceRange.mipLevel = mipIndex;
- subresourceRange.baseArrayLayer = sliceIndex;
- subresourceRange.layerCount = 1;
- barrier_image(vkTexture, subresourceRange, VK_IMAGE_LAYOUT_GENERAL);
- }
- else
- {
- ClearColorImage(vkTexture, sliceIndex, mipIndex, { 0,0,0,0 }, VK_IMAGE_LAYOUT_GENERAL);
- }
+ ClearColorImage(vkTexture, sliceIndex, mipIndex, { 0,0,0,0 }, VK_IMAGE_LAYOUT_GENERAL);
}
}
void VulkanRenderer::texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a)
{
auto vkTexture = (LatteTextureVk*)hostTexture;
- cemu_assert_debug(vkTexture->dim != Latte::E_DIM::DIM_3D);
- ClearColorImage(vkTexture, sliceIndex, mipIndex, { r,g,b,a }, VK_IMAGE_LAYOUT_GENERAL);
+ if(vkTexture->dim == Latte::E_DIM::DIM_3D)
+ {
+ cemu_assert_unimplemented();
+ }
+ ClearColorImage(vkTexture, sliceIndex, mipIndex, {r, g, b, a}, VK_IMAGE_LAYOUT_GENERAL);
}
void VulkanRenderer::texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sliceIndex, sint32 mipIndex, bool clearDepth, bool clearStencil, float depthValue, uint32 stencilValue)
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
index 3e55fc0c..d4eda785 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
@@ -130,7 +130,6 @@ class VulkanRenderer : public Renderer
using QueueFamilyIndices = SwapchainInfoVk::QueueFamilyIndices;
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 TEXTURE_READBACK_SIZE = 32 * 1024 * 1024; // 32 MB
From ea68f787eb6b8054805502a8b4aabae08ae59d94 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Fri, 8 Mar 2024 14:41:01 +0100
Subject: [PATCH 042/319] Vulkan: For MSAA surface copies make the target MSAA
too
Fixes #1108
---
src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp | 2 +-
src/Cafe/HW/Latte/ISA/LatteReg.h | 5 +++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp b/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp
index 4f5b24ad..45be6843 100644
--- a/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp
@@ -37,7 +37,7 @@ void LatteSurfaceCopy_copySurfaceNew(MPTR srcPhysAddr, MPTR srcMipAddr, uint32 s
if (!destinationTexture)
{
LatteTexture* renderTargetConf = nullptr;
- destinationView = LatteTexture_CreateMapping(dstPhysAddr, dstMipAddr, dstWidth, dstHeight, dstDepth, dstPitch, dstTilemode, dstSwizzle, dstLevel, 1, dstSlice, 1, dstSurfaceFormat, dstDim, Latte::E_DIM::DIM_2D, false);
+ destinationView = LatteTexture_CreateMapping(dstPhysAddr, dstMipAddr, dstWidth, dstHeight, dstDepth, dstPitch, dstTilemode, dstSwizzle, dstLevel, 1, dstSlice, 1, dstSurfaceFormat, dstDim, Latte::IsMSAA(dstDim) ? Latte::E_DIM::DIM_2D_MSAA : Latte::E_DIM::DIM_2D, false);
destinationTexture = destinationView->baseTexture;
}
// copy texture
diff --git a/src/Cafe/HW/Latte/ISA/LatteReg.h b/src/Cafe/HW/Latte/ISA/LatteReg.h
index d571dc6e..d1a2a028 100644
--- a/src/Cafe/HW/Latte/ISA/LatteReg.h
+++ b/src/Cafe/HW/Latte/ISA/LatteReg.h
@@ -345,6 +345,11 @@ namespace Latte
return IsCompressedFormat((Latte::E_HWSURFFMT)((uint32)format & 0x3F));
}
+ inline bool IsMSAA(Latte::E_DIM dim)
+ {
+ return dim == E_DIM::DIM_2D_MSAA || dim == E_DIM::DIM_2D_ARRAY_MSAA;
+ }
+
enum GPU_LIMITS
{
NUM_VERTEX_BUFFERS = 16,
From b390023bc5b04a0b50c6fd2a1bc10feb19a22f59 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Fri, 8 Mar 2024 14:48:59 +0100
Subject: [PATCH 043/319] README.md: Fix minor ambiguity
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index e57cb483..dfd35791 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,7 @@ Before submitting a pull request, please read and follow our code style guidelin
If coding isn't your thing, testing games and making detailed bug reports or updating the (usually outdated) compatibility wiki is also appreciated!
-Questions about Cemu's software architecture can also be answered on Discord (through the Matrix bridge).
+Questions about Cemu's software architecture can also be answered on Discord (or through the Matrix bridge).
## License
Cemu is licensed under [Mozilla Public License 2.0](/LICENSE.txt). Exempt from this are all files in the dependencies directory for which the licenses of the original code apply as well as some individual files in the src folder, as specified in those file headers respectively.
From d9e8ca2c833e2b2adf8f1c1cc71f7846fd87b816 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Sat, 9 Mar 2024 02:25:40 +0100
Subject: [PATCH 044/319] Revert "Vulkan: Update some code to use
VK_KHR_synchronization2"
This reverts commit 8f1cd4f9255e16aeddb2e72d35a47f37e1e478bc.
We received reports from users stuck with Vulkan drivers from 2019. (E.g. Kepler on Windows). So let's not unnecessarily increase the Vulkan requirement for now and postpone this to after the next stable release
---
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 30 +--
.../HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 220 +++++++++---------
.../Renderer/Vulkan/VulkanRendererCore.cpp | 35 ++-
3 files changed, 145 insertions(+), 140 deletions(-)
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index bb83607f..8711359e 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -468,15 +468,6 @@ VulkanRenderer::VulkanRenderer()
void* deviceExtensionFeatures = nullptr;
- // enable VK_KHR_synchonization_2
- VkPhysicalDeviceSynchronization2FeaturesKHR sync2Feature{};
- {
- sync2Feature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR;
- sync2Feature.pNext = deviceExtensionFeatures;
- deviceExtensionFeatures = &sync2Feature;
- sync2Feature.synchronization2 = VK_TRUE;
- }
-
// enable VK_EXT_pipeline_creation_cache_control
VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT cacheControlFeature{};
if (m_featureControl.deviceExtensions.pipeline_creation_cache_control)
@@ -2875,20 +2866,13 @@ void VulkanRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
ClearColorbuffer(padView);
// barrier for input texture
- {
- VkMemoryBarrier2 memoryBarrier2{};
- memoryBarrier2.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2;
- memoryBarrier2.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR | VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR;
- memoryBarrier2.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR | VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR | VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR;
- memoryBarrier2.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT;
- memoryBarrier2.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT;
- VkDependencyInfo dependencyInfo{};
- dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
- dependencyInfo.dependencyFlags = 0;
- dependencyInfo.memoryBarrierCount = 1;
- dependencyInfo.pMemoryBarriers = &memoryBarrier2;
- vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &dependencyInfo);
- }
+ VkMemoryBarrier memoryBarrier{};
+ memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
+ VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
+ memoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
+ vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStage, dstStage, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
auto pipeline = backbufferBlit_createGraphicsPipeline(m_swapchainDescriptorSetLayout, padView, shader);
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
index d4eda785..479c9e54 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
@@ -720,192 +720,201 @@ private:
IMAGE_READ = 0x20,
IMAGE_WRITE = 0x40,
+
};
template
- void barrier_calcStageAndMask(VkPipelineStageFlags2& stages, VkAccessFlags2& accessFlags)
+ void barrier_calcStageAndMask(VkPipelineStageFlags& stages, VkAccessFlags& accessFlags)
{
stages = 0;
accessFlags = 0;
if constexpr ((TSyncOp & BUFFER_SHADER_READ) != 0)
{
- // in theory: VK_ACCESS_2_INDEX_READ_BIT should be set here too but indices are currently separated
- stages |= VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
- accessFlags |= VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_2_UNIFORM_READ_BIT | VK_ACCESS_2_SHADER_READ_BIT;
+ // in theory: VK_ACCESS_INDEX_READ_BIT should be set here too but indices are currently separated
+ stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ accessFlags |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
}
-
+
if constexpr ((TSyncOp & BUFFER_SHADER_WRITE) != 0)
{
- stages |= VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
- accessFlags |= VK_ACCESS_2_SHADER_WRITE_BIT;
+ stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ accessFlags |= VK_ACCESS_SHADER_WRITE_BIT;
}
if constexpr ((TSyncOp & ANY_TRANSFER) != 0)
{
- stages |= VK_PIPELINE_STAGE_2_TRANSFER_BIT;
- accessFlags |= VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT;
+ //stages |= VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_HOST_BIT;
+ //accessFlags |= VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT;
+ stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ accessFlags |= VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
+
+ //accessFlags |= VK_ACCESS_MEMORY_READ_BIT;
+ //accessFlags |= VK_ACCESS_MEMORY_WRITE_BIT;
}
if constexpr ((TSyncOp & TRANSFER_READ) != 0)
{
- stages |= VK_PIPELINE_STAGE_2_TRANSFER_BIT;
- accessFlags |= VK_ACCESS_2_TRANSFER_READ_BIT;
+ stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ accessFlags |= VK_ACCESS_TRANSFER_READ_BIT;
+
+ //accessFlags |= VK_ACCESS_MEMORY_READ_BIT;
}
if constexpr ((TSyncOp & TRANSFER_WRITE) != 0)
{
- stages |= VK_PIPELINE_STAGE_2_TRANSFER_BIT;
- accessFlags |= VK_ACCESS_2_TRANSFER_WRITE_BIT;
+ stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+ accessFlags |= VK_ACCESS_TRANSFER_WRITE_BIT;
+
+ //accessFlags |= VK_ACCESS_MEMORY_WRITE_BIT;
}
if constexpr ((TSyncOp & HOST_WRITE) != 0)
{
- stages |= VK_PIPELINE_STAGE_2_HOST_BIT;
- accessFlags |= VK_ACCESS_2_HOST_WRITE_BIT;
+ stages |= VK_PIPELINE_STAGE_HOST_BIT;
+ accessFlags |= VK_ACCESS_HOST_WRITE_BIT;
}
if constexpr ((TSyncOp & HOST_READ) != 0)
{
- stages |= VK_PIPELINE_STAGE_2_HOST_BIT;
- accessFlags |= VK_ACCESS_2_HOST_READ_BIT;
+ stages |= VK_PIPELINE_STAGE_HOST_BIT;
+ accessFlags |= VK_ACCESS_HOST_READ_BIT;
}
if constexpr ((TSyncOp & IMAGE_READ) != 0)
{
- stages |= VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
- accessFlags |= VK_ACCESS_2_SHADER_READ_BIT;
+ stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ accessFlags |= VK_ACCESS_SHADER_READ_BIT;
- stages |= VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
- accessFlags |= VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT;
+ stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ accessFlags |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
- stages |= VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
- accessFlags |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
+ stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ accessFlags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
}
if constexpr ((TSyncOp & IMAGE_WRITE) != 0)
{
- stages |= VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
- accessFlags |= VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
+ stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ accessFlags |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- stages |= VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
- accessFlags |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+ stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ accessFlags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
}
}
template
void barrier_bufferRange(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size)
{
- VkBufferMemoryBarrier2 bufMemBarrier{};
- bufMemBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2;
+ VkBufferMemoryBarrier bufMemBarrier{};
+ bufMemBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
bufMemBarrier.pNext = nullptr;
bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier_calcStageAndMask(bufMemBarrier.srcStageMask, bufMemBarrier.srcAccessMask);
- barrier_calcStageAndMask(bufMemBarrier.dstStageMask, bufMemBarrier.dstAccessMask);
+ VkPipelineStageFlags srcStages = 0;
+ VkPipelineStageFlags dstStages = 0;
+
+ bufMemBarrier.srcAccessMask = 0;
+ bufMemBarrier.dstAccessMask = 0;
+
+ barrier_calcStageAndMask(srcStages, bufMemBarrier.srcAccessMask);
+ barrier_calcStageAndMask(dstStages, bufMemBarrier.dstAccessMask);
bufMemBarrier.buffer = buffer;
bufMemBarrier.offset = offset;
bufMemBarrier.size = size;
-
- VkDependencyInfo depInfo{};
- depInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
- depInfo.pNext = nullptr;
- depInfo.bufferMemoryBarrierCount = 1;
- depInfo.pBufferMemoryBarriers = &bufMemBarrier;
- vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &depInfo);
+ vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStages, dstStages, 0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
}
template
void barrier_bufferRange(VkBuffer bufferA, VkDeviceSize offsetA, VkDeviceSize sizeA,
VkBuffer bufferB, VkDeviceSize offsetB, VkDeviceSize sizeB)
{
- VkBufferMemoryBarrier2 bufMemBarrier2[2] = {};
- bufMemBarrier2[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR;
- bufMemBarrier2[0].pNext = nullptr;
- bufMemBarrier2[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- bufMemBarrier2[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- bufMemBarrier2[0].buffer = bufferA;
- bufMemBarrier2[0].offset = offsetA;
- bufMemBarrier2[0].size = sizeA;
- barrier_calcStageAndMask(bufMemBarrier2[0].srcStageMask, bufMemBarrier2[0].srcAccessMask);
- barrier_calcStageAndMask(bufMemBarrier2[0].dstStageMask, bufMemBarrier2[0].dstAccessMask);
+ VkPipelineStageFlags srcStagesA = 0;
+ VkPipelineStageFlags dstStagesA = 0;
+ VkPipelineStageFlags srcStagesB = 0;
+ VkPipelineStageFlags dstStagesB = 0;
- bufMemBarrier2[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR;
- bufMemBarrier2[1].pNext = nullptr;
- bufMemBarrier2[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- bufMemBarrier2[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- bufMemBarrier2[1].buffer = bufferB;
- bufMemBarrier2[1].offset = offsetB;
- bufMemBarrier2[1].size = sizeB;
- barrier_calcStageAndMask(bufMemBarrier2[1].srcStageMask, bufMemBarrier2[1].srcAccessMask);
- barrier_calcStageAndMask(bufMemBarrier2[1].dstStageMask, bufMemBarrier2[1].dstAccessMask);
+ VkBufferMemoryBarrier bufMemBarrier[2];
- VkDependencyInfo dependencyInfo = {};
- dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
- dependencyInfo.pNext = nullptr;
- dependencyInfo.bufferMemoryBarrierCount = 2;
- dependencyInfo.pBufferMemoryBarriers = bufMemBarrier2;
- vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &dependencyInfo);
+ bufMemBarrier[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+ bufMemBarrier[0].pNext = nullptr;
+ bufMemBarrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier[0].srcAccessMask = 0;
+ bufMemBarrier[0].dstAccessMask = 0;
+ barrier_calcStageAndMask(srcStagesA, bufMemBarrier[0].srcAccessMask);
+ barrier_calcStageAndMask(dstStagesA, bufMemBarrier[0].dstAccessMask);
+ bufMemBarrier[0].buffer = bufferA;
+ bufMemBarrier[0].offset = offsetA;
+ bufMemBarrier[0].size = sizeA;
+
+ bufMemBarrier[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+ bufMemBarrier[1].pNext = nullptr;
+ bufMemBarrier[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier[1].srcAccessMask = 0;
+ bufMemBarrier[1].dstAccessMask = 0;
+ barrier_calcStageAndMask(srcStagesB, bufMemBarrier[1].srcAccessMask);
+ barrier_calcStageAndMask(dstStagesB, bufMemBarrier[1].dstAccessMask);
+ bufMemBarrier[1].buffer = bufferB;
+ bufMemBarrier[1].offset = offsetB;
+ bufMemBarrier[1].size = sizeB;
+
+ vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStagesA|srcStagesB, dstStagesA|dstStagesB, 0, 0, nullptr, 2, bufMemBarrier, 0, nullptr);
}
void barrier_sequentializeTransfer()
{
- VkMemoryBarrier2 memoryBarrier2{};
- memoryBarrier2.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2;
- memoryBarrier2.pNext = nullptr;
- memoryBarrier2.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
- memoryBarrier2.srcAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT;
- memoryBarrier2.dstStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
- memoryBarrier2.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT;
+ VkMemoryBarrier memBarrier{};
+ memBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ memBarrier.pNext = nullptr;
- VkDependencyInfo dependencyInfo{};
- dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
- dependencyInfo.pNext = nullptr;
- dependencyInfo.memoryBarrierCount = 1;
- dependencyInfo.pMemoryBarriers = &memoryBarrier2;
- dependencyInfo.bufferMemoryBarrierCount = 0;
- dependencyInfo.imageMemoryBarrierCount = 0;
- vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &dependencyInfo);
+ VkPipelineStageFlags srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ VkPipelineStageFlags dstStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+
+ memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
+ memBarrier.dstAccessMask = 0;
+
+ memBarrier.srcAccessMask |= (VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
+ memBarrier.dstAccessMask |= (VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
+
+ vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStages, dstStages, 0, 1, &memBarrier, 0, nullptr, 0, nullptr);
}
void barrier_sequentializeCommand()
{
- VkMemoryBarrier2 memoryBarrier = {};
- memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2;
- memoryBarrier.srcStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR;
- memoryBarrier.srcAccessMask = 0;
- memoryBarrier.dstStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR;
- memoryBarrier.dstAccessMask = 0;
+ VkPipelineStageFlags srcStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ VkPipelineStageFlags dstStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- VkDependencyInfo dependencyInfo = {};
- dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
- dependencyInfo.dependencyFlags = 0;
- dependencyInfo.memoryBarrierCount = 1;
- dependencyInfo.pMemoryBarriers = &memoryBarrier;
- vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &dependencyInfo);
+ vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStages, dstStages, 0, 0, nullptr, 0, nullptr, 0, nullptr);
}
template
void barrier_image(VkImage imageVk, VkImageSubresourceRange& subresourceRange, VkImageLayout oldLayout, VkImageLayout newLayout)
{
- VkImageMemoryBarrier2 imageMemBarrier2{};
- imageMemBarrier2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2;
- imageMemBarrier2.oldLayout = oldLayout;
- imageMemBarrier2.newLayout = newLayout;
- imageMemBarrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- imageMemBarrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- imageMemBarrier2.image = imageVk;
- imageMemBarrier2.subresourceRange = subresourceRange;
+ VkPipelineStageFlags srcStages = 0;
+ VkPipelineStageFlags dstStages = 0;
- barrier_calcStageAndMask(imageMemBarrier2.srcStageMask, imageMemBarrier2.srcAccessMask);
- barrier_calcStageAndMask(imageMemBarrier2.dstStageMask, imageMemBarrier2.dstAccessMask);
+ VkImageMemoryBarrier imageMemBarrier{};
+ imageMemBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ imageMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ imageMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ imageMemBarrier.srcAccessMask = 0;
+ imageMemBarrier.dstAccessMask = 0;
+ barrier_calcStageAndMask(srcStages, imageMemBarrier.srcAccessMask);
+ barrier_calcStageAndMask(dstStages, imageMemBarrier.dstAccessMask);
+ imageMemBarrier.image = imageVk;
+ imageMemBarrier.subresourceRange = subresourceRange;
+ imageMemBarrier.oldLayout = oldLayout;
+ imageMemBarrier.newLayout = newLayout;
- VkDependencyInfo dependencyInfo{};
- dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
- dependencyInfo.imageMemoryBarrierCount = 1;
- dependencyInfo.pImageMemoryBarriers = &imageMemBarrier2;
- vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &dependencyInfo);
+ vkCmdPipelineBarrier(m_state.currentCommandBuffer,
+ srcStages, dstStages,
+ 0,
+ 0, NULL,
+ 0, NULL,
+ 1, &imageMemBarrier);
}
template
@@ -925,6 +934,7 @@ private:
vkTexture->SetImageLayout(subresourceRange, newLayout);
}
+
public:
bool GetDisableMultithreadedCompilation() const { return m_featureControl.disableMultithreadedCompilation; }
bool UseTFViaSSBO() const { return m_featureControl.mode.useTFEmulationViaSSBO; }
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp
index b6cae7f7..320357f1 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp
@@ -1033,18 +1033,29 @@ void VulkanRenderer::sync_inputTexturesChanged()
// barrier here
if (writeFlushRequired)
{
- VkMemoryBarrier2 memoryBarrier2{};
- memoryBarrier2.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR;
- memoryBarrier2.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR | VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR;
- memoryBarrier2.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR;
- memoryBarrier2.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR | VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR | VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR | VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR;
- memoryBarrier2.dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR | VK_ACCESS_2_SHADER_READ_BIT_KHR;
- VkDependencyInfo dependencyInfo{};
- dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR;
- dependencyInfo.dependencyFlags = 0;
- dependencyInfo.memoryBarrierCount = 1;
- dependencyInfo.pMemoryBarriers = &memoryBarrier2;
- vkCmdPipelineBarrier2KHR(m_state.currentCommandBuffer, &dependencyInfo);
+ VkMemoryBarrier memoryBarrier{};
+ memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ memoryBarrier.srcAccessMask = 0;
+ memoryBarrier.dstAccessMask = 0;
+
+ VkPipelineStageFlags srcStage = 0;
+ VkPipelineStageFlags dstStage = 0;
+
+ // src
+ srcStage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ memoryBarrier.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ srcStage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ memoryBarrier.srcAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+
+ // dst
+ dstStage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ memoryBarrier.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
+
+ dstStage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ memoryBarrier.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
+
+ vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStage, dstStage, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
performanceMonitor.vk.numDrawBarriersPerFrame.increment();
From f69fddc6e50aabf71d1c78e73d7bcd6545b8ab92 Mon Sep 17 00:00:00 2001
From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com>
Date: Sun, 10 Mar 2024 23:25:16 +0100
Subject: [PATCH 045/319] TitleManager: Fix crash when sorting by format
(#1113)
---
src/gui/components/wxTitleManagerList.cpp | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/gui/components/wxTitleManagerList.cpp b/src/gui/components/wxTitleManagerList.cpp
index d6ad8118..c02bffb7 100644
--- a/src/gui/components/wxTitleManagerList.cpp
+++ b/src/gui/components/wxTitleManagerList.cpp
@@ -1143,7 +1143,7 @@ bool wxTitleManagerList::SortFunc(int column, const Type_t& v1, const Type_t& v2
// check column: title id -> type -> path
if (column == ColumnTitleId)
{
- // ensure strong ordering -> use type since only one entry should be now (should be changed if every save for every user is displayed spearately?)
+ // ensure strong ordering -> use type since only one entry should be now (should be changed if every save for every user is displayed separately?)
if (entry1.title_id == entry2.title_id)
return SortFunc(ColumnType, v1, v2);
@@ -1159,7 +1159,7 @@ bool wxTitleManagerList::SortFunc(int column, const Type_t& v1, const Type_t& v2
}
else if (column == ColumnType)
{
- if(std::underlying_type_t(entry1.type) == std::underlying_type_t(entry2.type))
+ if(entry1.type == entry2.type)
return SortFunc(-1, v1, v2);
return std::underlying_type_t(entry1.type) < std::underlying_type_t(entry2.type);
@@ -1178,6 +1178,13 @@ bool wxTitleManagerList::SortFunc(int column, const Type_t& v1, const Type_t& v2
return std::underlying_type_t(entry1.region) < std::underlying_type_t(entry2.region);
}
+ else if (column == ColumnFormat)
+ {
+ if(entry1.format == entry2.format)
+ return SortFunc(ColumnType, v1, v2);
+
+ return std::underlying_type_t(entry1.format) < std::underlying_type_t(entry2.format);
+ }
return false;
}
From a2d74972d4e0cd3b61dc4deb32566fc385942963 Mon Sep 17 00:00:00 2001
From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com>
Date: Mon, 11 Mar 2024 00:55:31 +0100
Subject: [PATCH 046/319] Prevent changing of console language while a game is
running (#1114)
---
src/gui/MainWindow.cpp | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index d271ca3a..311ddfb7 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -1019,8 +1019,11 @@ void MainWindow::OnConsoleLanguage(wxCommandEvent& event)
default:
cemu_assert_debug(false);
}
- m_game_list->DeleteCachedStrings();
- m_game_list->ReloadGameEntries(false);
+ if (m_game_list)
+ {
+ m_game_list->DeleteCachedStrings();
+ m_game_list->ReloadGameEntries(false);
+ }
g_config.Save();
}
@@ -2159,6 +2162,14 @@ void MainWindow::RecreateMenu()
optionsConsoleLanguageMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_LANGUAGE_PORTUGUESE, _("&Portuguese"), wxEmptyString)->Check(config.console_language == CafeConsoleLanguage::PT);
optionsConsoleLanguageMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_LANGUAGE_RUSSIAN, _("&Russian"), wxEmptyString)->Check(config.console_language == CafeConsoleLanguage::RU);
optionsConsoleLanguageMenu->AppendRadioItem(MAINFRAME_MENU_ID_OPTIONS_LANGUAGE_TAIWANESE, _("&Taiwanese"), wxEmptyString)->Check(config.console_language == CafeConsoleLanguage::TW);
+ if(IsGameLaunched())
+ {
+ auto items = optionsConsoleLanguageMenu->GetMenuItems();
+ for (auto& item : items)
+ {
+ item->Enable(false);
+ }
+ }
// options submenu
wxMenu* optionsMenu = new wxMenu();
From e1435066ee0ccc65e3ec6244c334214243236883 Mon Sep 17 00:00:00 2001
From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com>
Date: Mon, 11 Mar 2024 00:57:31 +0100
Subject: [PATCH 047/319] OpenGL: Fix crash related to wxWidgets handling of
vsync (#1112)
---
.../HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp | 14 ++++++++++++++
src/Common/GLInclude/GLInclude.h | 4 ++++
2 files changed, 18 insertions(+)
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
index f09f04f1..8548fa1c 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
@@ -24,11 +24,14 @@
#define STRINGIFY2(X) #X
#define STRINGIFY(X) STRINGIFY2(X)
+namespace CemuGL
+{
#define GLFUNC(__type, __name) __type __name;
#define EGLFUNC(__type, __name) __type __name;
#include "Common/GLInclude/glFunctions.h"
#undef GLFUNC
#undef EGLFUNC
+}
#include "config/ActiveSettings.h"
#include "config/LaunchSettings.h"
@@ -241,6 +244,17 @@ void LoadOpenGLImports()
#undef GLFUNC
#undef EGLFUNC
}
+
+#if BOOST_OS_LINUX
+// dummy function for all code that is statically linked with cemu and attempts to use eglSwapInterval
+// used to suppress wxWidgets calls to eglSwapInterval
+extern "C"
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval)
+{
+ return EGL_TRUE;
+}
+#endif
+
#elif BOOST_OS_MACOS
void LoadOpenGLImports()
{
diff --git a/src/Common/GLInclude/GLInclude.h b/src/Common/GLInclude/GLInclude.h
index bf7a6bf8..86df0232 100644
--- a/src/Common/GLInclude/GLInclude.h
+++ b/src/Common/GLInclude/GLInclude.h
@@ -36,6 +36,8 @@ typedef struct __GLXFBConfigRec *GLXFBConfig;
#endif
+namespace CemuGL
+{
#define GLFUNC(__type, __name) extern __type __name;
#define EGLFUNC(__type, __name) extern __type __name;
#include "glFunctions.h"
@@ -213,6 +215,8 @@ static void glCompressedTextureSubImage3DWrapper(GLenum target, GLuint texture,
glBindTexture(target, originalTexture);
}
+}
+using namespace CemuGL;
// this prevents Windows GL.h from being included:
#define __gl_h_
#define __GL_H__
From 788da3cdf73741a10f714772b74b0675e2e98282 Mon Sep 17 00:00:00 2001
From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com>
Date: Mon, 11 Mar 2024 01:47:31 +0100
Subject: [PATCH 048/319] CafeSystem: Init recompiler after game profile has
been loaded (#1115)
---
src/Cafe/CafeSystem.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp
index 30dab1d4..76f8ae70 100644
--- a/src/Cafe/CafeSystem.cpp
+++ b/src/Cafe/CafeSystem.cpp
@@ -779,10 +779,10 @@ namespace CafeSystem
return r;
// setup memory space and PPC recompiler
SetupMemorySpace();
- PPCRecompiler_init();
r = SetupExecutable(); // load RPX
if (r != STATUS_CODE::SUCCESS)
return r;
+ PPCRecompiler_init();
InitVirtualMlcStorage();
return STATUS_CODE::SUCCESS;
}
@@ -821,11 +821,11 @@ namespace CafeSystem
uint32 h = generateHashFromRawRPXData(execData->data(), execData->size());
sForegroundTitleId = 0xFFFFFFFF00000000ULL | (uint64)h;
cemuLog_log(LogType::Force, "Generated placeholder TitleId: {:016x}", sForegroundTitleId);
- // setup memory space and ppc recompiler
+ // setup memory space
SetupMemorySpace();
- PPCRecompiler_init();
// load executable
SetupExecutable();
+ PPCRecompiler_init();
InitVirtualMlcStorage();
return STATUS_CODE::SUCCESS;
}
From ccabd9315947cedbbf198c1e0dabffe963b67550 Mon Sep 17 00:00:00 2001
From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com>
Date: Mon, 11 Mar 2024 02:13:53 +0100
Subject: [PATCH 049/319] Linux: Exit on SIGTERM (#1116)
---
src/Common/ExceptionHandler/ExceptionHandler_posix.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp
index cf547110..7afbf191 100644
--- a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp
+++ b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp
@@ -155,6 +155,7 @@ void ExceptionHandler_Init()
action.sa_handler = handler_SIGINT;
sigaction(SIGINT, &action, nullptr);
+ sigaction(SIGTERM, &action, nullptr);
action.sa_flags = SA_SIGINFO;
action.sa_handler = nullptr;
From bb88b5c36dd145c4d176b26b749c0817c300b2e6 Mon Sep 17 00:00:00 2001
From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com>
Date: Mon, 11 Mar 2024 02:40:47 +0100
Subject: [PATCH 050/319] Fix crash introduced by #1115 (#1117)
* Revert "CafeSystem: Init recompiler after game profile has been loaded (#1115)"
* Instead move gameprofile load call
---
src/Cafe/CafeSystem.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp
index 76f8ae70..75cb1116 100644
--- a/src/Cafe/CafeSystem.cpp
+++ b/src/Cafe/CafeSystem.cpp
@@ -748,7 +748,6 @@ namespace CafeSystem
}
}
LoadMainExecutable();
- gameProfile_load();
return STATUS_CODE::SUCCESS;
}
@@ -777,12 +776,13 @@ namespace CafeSystem
STATUS_CODE r = LoadAndMountForegroundTitle(titleId);
if (r != STATUS_CODE::SUCCESS)
return r;
+ gameProfile_load();
// setup memory space and PPC recompiler
SetupMemorySpace();
+ PPCRecompiler_init();
r = SetupExecutable(); // load RPX
if (r != STATUS_CODE::SUCCESS)
return r;
- PPCRecompiler_init();
InitVirtualMlcStorage();
return STATUS_CODE::SUCCESS;
}
@@ -821,11 +821,11 @@ namespace CafeSystem
uint32 h = generateHashFromRawRPXData(execData->data(), execData->size());
sForegroundTitleId = 0xFFFFFFFF00000000ULL | (uint64)h;
cemuLog_log(LogType::Force, "Generated placeholder TitleId: {:016x}", sForegroundTitleId);
- // setup memory space
+ // setup memory space and ppc recompiler
SetupMemorySpace();
+ PPCRecompiler_init();
// load executable
SetupExecutable();
- PPCRecompiler_init();
InitVirtualMlcStorage();
return STATUS_CODE::SUCCESS;
}
From 3d0d987d895686d749073006c9eca96aa650b9ac Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Sun, 10 Mar 2024 01:10:19 +0100
Subject: [PATCH 051/319] Logging: Introduce logOnce helper
For cases where printing a message once is enough and to avoid spamming log.txt
---
src/Cemu/Logging/CemuLogging.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/Cemu/Logging/CemuLogging.h b/src/Cemu/Logging/CemuLogging.h
index 728c8b93..388e51ab 100644
--- a/src/Cemu/Logging/CemuLogging.h
+++ b/src/Cemu/Logging/CemuLogging.h
@@ -7,7 +7,7 @@ enum class LogType : sint32
// note: IDs must be in range 1-64
Force = 63, // always enabled
Placeholder = 62, // always disabled
- APIErrors = Force, // alias for Force. Logs bad parameters or other API errors in OS libs
+ APIErrors = Force, // alias for Force. Logs bad parameters or other API usage mistakes or unintended errors in OS libs
CoreinitFile = 0,
GX2 = 1,
@@ -99,6 +99,8 @@ bool cemuLog_log(LogType type, const T* format, TArgs&&... args)
return cemuLog_log(type, format_str, std::forward(args)...);
}
+#define cemuLog_logOnce(...) { static bool _not_first_call = false; if (!_not_first_call) { _not_first_call = true; cemuLog_log(__VA_ARGS__); } }
+
// same as cemuLog_log, but only outputs in debug mode
template
bool cemuLog_logDebug(LogType type, TFmt format, TArgs&&... args)
From 0993658c82e89dbda35d29b36a69d1e9e3d47678 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Sun, 10 Mar 2024 01:21:04 +0100
Subject: [PATCH 052/319] GX2: Rework GX2Set*UniformReg
- Use cafeExportRegister() instead of legacy export
- Submit as a single PM4 packet
- Add logging for the special case of the size parameter (not sure if this is used by any game?)
- Add some extra validation and logging which may be helpful to homebrew devs
---
src/Cafe/OS/libs/gx2/GX2.cpp | 3 --
src/Cafe/OS/libs/gx2/GX2.h | 2 --
src/Cafe/OS/libs/gx2/GX2_Shader.cpp | 34 +++++++++++++++++++++
src/Cafe/OS/libs/gx2/GX2_shader_legacy.cpp | 35 ----------------------
src/Cafe/OS/libs/nn_act/nn_act.cpp | 2 --
5 files changed, 34 insertions(+), 42 deletions(-)
diff --git a/src/Cafe/OS/libs/gx2/GX2.cpp b/src/Cafe/OS/libs/gx2/GX2.cpp
index 82aef164..c2ea34a4 100644
--- a/src/Cafe/OS/libs/gx2/GX2.cpp
+++ b/src/Cafe/OS/libs/gx2/GX2.cpp
@@ -396,16 +396,13 @@ void gx2_load()
osLib_addFunction("gx2", "GX2GetCurrentScanBuffer", gx2Export_GX2GetCurrentScanBuffer);
// shader stuff
- //osLib_addFunction("gx2", "GX2SetVertexShader", gx2Export_GX2SetVertexShader);
osLib_addFunction("gx2", "GX2SetPixelShader", gx2Export_GX2SetPixelShader);
osLib_addFunction("gx2", "GX2SetGeometryShader", gx2Export_GX2SetGeometryShader);
osLib_addFunction("gx2", "GX2SetComputeShader", gx2Export_GX2SetComputeShader);
- osLib_addFunction("gx2", "GX2SetVertexUniformReg", gx2Export_GX2SetVertexUniformReg);
osLib_addFunction("gx2", "GX2SetVertexUniformBlock", gx2Export_GX2SetVertexUniformBlock);
osLib_addFunction("gx2", "GX2RSetVertexUniformBlock", gx2Export_GX2RSetVertexUniformBlock);
osLib_addFunction("gx2", "GX2SetPixelUniformBlock", gx2Export_GX2SetPixelUniformBlock);
- osLib_addFunction("gx2", "GX2SetPixelUniformReg", gx2Export_GX2SetPixelUniformReg);
osLib_addFunction("gx2", "GX2SetGeometryUniformBlock", gx2Export_GX2SetGeometryUniformBlock);
osLib_addFunction("gx2", "GX2SetShaderModeEx", gx2Export_GX2SetShaderModeEx);
diff --git a/src/Cafe/OS/libs/gx2/GX2.h b/src/Cafe/OS/libs/gx2/GX2.h
index 58d98191..a22719f4 100644
--- a/src/Cafe/OS/libs/gx2/GX2.h
+++ b/src/Cafe/OS/libs/gx2/GX2.h
@@ -18,11 +18,9 @@ void gx2_load();
void gx2Export_GX2SetPixelShader(PPCInterpreter_t* hCPU);
void gx2Export_GX2SetGeometryShader(PPCInterpreter_t* hCPU);
void gx2Export_GX2SetComputeShader(PPCInterpreter_t* hCPU);
-void gx2Export_GX2SetVertexUniformReg(PPCInterpreter_t* hCPU);
void gx2Export_GX2SetVertexUniformBlock(PPCInterpreter_t* hCPU);
void gx2Export_GX2RSetVertexUniformBlock(PPCInterpreter_t* hCPU);
void gx2Export_GX2SetPixelUniformBlock(PPCInterpreter_t* hCPU);
-void gx2Export_GX2SetPixelUniformReg(PPCInterpreter_t* hCPU);
void gx2Export_GX2SetGeometryUniformBlock(PPCInterpreter_t* hCPU);
void gx2Export_GX2SetShaderModeEx(PPCInterpreter_t* hCPU);
void gx2Export_GX2CalcGeometryShaderInputRingBufferSize(PPCInterpreter_t* hCPU);
diff --git a/src/Cafe/OS/libs/gx2/GX2_Shader.cpp b/src/Cafe/OS/libs/gx2/GX2_Shader.cpp
index ad17dc49..d004288b 100644
--- a/src/Cafe/OS/libs/gx2/GX2_Shader.cpp
+++ b/src/Cafe/OS/libs/gx2/GX2_Shader.cpp
@@ -417,6 +417,37 @@ namespace GX2
}
}
+ void _GX2SubmitUniformReg(uint32 offsetRegBase, uint32 aluRegisterOffset, uint32be* dataWords, uint32 sizeInU32s)
+ {
+ if(aluRegisterOffset&0x8000)
+ {
+ cemuLog_logDebug(LogType::Force, "_GX2SubmitUniformReg(): Unhandled loop const special case or invalid offset");
+ return;
+ }
+ if((aluRegisterOffset+sizeInU32s) > 0x400)
+ {
+ cemuLog_logOnce(LogType::APIErrors, "GX2SetVertexUniformReg values are out of range (offset {} + size {} must be equal or smaller than 0x400)", aluRegisterOffset, sizeInU32s);
+ }
+ if( (sizeInU32s&3) != 0)
+ {
+ cemuLog_logOnce(LogType::APIErrors, "GX2Set*UniformReg must be called with a size that is a multiple of 4 (size: {:})", sizeInU32s);
+ sizeInU32s &= ~3;
+ }
+ GX2ReserveCmdSpace(2 + sizeInU32s);
+ gx2WriteGather_submit(pm4HeaderType3(IT_SET_ALU_CONST, 1 + sizeInU32s), offsetRegBase + aluRegisterOffset);
+ gx2WriteGather_submitU32AsLEArray((uint32*)dataWords, sizeInU32s);
+ }
+
+ void GX2SetVertexUniformReg(uint32 offset, uint32 sizeInU32s, uint32be* values)
+ {
+ _GX2SubmitUniformReg(0x400, offset, values, sizeInU32s);
+ }
+
+ void GX2SetPixelUniformReg(uint32 offset, uint32 sizeInU32s, uint32be* values)
+ {
+ _GX2SubmitUniformReg(0, offset, values, sizeInU32s);
+ }
+
void GX2ShaderInit()
{
cafeExportRegister("gx2", GX2CalcFetchShaderSizeEx, LogType::GX2);
@@ -428,5 +459,8 @@ namespace GX2
cafeExportRegister("gx2", GX2GetPixelShaderStackEntries, LogType::GX2);
cafeExportRegister("gx2", GX2SetFetchShader, LogType::GX2);
cafeExportRegister("gx2", GX2SetVertexShader, LogType::GX2);
+
+ cafeExportRegister("gx2", GX2SetVertexUniformReg, LogType::GX2);
+ cafeExportRegister("gx2", GX2SetPixelUniformReg, LogType::GX2);
}
}
\ No newline at end of file
diff --git a/src/Cafe/OS/libs/gx2/GX2_shader_legacy.cpp b/src/Cafe/OS/libs/gx2/GX2_shader_legacy.cpp
index 1cb61a7e..b0a5d2fa 100644
--- a/src/Cafe/OS/libs/gx2/GX2_shader_legacy.cpp
+++ b/src/Cafe/OS/libs/gx2/GX2_shader_legacy.cpp
@@ -270,41 +270,6 @@ void gx2Export_GX2SetComputeShader(PPCInterpreter_t* hCPU)
osLib_returnFromFunction(hCPU, 0);
}
-void _GX2SubmitUniformReg(uint32 aluRegisterOffset, MPTR virtualAddress, uint32 count)
-{
- uint32* dataWords = (uint32*)memory_getPointerFromVirtualOffset(virtualAddress);
- GX2ReserveCmdSpace(2 + (count / 0xFF) * 2 + count);
- // write PM4 command(s)
- uint32 currentRegisterOffset = aluRegisterOffset;
- while (count > 0)
- {
- uint32 subCount = std::min(count, 0xFFu); // a single command can write at most 0xFF values
- gx2WriteGather_submit(pm4HeaderType3(IT_SET_ALU_CONST, 1 + subCount),
- currentRegisterOffset);
- gx2WriteGather_submitU32AsLEArray(dataWords, subCount);
-
- dataWords += subCount;
- count -= subCount;
- currentRegisterOffset += subCount;
- }
-}
-
-void gx2Export_GX2SetVertexUniformReg(PPCInterpreter_t* hCPU)
-{
- cemuLog_log(LogType::GX2, "GX2SetVertexUniformReg(0x{:08x},0x{:x},0x{:08x})", hCPU->gpr[3], hCPU->gpr[4], hCPU->gpr[5]);
- _GX2SubmitUniformReg(hCPU->gpr[3] + 0x400, hCPU->gpr[5], hCPU->gpr[4]);
- cemu_assert_debug((hCPU->gpr[3] + hCPU->gpr[4]) <= 0x400);
- osLib_returnFromFunction(hCPU, 0);
-}
-
-void gx2Export_GX2SetPixelUniformReg(PPCInterpreter_t* hCPU)
-{
- cemuLog_log(LogType::GX2, "GX2SetPixelUniformReg(0x{:08x},0x{:x},0x{:08x})", hCPU->gpr[3], hCPU->gpr[4], hCPU->gpr[5]);
- _GX2SubmitUniformReg(hCPU->gpr[3], hCPU->gpr[5], hCPU->gpr[4]);
- cemu_assert_debug((hCPU->gpr[3] + hCPU->gpr[4]) <= 0x400);
- osLib_returnFromFunction(hCPU, 0);
-}
-
void _GX2SubmitUniformBlock(uint32 registerBase, uint32 index, MPTR virtualAddress, uint32 size)
{
GX2ReserveCmdSpace(9);
diff --git a/src/Cafe/OS/libs/nn_act/nn_act.cpp b/src/Cafe/OS/libs/nn_act/nn_act.cpp
index 0fd9df5a..2a9f61bc 100644
--- a/src/Cafe/OS/libs/nn_act/nn_act.cpp
+++ b/src/Cafe/OS/libs/nn_act/nn_act.cpp
@@ -543,8 +543,6 @@ void nnActExport_GetDefaultAccount(PPCInterpreter_t* hCPU)
void nnActExport_GetSlotNo(PPCInterpreter_t* hCPU)
{
// id of active account
- // uint8 GetSlotNo(void);
- cemuLog_logDebug(LogType::Force, "nn_act.GetSlotNo()");
osLib_returnFromFunction(hCPU, 1); // 1 is the first slot (0 is invalid)
}
From dd7cb74cd21202471634e991865be242f8e45c58 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Sun, 10 Mar 2024 23:36:47 +0100
Subject: [PATCH 053/319] Latte: Small refactor and clean up for texture size
code
---
.gitignore | 1 +
src/Cafe/HW/Latte/Core/LatteBufferCache.cpp | 2 +-
src/Cafe/HW/Latte/Core/LatteCachedFBO.h | 4 +-
src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp | 28 ++++-------
src/Cafe/HW/Latte/Core/LatteTexture.cpp | 8 +--
src/Cafe/HW/Latte/Core/LatteTexture.h | 25 +++++++++-
src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp | 50 ++-----------------
.../Latte/Renderer/OpenGL/OpenGLRenderer.cpp | 23 ++++-----
.../Renderer/OpenGL/OpenGLSurfaceCopy.cpp | 5 +-
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 2 +-
.../Renderer/Vulkan/VulkanSurfaceCopy.cpp | 22 +++-----
src/Cafe/OS/libs/gx2/GX2_Resource.cpp | 2 +-
src/Cemu/Logging/CemuLogging.h | 2 +
13 files changed, 64 insertions(+), 110 deletions(-)
diff --git a/.gitignore b/.gitignore
index 18f14cf3..c10b38da 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@ bin/sdcard/*
bin/screenshots/*
bin/dump/*
bin/cafeLibs/*
+bin/keys.txt
!bin/shaderCache/info.txt
bin/shaderCache/*
diff --git a/src/Cafe/HW/Latte/Core/LatteBufferCache.cpp b/src/Cafe/HW/Latte/Core/LatteBufferCache.cpp
index 92c2d1b0..716312a3 100644
--- a/src/Cafe/HW/Latte/Core/LatteBufferCache.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteBufferCache.cpp
@@ -309,7 +309,7 @@ public:
{
if ((rangeBegin & 0xF))
{
- cemuLog_logDebug(LogType::Force, "writeStreamout(): RangeBegin not aligned to 16. Begin {:08x} End {:08x}", rangeBegin, rangeEnd);
+ cemuLog_logDebugOnce(LogType::Force, "writeStreamout(): RangeBegin not aligned to 16. Begin {:08x} End {:08x}", rangeBegin, rangeEnd);
rangeBegin = (rangeBegin + 0xF) & ~0xF;
rangeEnd = std::max(rangeBegin, rangeEnd);
}
diff --git a/src/Cafe/HW/Latte/Core/LatteCachedFBO.h b/src/Cafe/HW/Latte/Core/LatteCachedFBO.h
index 6d5925fe..5f3aaed4 100644
--- a/src/Cafe/HW/Latte/Core/LatteCachedFBO.h
+++ b/src/Cafe/HW/Latte/Core/LatteCachedFBO.h
@@ -42,7 +42,7 @@ private:
if(colorBuffer[i].texture == nullptr)
continue;
sint32 effectiveWidth, effectiveHeight;
- LatteTexture_getEffectiveSize(colorBuffer[i].texture->baseTexture, &effectiveWidth, &effectiveHeight, nullptr, colorBuffer[i].texture->firstMip);
+ colorBuffer[i].texture->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, colorBuffer[i].texture->firstMip);
if (rtEffectiveSize.x == 0 && rtEffectiveSize.y == 0)
{
rtEffectiveSize.x = effectiveWidth;
@@ -64,7 +64,7 @@ private:
if (depthBuffer.texture)
{
sint32 effectiveWidth, effectiveHeight;
- LatteTexture_getEffectiveSize(depthBuffer.texture->baseTexture, &effectiveWidth, &effectiveHeight, nullptr, depthBuffer.texture->firstMip);
+ depthBuffer.texture->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, depthBuffer.texture->firstMip);
if (rtEffectiveSize.x == 0 && rtEffectiveSize.y == 0)
{
rtEffectiveSize.x = effectiveWidth;
diff --git a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
index abdfda21..8c29ccc5 100644
--- a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
@@ -516,14 +516,12 @@ bool LatteMRT::UpdateCurrentFBO()
sLatteRenderTargetState.rtUpdateList[sLatteRenderTargetState.rtUpdateListCount] = colorAttachmentView;
sLatteRenderTargetState.rtUpdateListCount++;
- sint32 colorAttachmentWidth;
- sint32 colorAttachmentHeight;
-
- LatteTexture_getSize(colorAttachmentView->baseTexture, &colorAttachmentWidth, &colorAttachmentHeight, nullptr, colorAttachmentView->firstMip);
+ sint32 colorAttachmentWidth, colorAttachmentHeight;
+ colorAttachmentView->baseTexture->GetSize(colorAttachmentWidth, colorAttachmentHeight, colorAttachmentView->firstMip);
// set effective size
sint32 effectiveWidth, effectiveHeight;
- LatteTexture_getEffectiveSize(colorAttachmentView->baseTexture, &effectiveWidth, &effectiveHeight, nullptr, colorAttachmentView->firstMip);
+ colorAttachmentView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, colorAttachmentView->firstMip);
if (rtEffectiveSize->width == 0 && rtEffectiveSize->height == 0)
{
rtEffectiveSize->width = effectiveWidth;
@@ -531,9 +529,7 @@ bool LatteMRT::UpdateCurrentFBO()
}
else if (rtEffectiveSize->width != effectiveWidth && rtEffectiveSize->height != effectiveHeight)
{
-#ifdef CEMU_DEBUG_ASSERT
- cemuLog_log(LogType::Force, "Color buffer size mismatch ({}x{}). Effective size: {}x{} Real size: {}x{} Mismatching texture: {:08x} {}x{} fmt {:04x}", rtEffectiveSize->width, rtEffectiveSize->height, effectiveWidth, effectiveHeight, colorAttachmentView->baseTexture->width, colorAttachmentView->baseTexture->height, colorAttachmentView->baseTexture->physAddress, colorAttachmentView->baseTexture->width, colorAttachmentView->baseTexture->height, (uint32)colorAttachmentView->baseTexture->format);
-#endif
+ cemuLog_logDebug(LogType::Force, "Color buffer size mismatch ({}x{}). Effective size: {}x{} Real size: {}x{} Mismatching texture: {:08x} {}x{} fmt {:04x}", rtEffectiveSize->width, rtEffectiveSize->height, effectiveWidth, effectiveHeight, colorAttachmentView->baseTexture->width, colorAttachmentView->baseTexture->height, colorAttachmentView->baseTexture->physAddress, colorAttachmentView->baseTexture->width, colorAttachmentView->baseTexture->height, (uint32)colorAttachmentView->baseTexture->format);
}
// currently the first color attachment defines the size of the current render target
if (rtRealSize->width == 0 && rtRealSize->height == 0)
@@ -608,15 +604,11 @@ bool LatteMRT::UpdateCurrentFBO()
if (depthBufferPhysMem != MPTR_NULL)
{
- bool depthBufferWasFound = false;
LatteTextureView* depthBufferView = LatteTextureViewLookupCache::lookupSliceEx(depthBufferPhysMem, depthBufferWidth, depthBufferHeight, depthBufferPitch, 0, depthBufferViewFirstSlice, depthBufferFormat, true);
if (depthBufferView == nullptr)
{
- // create depth buffer view
- if(depthBufferViewFirstSlice == 0)
- depthBufferView = LatteTexture_CreateMapping(depthBufferPhysMem, 0, depthBufferWidth, depthBufferHeight, 1, depthBufferPitch, depthBufferTileMode, depthBufferSwizzle, 0, 1, 0, 1, depthBufferFormat, Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true);
- else
- depthBufferView = LatteTexture_CreateMapping(depthBufferPhysMem, 0, depthBufferWidth, depthBufferHeight, depthBufferViewFirstSlice+1, depthBufferPitch, depthBufferTileMode, depthBufferSwizzle, 0, 1, depthBufferViewFirstSlice, 1, depthBufferFormat, Latte::E_DIM::DIM_2D_ARRAY, Latte::E_DIM::DIM_2D, true);
+ // create new depth buffer view and if it doesn't exist then also create the texture
+ depthBufferView = LatteTexture_CreateMapping(depthBufferPhysMem, 0, depthBufferWidth, depthBufferHeight, depthBufferViewFirstSlice+1, depthBufferPitch, depthBufferTileMode, depthBufferSwizzle, 0, 1, depthBufferViewFirstSlice, 1, depthBufferFormat, depthBufferViewFirstSlice > 0 ? Latte::E_DIM::DIM_2D_ARRAY : Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true);
LatteGPUState.repeatTextureInitialization = true;
}
else
@@ -626,7 +618,7 @@ bool LatteMRT::UpdateCurrentFBO()
}
// set effective size
sint32 effectiveWidth, effectiveHeight;
- LatteTexture_getEffectiveSize(depthBufferView->baseTexture, &effectiveWidth, &effectiveHeight, NULL);
+ depthBufferView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, depthBufferViewFirstSlice);
if (rtEffectiveSize->width == 0 && rtEffectiveSize->height == 0)
{
rtEffectiveSize->width = effectiveWidth;
@@ -917,10 +909,8 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa
// mark source texture as still in use
LatteTC_MarkTextureStillInUse(textureView->baseTexture);
- sint32 effectiveWidth;
- sint32 effectiveHeight;
- sint32 effectiveDepth;
- LatteTexture_getEffectiveSize(textureView->baseTexture, &effectiveWidth, &effectiveHeight, &effectiveDepth, 0);
+ sint32 effectiveWidth, effectiveHeight;
+ textureView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0);
_currentOutputImageWidth = effectiveWidth;
_currentOutputImageHeight = effectiveHeight;
diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.cpp b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
index 707428af..91a1aa56 100644
--- a/src/Cafe/HW/Latte/Core/LatteTexture.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
@@ -297,9 +297,9 @@ void LatteTexture_copyData(LatteTexture* srcTexture, LatteTexture* dstTexture, s
else
{
sint32 effectiveWidth_dst, effectiveHeight_dst;
- LatteTexture_getEffectiveSize(srcTexture, &effectiveWidth_dst, &effectiveHeight_dst, NULL, 0);
+ srcTexture->GetEffectiveSize(effectiveWidth_dst, effectiveHeight_dst, 0);
sint32 effectiveWidth_src, effectiveHeight_src;
- LatteTexture_getEffectiveSize(dstTexture, &effectiveWidth_src, &effectiveHeight_src, NULL, 0);
+ dstTexture->GetEffectiveSize(effectiveWidth_src, effectiveHeight_src, 0);
debug_printf("texture_copyData(): Effective size mismatch\n");
cemuLog_logDebug(LogType::Force, "texture_copyData(): Effective size mismatch (due to texture rule)");
@@ -307,8 +307,6 @@ void LatteTexture_copyData(LatteTexture* srcTexture, LatteTexture* dstTexture, s
cemuLog_logDebug(LogType::Force, "Source: origResolution {:04}x{:04} effectiveResolution {:04}x{:04} fmt {:04x} mipIndex {}", srcTexture->width, srcTexture->height, effectiveWidth_src, effectiveHeight_src, (uint32)srcTexture->format, 0);
return;
}
- catchOpenGLError();
-
for (sint32 mipIndex = 0; mipIndex < mipCount; mipIndex++)
{
sint32 sliceCopyWidth = std::max(effectiveCopyWidth >> mipIndex, 1);
@@ -323,9 +321,7 @@ void LatteTexture_copyData(LatteTexture* srcTexture, LatteTexture* dstTexture, s
LatteTextureSliceMipInfo* dstTexSliceInfo = dstTexture->sliceMipInfo + dstTexture->GetSliceMipArrayIndex(sliceIndex, mipIndex);
dstTexSliceInfo->lastDynamicUpdate = srcTexSliceInfo->lastDynamicUpdate;
}
- catchOpenGLError();
}
- catchOpenGLError();
}
template
diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.h b/src/Cafe/HW/Latte/Core/LatteTexture.h
index d5e872e6..b46c1323 100644
--- a/src/Cafe/HW/Latte/Core/LatteTexture.h
+++ b/src/Cafe/HW/Latte/Core/LatteTexture.h
@@ -55,6 +55,29 @@ public:
bool Is3DTexture() const { return dim == Latte::E_DIM::DIM_3D; };
+ void GetSize(sint32& width, sint32& height, sint32 mipLevel) const
+ {
+ width = std::max(1, this->width >> mipLevel);
+ height = std::max(1, this->height >> mipLevel);
+ }
+
+ // similar to GetSize, but returns the real size of the texture taking into account any resolution overwrite by gfx pack rules
+ void GetEffectiveSize(sint32& effectiveWidth, sint32& effectiveHeight, sint32 mipLevel) const
+ {
+ if( overwriteInfo.hasResolutionOverwrite )
+ {
+ effectiveWidth = overwriteInfo.width;
+ effectiveHeight = overwriteInfo.height;
+ }
+ else
+ {
+ effectiveWidth = this->width;
+ effectiveHeight = this->height;
+ }
+ effectiveWidth = std::max(1, effectiveWidth >> mipLevel);
+ effectiveHeight = std::max(1, effectiveHeight >> mipLevel);
+ }
+
sint32 GetMipDepth(sint32 mipIndex)
{
cemu_assert_debug(mipIndex >= 0 && mipIndex < this->mipLevels);
@@ -310,8 +333,6 @@ void LatteTexture_Delete(LatteTexture* texture);
void LatteTextureLoader_writeReadbackTextureToMemory(LatteTextureDefinition* textureData, uint32 sliceIndex, uint32 mipIndex, uint8* linearPixelData);
-void LatteTexture_getSize(LatteTexture* texture, sint32* width, sint32* height, sint32* depth, sint32 mipLevel);
-void LatteTexture_getEffectiveSize(LatteTexture* texture, sint32* effectiveWidth, sint32* effectiveHeight, sint32* effectiveDepth, sint32 mipLevel = 0);
sint32 LatteTexture_getEffectiveWidth(LatteTexture* texture);
bool LatteTexture_doesEffectiveRescaleRatioMatch(LatteTexture* texture1, sint32 mipLevel1, LatteTexture* texture2, sint32 mipLevel2);
void LatteTexture_scaleToEffectiveSize(LatteTexture* texture, sint32* x, sint32* y, sint32 mipLevel);
diff --git a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
index 0260002b..b35f608c 100644
--- a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
@@ -206,14 +206,10 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u
bool isDepthSampler = shaderContext->textureUsesDepthCompare[textureIndex];
// look for already existing texture
- LatteTextureView* textureView;
- if (isDepthSampler == false)
- textureView = LatteTextureViewLookupCache::lookup(physAddr, width, height, depth, pitch, viewFirstMip, viewNumMips, viewFirstSlice, viewNumSlices, format, dim);
- else
- textureView = LatteTextureViewLookupCache::lookup(physAddr, width, height, depth, pitch, viewFirstMip, viewNumMips, viewFirstSlice, viewNumSlices, format, dim, true);
- if (textureView == nullptr)
+ LatteTextureView* textureView = LatteTextureViewLookupCache::lookup(physAddr, width, height, depth, pitch, viewFirstMip, viewNumMips, viewFirstSlice, viewNumSlices, format, dim, isDepthSampler);
+ if (!textureView)
{
- // create new mapping
+ // view not found, create a new mapping which will also create a new texture if necessary
textureView = LatteTexture_CreateMapping(physAddr, physMipAddr, width, height, depth, pitch, tileMode, swizzle, viewFirstMip, viewNumMips, viewFirstSlice, viewNumSlices, format, dim, dim, isDepthSampler);
if (textureView == nullptr)
continue;
@@ -273,9 +269,7 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u
// check for changes
if (LatteTC_HasTextureChanged(textureView->baseTexture) || swizzleChanged)
{
-#ifdef CEMU_DEBUG_ASSERT
debug_printf("Reload texture 0x%08x res %dx%d memRange %08x-%08x SwizzleChange: %s\n", textureView->baseTexture->physAddress, textureView->baseTexture->width, textureView->baseTexture->height, textureView->baseTexture->texDataPtrLow, textureView->baseTexture->texDataPtrHigh, swizzleChanged ? "yes" : "no");
-#endif
// update swizzle / changed mip address
if (swizzleChanged)
{
@@ -338,44 +332,6 @@ void LatteTexture_updateTextures()
LatteTexture_updateTexturesForStage(geometryShader, LATTE_CEMU_GS_TEX_UNIT_BASE, LatteGPUState.contextNew.SQ_TEX_START_GS);
}
-// returns the width, height, depth of the texture
-void LatteTexture_getSize(LatteTexture* texture, sint32* width, sint32* height, sint32* depth, sint32 mipLevel)
-{
- *width = texture->width;
- *height = texture->height;
- if (depth != NULL)
- *depth = texture->depth;
- // handle mip level
- *width = std::max(1, *width >> mipLevel);
- *height = std::max(1, *height >> mipLevel);
- if(texture->Is3DTexture() && depth)
- *depth = std::max(1, *depth >> mipLevel);
-}
-
-/*
- * Returns the internally used width/height/depth of the texture
- * Usually this is the width/height/depth specified by the game,
- * unless the texture resolution was redefined via graphic pack texture rules
- */
-void LatteTexture_getEffectiveSize(LatteTexture* texture, sint32* effectiveWidth, sint32* effectiveHeight, sint32* effectiveDepth, sint32 mipLevel)
-{
- *effectiveWidth = texture->width;
- *effectiveHeight = texture->height;
- if( effectiveDepth != NULL )
- *effectiveDepth = texture->depth;
- if( texture->overwriteInfo.hasResolutionOverwrite )
- {
- *effectiveWidth = texture->overwriteInfo.width;
- *effectiveHeight = texture->overwriteInfo.height;
- if( effectiveDepth != NULL )
- *effectiveDepth = texture->overwriteInfo.depth;
- }
- // handle mipLevel
- // todo: Mip-mapped 3D textures decrease in depth also?
- *effectiveWidth = std::max(1, *effectiveWidth >> mipLevel);
- *effectiveHeight = std::max(1, *effectiveHeight >> mipLevel);
-}
-
sint32 LatteTexture_getEffectiveWidth(LatteTexture* texture)
{
if (texture->overwriteInfo.hasResolutionOverwrite)
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
index 8548fa1c..68d7def6 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
@@ -569,10 +569,8 @@ void OpenGLRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutpu
g_renderer->ClearColorbuffer(padView);
}
- // calculate effective size
- sint32 effectiveWidth;
- sint32 effectiveHeight;
- LatteTexture_getEffectiveSize(texView->baseTexture, &effectiveWidth, &effectiveHeight, nullptr, 0);
+ sint32 effectiveWidth, effectiveHeight;
+ texView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0);
shader_unbind(RendererShader::ShaderType::kGeometry);
shader_bind(shader->GetVertexShader());
@@ -1127,8 +1125,8 @@ void OpenGLRenderer::texture_clearColorSlice(LatteTexture* hostTexture, sint32 s
LatteTextureGL* texGL = (LatteTextureGL*)hostTexture;
cemu_assert_debug(!texGL->isDepth);
- sint32 eWidth, eHeight, eDepth;
- LatteTexture_getEffectiveSize(hostTexture, &eWidth, &eHeight, &eDepth, mipIndex);
+ sint32 eWidth, eHeight;
+ hostTexture->GetEffectiveSize(eWidth, eHeight, mipIndex);
renderstate_resetColorControl();
renderTarget_setViewport(0, 0, eWidth, eHeight, 0.0f, 1.0f);
LatteMRT::BindColorBufferOnly(hostTexture->GetOrCreateView(mipIndex, 1, sliceIndex, 1));
@@ -1141,8 +1139,8 @@ void OpenGLRenderer::texture_clearDepthSlice(LatteTexture* hostTexture, uint32 s
LatteTextureGL* texGL = (LatteTextureGL*)hostTexture;
cemu_assert_debug(texGL->isDepth);
- sint32 eWidth, eHeight, eDepth;
- LatteTexture_getEffectiveSize(hostTexture, &eWidth, &eHeight, &eDepth, mipIndex);
+ sint32 eWidth, eHeight;
+ hostTexture->GetEffectiveSize(eWidth, eHeight, mipIndex);
renderstate_resetColorControl();
renderstate_resetDepthControl();
renderTarget_setViewport(0, 0, eWidth, eHeight, 0.0f, 1.0f);
@@ -1170,13 +1168,12 @@ void OpenGLRenderer::texture_clearSlice(LatteTexture* hostTextureGeneric, sint32
LatteTextureGL::FormatInfoGL formatInfoGL;
LatteTextureGL::GetOpenGLFormatInfo(hostTexture->isDepth, hostTexture->format, hostTexture->dim, &formatInfoGL);
// get effective size of mip
- sint32 effectiveWidth;
- sint32 effectiveHeight;
- LatteTexture_getEffectiveSize(hostTexture, &effectiveWidth, &effectiveHeight, nullptr, mipIndex);
+ sint32 effectiveWidth, effectiveHeight;
+ hostTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, mipIndex);
// on Nvidia glClearTexImage and glClearTexSubImage has bad performance (clearing a 4K texture takes up to 50ms)
// clearing with glTextureSubImage2D from a CPU RAM buffer is only slightly slower
- // clearing with glTextureSubImage2D from a OpenGL buffer is 10-20% faster than glClearTexImage)
+ // clearing with glTextureSubImage2D from a OpenGL buffer is 10-20% faster than glClearTexImage
// clearing with FBO and glClear is orders of magnitude faster than the other methods
// (these are results from 2018, may be different now)
@@ -1207,7 +1204,6 @@ void OpenGLRenderer::texture_clearSlice(LatteTexture* hostTextureGeneric, sint32
}
if (glClearTexSubImage == nullptr)
return;
- // clear
glClearTexSubImage(hostTexture->glId_texture, mipIndex, 0, 0, sliceIndex, effectiveWidth, effectiveHeight, 1, formatInfoGL.glSuppliedFormat, formatInfoGL.glSuppliedFormatType, NULL);
}
@@ -1215,7 +1211,6 @@ LatteTexture* OpenGLRenderer::texture_createTextureEx(Latte::E_DIM dim, MPTR phy
uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth)
{
return new LatteTextureGL(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth);
-
}
void OpenGLRenderer::texture_setActiveTextureUnit(sint32 index)
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp
index c49a57e4..d578b842 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLSurfaceCopy.cpp
@@ -30,9 +30,8 @@ void OpenGLRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* s
sint32 effectiveCopyWidth = width;
sint32 effectiveCopyHeight = height;
LatteTexture_scaleToEffectiveSize(sourceTexture, &effectiveCopyWidth, &effectiveCopyHeight, 0);
- sint32 sourceEffectiveWidth;
- sint32 sourceEffectiveHeight;
- LatteTexture_getEffectiveSize(sourceTexture, &sourceEffectiveWidth, &sourceEffectiveHeight, nullptr, srcMip);
+ sint32 sourceEffectiveWidth, sourceEffectiveHeight;
+ sourceTexture->GetEffectiveSize(sourceEffectiveWidth, sourceEffectiveHeight, srcMip);
// reset everything
renderstate_resetColorControl();
renderstate_resetDepthControl();
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index 8711359e..5285e4ac 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -764,7 +764,7 @@ void VulkanRenderer::HandleScreenshotRequest(LatteTextureView* texView, bool pad
//dumpImage->flagForCurrentCommandBuffer();
int width, height;
- LatteTexture_getEffectiveSize(baseImageTex, &width, &height, nullptr, 0);
+ baseImageTex->GetEffectiveSize(width, height, 0);
VkImage image = nullptr;
VkDeviceMemory imageMemory = nullptr;;
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp
index 6d5d9402..d89cdaa1 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp
@@ -464,9 +464,8 @@ VKRObjectFramebuffer* VulkanRenderer::surfaceCopy_getOrCreateFramebuffer(VkCopyS
VKRObjectTextureView* vkObjTextureView = surfaceCopy_createImageView(state.destinationTexture, state.dstSlice, state.dstMip);
// create new framebuffer
- sint32 effectiveWidth = 0;
- sint32 effectiveHeight = 0;
- LatteTexture_getEffectiveSize(state.destinationTexture, &effectiveWidth, &effectiveHeight, nullptr, state.dstMip);
+ sint32 effectiveWidth, effectiveHeight;
+ state.destinationTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, state.dstMip);
std::array fbAttachments;
fbAttachments[0] = vkObjTextureView;
@@ -595,15 +594,11 @@ void VulkanRenderer::surfaceCopy_viaDrawcall(LatteTextureVk* srcTextureVk, sint3
// get descriptor set
VKRObjectDescriptorSet* vkObjDescriptorSet = surfaceCopy_getOrCreateDescriptorSet(copySurfaceState, copySurfacePipelineInfo);
- // get extend
- sint32 effectiveWidth = 0;
- sint32 effectiveHeight = 0;
- LatteTexture_getEffectiveSize(dstTextureVk, &effectiveWidth, &effectiveHeight, nullptr, texDstMip);
+ sint32 dstEffectiveWidth, dstEffectiveHeight;
+ dstTextureVk->GetEffectiveSize(dstEffectiveWidth, dstEffectiveHeight, texDstMip);
- // get extend
- sint32 srcEffectiveWidth = 0;
- sint32 srcEffectiveHeight = 0;
- LatteTexture_getEffectiveSize(srcTextureVk, &srcEffectiveWidth, &srcEffectiveHeight, nullptr, texSrcMip);
+ sint32 srcEffectiveWidth, srcEffectiveHeight;
+ srcTextureVk->GetEffectiveSize(srcEffectiveWidth, srcEffectiveHeight, texSrcMip);
CopyShaderPushConstantData_t pushConstantData;
@@ -878,9 +873,8 @@ void VulkanRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* s
sint32 effectiveCopyWidth = width;
sint32 effectiveCopyHeight = height;
LatteTexture_scaleToEffectiveSize(sourceTexture, &effectiveCopyWidth, &effectiveCopyHeight, 0);
- sint32 sourceEffectiveWidth;
- sint32 sourceEffectiveHeight;
- LatteTexture_getEffectiveSize(sourceTexture, &sourceEffectiveWidth, &sourceEffectiveHeight, nullptr, srcMip);
+ sint32 sourceEffectiveWidth, sourceEffectiveHeight;
+ sourceTexture->GetEffectiveSize(sourceEffectiveWidth, sourceEffectiveHeight, srcMip);
sint32 texSrcMip = srcMip;
sint32 texSrcSlice = srcSlice;
diff --git a/src/Cafe/OS/libs/gx2/GX2_Resource.cpp b/src/Cafe/OS/libs/gx2/GX2_Resource.cpp
index 70390921..97f51a0d 100644
--- a/src/Cafe/OS/libs/gx2/GX2_Resource.cpp
+++ b/src/Cafe/OS/libs/gx2/GX2_Resource.cpp
@@ -114,7 +114,7 @@ namespace GX2
void GX2RSetStreamOutBuffer(uint32 bufferIndex, GX2StreamOutBuffer* soBuffer)
{
- // seen in CoD: Ghosts
+ // seen in CoD: Ghosts and CoD: Black Ops 2
GX2SetStreamOutBuffer(bufferIndex, soBuffer);
}
diff --git a/src/Cemu/Logging/CemuLogging.h b/src/Cemu/Logging/CemuLogging.h
index 388e51ab..bbffd164 100644
--- a/src/Cemu/Logging/CemuLogging.h
+++ b/src/Cemu/Logging/CemuLogging.h
@@ -112,6 +112,8 @@ bool cemuLog_logDebug(LogType type, TFmt format, TArgs&&... args)
#endif
}
+#define cemuLog_logDebugOnce(...) { static bool _not_first_call = false; if (!_not_first_call) { _not_first_call = true; cemuLog_logDebug(__VA_ARGS__); } }
+
// cafe lib calls
bool cemuLog_advancedPPCLoggingEnabled();
From 40d1eaeb72f050916b29396805b8ea990345d418 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Mon, 11 Mar 2024 21:37:44 +0100
Subject: [PATCH 054/319] nn_ac: Refactor and implement more API
Doesn't fix any issue as far as I know but it removes some of the unsupported API complaints in debug logging
---
src/Cafe/OS/libs/nn_ac/nn_ac.cpp | 189 +++++++++++++++++--------------
1 file changed, 105 insertions(+), 84 deletions(-)
diff --git a/src/Cafe/OS/libs/nn_ac/nn_ac.cpp b/src/Cafe/OS/libs/nn_ac/nn_ac.cpp
index bb7d4af6..5f231499 100644
--- a/src/Cafe/OS/libs/nn_ac/nn_ac.cpp
+++ b/src/Cafe/OS/libs/nn_ac/nn_ac.cpp
@@ -8,83 +8,14 @@
// AC lib (manages internet connection)
-#define AC_STATUS_FAILED (-1)
-#define AC_STATUS_OK (0)
-
-void nn_acExport_ConnectAsync(PPCInterpreter_t* hCPU)
+enum class AC_STATUS : uint32
{
- cemuLog_logDebug(LogType::Force, "nn_ac.ConnectAsync();");
- uint32 nnResultCode = BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0);
- osLib_returnFromFunction(hCPU, nnResultCode);
-}
-
-void nn_acExport_Connect(PPCInterpreter_t* hCPU)
-{
- cemuLog_logDebug(LogType::Force, "nn_ac.Connect();");
-
- // Terraria expects this (or GetLastErrorCode) to return 0 on success
- // investigate on the actual console
- // maybe all success codes are always 0 and dont have any of the other fields set?
-
- uint32 nnResultCode = 0;// BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0); // Splatoon freezes if this function fails?
- osLib_returnFromFunction(hCPU, nnResultCode);
-}
+ FAILED = (uint32)-1,
+ OK = 0,
+};
static_assert(TRUE == 1, "TRUE not 1");
-void nn_acExport_IsApplicationConnected(PPCInterpreter_t* hCPU)
-{
- //cemuLog_logDebug(LogType::Force, "nn_ac.IsApplicationConnected(0x{:08x})", hCPU->gpr[3]);
- ppcDefineParamMEMPTR(connected, uint8, 0);
- if (connected)
- *connected = TRUE;
- //memory_writeU8(hCPU->gpr[3], 1); // always return true regardless of actual online state
-
- const uint32 nnResultCode = BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0);
- osLib_returnFromFunction(hCPU, nnResultCode);
-}
-
-void nn_acExport_GetConnectStatus(PPCInterpreter_t* hCPU)
-{
- ppcDefineParamMEMPTR(status, uint32, 0);
- if (status)
- *status = AC_STATUS_OK;
-
- const uint32 nnResultCode = BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0);
- osLib_returnFromFunction(hCPU, nnResultCode);
-}
-
-void nn_acExport_GetLastErrorCode(PPCInterpreter_t* hCPU)
-{
- //cemuLog_logDebug(LogType::Force, "nn_ac.GetLastErrorCode();");
- ppcDefineParamMEMPTR(errorCode, uint32, 0);
- if (errorCode)
- *errorCode = 0;
- const uint32 nnResultCode = BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0);
- osLib_returnFromFunction(hCPU, nnResultCode);
-}
-
-void nn_acExport_GetStatus(PPCInterpreter_t* hCPU)
-{
- cemuLog_logDebug(LogType::Force, "nn_ac.GetStatus();");
- ppcDefineParamMEMPTR(status, uint32, 0);
- if (status)
- *status = AC_STATUS_OK;
- const uint32 nnResultCode = BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0);
- osLib_returnFromFunction(hCPU, nnResultCode);
-}
-
-void nn_acExport_GetConnectResult(PPCInterpreter_t* hCPU)
-{
- // GetConnectStatus__Q2_2nn2acFPQ3_2nn2ac6Status
- cemuLog_logDebug(LogType::Force, "nn_ac.GetConnectResult(0x{:08x})", hCPU->gpr[3]);
- ppcDefineParamMEMPTR(result, uint32, 0);
- const uint32 nnResultCode = BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0);
- if (result)
- *result = nnResultCode;
- osLib_returnFromFunction(hCPU, nnResultCode);
-}
-
void _GetLocalIPAndSubnetMaskFallback(uint32& localIp, uint32& subnetMask)
{
// default to some hardcoded values
@@ -227,37 +158,127 @@ void nnAcExport_IsConfigExisting(PPCInterpreter_t* hCPU)
namespace nn_ac
{
+ nnResult Initialize()
+ {
+ return BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0);
+ }
+
+ nnResult ConnectAsync()
+ {
+ return BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0);
+ }
+
+ nnResult IsApplicationConnected(uint8be* connected)
+ {
+ if (connected)
+ *connected = TRUE;
+ return BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0);
+ }
+
+ uint32 Connect()
+ {
+ // Terraria expects this (or GetLastErrorCode) to return 0 on success
+ // investigate on the actual console
+ // maybe all success codes are always 0 and dont have any of the other fields set?
+ uint32 nnResultCode = 0;// BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0); // Splatoon freezes if this function fails?
+ return nnResultCode;
+ }
+
+ nnResult GetConnectStatus(betype* status)
+ {
+ if (status)
+ *status = AC_STATUS::OK;
+ return BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0);
+ }
+
+ nnResult GetStatus(betype* status)
+ {
+ return GetConnectStatus(status);
+ }
+
+ nnResult GetLastErrorCode(uint32be* errorCode)
+ {
+ if (errorCode)
+ *errorCode = 0;
+ return BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0);
+ }
+
+ nnResult GetConnectResult(uint32be* connectResult)
+ {
+ const uint32 nnResultCode = BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_AC, 0);
+ if (connectResult)
+ *connectResult = nnResultCode;
+ return nnResultCode;
+ }
+
+ static_assert(sizeof(betype) == 4);
+ static_assert(sizeof(betype) == 4);
+
+ nnResult ACInitialize()
+ {
+ return Initialize();
+ }
+
bool ACIsSuccess(betype* r)
{
return NN_RESULT_IS_SUCCESS(*r) ? 1 : 0;
}
- nnResult ACGetConnectStatus(uint32be* connectionStatus)
+ bool ACIsFailure(betype* r)
{
+ return NN_RESULT_IS_FAILURE(*r) ? 1 : 0;
+ }
- *connectionStatus = 0; // 0 means connected?
+ nnResult ACGetConnectStatus(betype* connectionStatus)
+ {
+ return GetConnectStatus(connectionStatus);
+ }
- return NN_RESULT_SUCCESS;
+ nnResult ACGetStatus(betype* connectionStatus)
+ {
+ return GetStatus(connectionStatus);
+ }
+
+ nnResult ACConnectAsync()
+ {
+ return ConnectAsync();
+ }
+
+ nnResult ACIsApplicationConnected(uint32be* connectedU32)
+ {
+ uint8be connected = 0;
+ nnResult r = IsApplicationConnected(&connected);
+ *connectedU32 = connected; // convert to uint32
+ return r;
}
void load()
{
+ cafeExportRegisterFunc(Initialize, "nn_ac", "Initialize__Q2_2nn2acFv", LogType::Placeholder);
+
+ cafeExportRegisterFunc(Connect, "nn_ac", "Connect__Q2_2nn2acFv", LogType::Placeholder);
+ cafeExportRegisterFunc(ConnectAsync, "nn_ac", "ConnectAsync__Q2_2nn2acFv", LogType::Placeholder);
+
+ cafeExportRegisterFunc(GetConnectResult, "nn_ac", "GetConnectResult__Q2_2nn2acFPQ2_2nn6Result", LogType::Placeholder);
+ cafeExportRegisterFunc(GetLastErrorCode, "nn_ac", "GetLastErrorCode__Q2_2nn2acFPUi", LogType::Placeholder);
+ cafeExportRegisterFunc(GetConnectStatus, "nn_ac", "GetConnectStatus__Q2_2nn2acFPQ3_2nn2ac6Status", LogType::Placeholder);
+ cafeExportRegisterFunc(GetStatus, "nn_ac", "GetStatus__Q2_2nn2acFPQ3_2nn2ac6Status", LogType::Placeholder);
+ cafeExportRegisterFunc(IsApplicationConnected, "nn_ac", "IsApplicationConnected__Q2_2nn2acFPb", LogType::Placeholder);
+
+ // AC also offers C-style wrappers
+ cafeExportRegister("nn_ac", ACInitialize, LogType::Placeholder);
cafeExportRegister("nn_ac", ACIsSuccess, LogType::Placeholder);
+ cafeExportRegister("nn_ac", ACIsFailure, LogType::Placeholder);
cafeExportRegister("nn_ac", ACGetConnectStatus, LogType::Placeholder);
+ cafeExportRegister("nn_ac", ACGetStatus, LogType::Placeholder);
+ cafeExportRegister("nn_ac", ACConnectAsync, LogType::Placeholder);
+ cafeExportRegister("nn_ac", ACIsApplicationConnected, LogType::Placeholder);
}
}
void nnAc_load()
{
- osLib_addFunction("nn_ac", "Connect__Q2_2nn2acFv", nn_acExport_Connect);
- osLib_addFunction("nn_ac", "ConnectAsync__Q2_2nn2acFv", nn_acExport_ConnectAsync);
- osLib_addFunction("nn_ac", "IsApplicationConnected__Q2_2nn2acFPb", nn_acExport_IsApplicationConnected);
- osLib_addFunction("nn_ac", "GetConnectStatus__Q2_2nn2acFPQ3_2nn2ac6Status", nn_acExport_GetConnectStatus);
- osLib_addFunction("nn_ac", "GetConnectResult__Q2_2nn2acFPQ2_2nn6Result", nn_acExport_GetConnectResult);
- osLib_addFunction("nn_ac", "GetLastErrorCode__Q2_2nn2acFPUi", nn_acExport_GetLastErrorCode);
- osLib_addFunction("nn_ac", "GetStatus__Q2_2nn2acFPQ3_2nn2ac6Status", nn_acExport_GetStatus);
-
osLib_addFunction("nn_ac", "GetAssignedAddress__Q2_2nn2acFPUl", nnAcExport_GetAssignedAddress);
osLib_addFunction("nn_ac", "GetAssignedSubnet__Q2_2nn2acFPUl", nnAcExport_GetAssignedSubnet);
From 1f9b89116f2bad17f9dbd0017b38e0da181fa4c9 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Mon, 11 Mar 2024 21:55:58 +0100
Subject: [PATCH 055/319] Vulkan: Fix crash during shutdown if shaders are
still compiling
Make sure the async shader compiler threads are stopped before the shaders are deleted
---
.../Renderer/Vulkan/RendererShaderVk.cpp | 23 +++++++++----------
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 4 ++--
2 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
index 970f5517..437ef51d 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
@@ -129,19 +129,18 @@ class _ShaderVkThreadPool
public:
void StartThreads()
{
- if (s_threads.empty())
- {
- // create thread pool
- m_shutdownThread.store(false);
- const uint32 threadCount = 2;
- for (uint32 i = 0; i < threadCount; ++i)
- s_threads.emplace_back(&_ShaderVkThreadPool::CompilerThreadFunc, this);
- }
+ if (m_threadsActive.exchange(true))
+ return;
+ // create thread pool
+ const uint32 threadCount = 2;
+ for (uint32 i = 0; i < threadCount; ++i)
+ s_threads.emplace_back(&_ShaderVkThreadPool::CompilerThreadFunc, this);
}
void StopThreads()
{
- m_shutdownThread.store(true);
+ if (!m_threadsActive.exchange(false))
+ return;
for (uint32 i = 0; i < s_threads.size(); ++i)
s_compilationQueueCount.increment();
for (auto& it : s_threads)
@@ -156,7 +155,7 @@ public:
void CompilerThreadFunc()
{
- while (!m_shutdownThread.load(std::memory_order::relaxed))
+ while (m_threadsActive.load(std::memory_order::relaxed))
{
s_compilationQueueCount.decrementWithWait();
s_compilationQueueMutex.lock();
@@ -181,7 +180,7 @@ public:
}
}
- bool HasThreadsRunning() const { return !m_shutdownThread; }
+ bool HasThreadsRunning() const { return m_threadsActive; }
public:
std::vector s_threads;
@@ -191,7 +190,7 @@ public:
std::mutex s_compilationQueueMutex;
private:
- std::atomic m_shutdownThread;
+ std::atomic m_threadsActive;
}ShaderVkThreadPool;
RendererShaderVk::RendererShaderVk(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& glslCode)
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index 5285e4ac..876baa07 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -600,7 +600,7 @@ VulkanRenderer::~VulkanRenderer()
SubmitCommandBuffer();
WaitDeviceIdle();
WaitCommandBufferFinished(GetCurrentCommandBufferId());
- // shut down compilation threads
+ // make sure compilation threads have been shut down
RendererShaderVk::Shutdown();
// shut down pipeline save thread
m_destructionRequested = true;
@@ -1558,12 +1558,12 @@ void VulkanRenderer::Shutdown()
Renderer::Shutdown();
SubmitCommandBuffer();
WaitDeviceIdle();
-
if (m_imguiRenderPass != VK_NULL_HANDLE)
{
vkDestroyRenderPass(m_logicalDevice, m_imguiRenderPass, nullptr);
m_imguiRenderPass = VK_NULL_HANDLE;
}
+ RendererShaderVk::Shutdown();
}
void VulkanRenderer::UnrecoverableError(const char* errMsg) const
From a50e25300d1c3d4eec9ba3085067facff035815f Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Mon, 11 Mar 2024 23:01:37 +0100
Subject: [PATCH 056/319] Vulkan: Remove unused code path for texture copies
In 2020 we switched to drawcalls for texture copies replacing the copy-via-buffer path. It's not been used since so lets remove it
---
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 14 --
.../HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 6 -
.../Renderer/Vulkan/VulkanSurfaceCopy.cpp | 127 +-----------------
3 files changed, 1 insertion(+), 146 deletions(-)
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index 876baa07..c7f8c043 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -577,20 +577,6 @@ VulkanRenderer::VulkanRenderer()
for (sint32 i = 0; i < OCCLUSION_QUERY_POOL_SIZE; i++)
m_occlusionQueries.list_availableQueryIndices.emplace_back(i);
- // enable surface copies via buffer if we have plenty of memory available (otherwise use drawcalls)
- size_t availableSurfaceCopyBufferMem = memoryManager->GetTotalMemoryForBufferType(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- //m_featureControl.mode.useBufferSurfaceCopies = availableSurfaceCopyBufferMem >= 2000ull * 1024ull * 1024ull; // enable if at least 2000MB VRAM
- m_featureControl.mode.useBufferSurfaceCopies = false;
-
- if (m_featureControl.mode.useBufferSurfaceCopies)
- {
- //cemuLog_log(LogType::Force, "Enable surface copies via buffer");
- }
- else
- {
- //cemuLog_log(LogType::Force, "Disable surface copies via buffer (Requires 2GB. Has only {}MB available)", availableSurfaceCopyBufferMem / 1024ull / 1024ull);
- }
-
// start compilation threads
RendererShaderVk::Init();
}
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
index 479c9e54..226edad6 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
@@ -311,7 +311,6 @@ public:
void surfaceCopy_notifyTextureRelease(LatteTextureVk* hostTexture);
private:
- void surfaceCopy_viaBuffer(LatteTextureVk* srcTextureVk, sint32 texSrcMip, sint32 texSrcLevel, LatteTextureVk* dstTextureVk, sint32 texDstMip, sint32 texDstLevel, sint32 effectiveCopyWidth, sint32 effectiveCopyHeight);
void surfaceCopy_viaDrawcall(LatteTextureVk* srcTextureVk, sint32 texSrcMip, sint32 texSrcSlice, LatteTextureVk* dstTextureVk, sint32 texDstMip, sint32 texDstSlice, sint32 effectiveCopyWidth, sint32 effectiveCopyHeight);
void surfaceCopy_cleanup();
@@ -328,10 +327,6 @@ private:
std::unordered_map m_copySurfacePipelineCache;
- VkBuffer m_surfaceCopyBuffer = VK_NULL_HANDLE;
- VkDeviceMemory m_surfaceCopyBufferMemory = VK_NULL_HANDLE;
- size_t m_surfaceCopyBufferSize{};
-
public:
// renderer interface
void bufferCache_init(const sint32 bufferSize) override;
@@ -470,7 +465,6 @@ private:
struct
{
- bool useBufferSurfaceCopies; // if GPU has enough VRAM to spare, allow to use a buffer to copy surfaces (instead of drawcalls)
bool useTFEmulationViaSSBO = true; // emulate transform feedback via shader writes to a storage buffer
}mode;
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp
index d89cdaa1..479b7e60 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp
@@ -763,110 +763,6 @@ bool vkIsBitCompatibleColorDepthFormat(VkFormat format1, VkFormat format2)
return false;
}
-void VulkanRenderer::surfaceCopy_viaBuffer(LatteTextureVk* srcTextureVk, sint32 texSrcMip, sint32 texSrcSlice, LatteTextureVk* dstTextureVk, sint32 texDstMip, sint32 texDstSlice, sint32 effectiveCopyWidth, sint32 effectiveCopyHeight)
-{
- cemu_assert_debug(false); // not used currently
-
- cemu_assert_debug(m_featureControl.mode.useBufferSurfaceCopies);
-
- if (srcTextureVk->dim == Latte::E_DIM::DIM_3D)
- {
- cemu_assert_debug(false);
- return;
- }
- if (dstTextureVk->dim == Latte::E_DIM::DIM_3D)
- {
- cemu_assert_debug(false);
- return;
- }
-
- draw_endRenderPass();
-
- // calculate buffer size required for copy
- VkDeviceSize copySize = std::max(srcTextureVk->getAllocation()->getAllocationSize(), dstTextureVk->getAllocation()->getAllocationSize());
-
- // make sure allocated buffer is large enough
- if (m_surfaceCopyBuffer == VK_NULL_HANDLE || copySize > m_surfaceCopyBufferSize)
- {
- if (m_surfaceCopyBuffer != VK_NULL_HANDLE)
- {
- // free existing buffer
- destroyDeviceMemory(m_surfaceCopyBufferMemory);
- m_surfaceCopyBufferMemory = VK_NULL_HANDLE;
- destroyBuffer(m_surfaceCopyBuffer);
- m_surfaceCopyBuffer = VK_NULL_HANDLE;
- }
- VkDeviceSize allocSize = (copySize + 1024ull * 1024ull - 1ull) & ~(1024ull * 1024ull - 1ull); // align to whole MB
- m_surfaceCopyBufferSize = allocSize;
- memoryManager->CreateBuffer(m_surfaceCopyBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, m_surfaceCopyBuffer, m_surfaceCopyBufferMemory);
- if (m_surfaceCopyBuffer == VK_NULL_HANDLE)
- {
- cemuLog_log(LogType::Force, "Vulkan: Failed to allocate surface copy buffer with size {}", allocSize);
- return;
- }
- }
- if (m_surfaceCopyBuffer == VK_NULL_HANDLE)
- return;
-
- auto vkObjSrcTexture = srcTextureVk->GetImageObj();
- auto vkObjDstTexture = dstTextureVk->GetImageObj();
- vkObjSrcTexture->flagForCurrentCommandBuffer();
- vkObjDstTexture->flagForCurrentCommandBuffer();
-
- VkBufferImageCopy region{};
- region.bufferOffset = 0;
- region.bufferRowLength = effectiveCopyWidth;
- region.bufferImageHeight = effectiveCopyHeight;
-
- if (srcTextureVk->isDepth)
- region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- else
- region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- region.imageSubresource.baseArrayLayer = texSrcSlice;
- region.imageSubresource.layerCount = 1;
- region.imageSubresource.mipLevel = texSrcMip;
-
- region.imageOffset = { 0,0,0 };
- region.imageExtent = { (uint32)effectiveCopyWidth, (uint32)effectiveCopyHeight, 1 };
-
- // make sure all write operations to the src image have finished
- barrier_image(srcTextureVk, region.imageSubresource, VK_IMAGE_LAYOUT_GENERAL);
-
- vkCmdCopyImageToBuffer(getCurrentCommandBuffer(), vkObjSrcTexture->m_image, VK_IMAGE_LAYOUT_GENERAL, m_surfaceCopyBuffer, 1, ®ion);
-
- // copy buffer to image
-
- VkBufferImageCopy imageRegion[2]{};
- sint32 imageRegionCount = 0;
-
- // color or depth only copy
- imageRegion[0].bufferOffset = 0;
- imageRegion[0].imageExtent.width = effectiveCopyWidth;
- imageRegion[0].imageExtent.height = effectiveCopyHeight;
- imageRegion[0].imageExtent.depth = 1;
-
- imageRegion[0].imageSubresource.mipLevel = texDstMip;
- if (dstTextureVk->isDepth)
- imageRegion[0].imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- else
- imageRegion[0].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- imageRegion[0].imageSubresource.baseArrayLayer = texDstSlice;
- imageRegion[0].imageSubresource.layerCount = 1;
-
- imageRegionCount = 1;
-
- // make sure the transfer to the buffer finished
- barrier_bufferRange(m_surfaceCopyBuffer, 0, VK_WHOLE_SIZE);
-
- // make sure all read and write operations to the dst image have finished
- barrier_image(dstTextureVk, imageRegion[0].imageSubresource, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
-
- vkCmdCopyBufferToImage(m_state.currentCommandBuffer, m_surfaceCopyBuffer, vkObjDstTexture->m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageRegionCount, imageRegion);
-
- // make sure transfer has finished before any other operation
- barrier_image(dstTextureVk, imageRegion[0].imageSubresource, VK_IMAGE_LAYOUT_GENERAL);
-}
-
void VulkanRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* sourceTexture, sint32 srcMip, sint32 srcSlice, LatteTexture* destinationTexture, sint32 dstMip, sint32 dstSlice, sint32 width, sint32 height)
{
// scale copy size to effective size
@@ -899,28 +795,7 @@ void VulkanRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* s
return;
}
- VkFormat srcFormatVk = srcTextureVk->GetFormat();
- VkFormat dstFormatVk = dstTextureVk->GetFormat();
-
- if ((srcTextureVk->isDepth && !dstTextureVk->isDepth) ||
- !srcTextureVk->isDepth && dstTextureVk->isDepth)
- {
- // depth to color or
- // color to depth
- if (m_featureControl.mode.useBufferSurfaceCopies && vkIsBitCompatibleColorDepthFormat(srcFormatVk, dstFormatVk))
- surfaceCopy_viaBuffer(srcTextureVk, texSrcMip, texSrcSlice, dstTextureVk, texDstMip, texDstSlice, effectiveCopyWidth, effectiveCopyHeight);
- else
- surfaceCopy_viaDrawcall(srcTextureVk, texSrcMip, texSrcSlice, dstTextureVk, texDstMip, texDstSlice, effectiveCopyWidth, effectiveCopyHeight);
- }
- else
- {
- // depth to depth or
- // color to color
- if (m_featureControl.mode.useBufferSurfaceCopies && srcFormatVk == dstFormatVk)
- surfaceCopy_viaBuffer(srcTextureVk, texSrcMip, texSrcSlice, dstTextureVk, texDstMip, texDstSlice, effectiveCopyWidth, effectiveCopyHeight);
- else
- surfaceCopy_viaDrawcall(srcTextureVk, texSrcMip, texSrcSlice, dstTextureVk, texDstMip, texDstSlice, effectiveCopyWidth, effectiveCopyHeight);
- }
+ surfaceCopy_viaDrawcall(srcTextureVk, texSrcMip, texSrcSlice, dstTextureVk, texDstMip, texDstSlice, effectiveCopyWidth, effectiveCopyHeight);
}
// called whenever a texture is destroyed
From 224866c3d218995458d957c1c3777313e289da63 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Tue, 12 Mar 2024 01:37:07 +0100
Subject: [PATCH 057/319] CI: Work around a vcpkg issue by checking out an
earlier commit
---
.github/workflows/build.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 00aac0fe..f3b834b4 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -28,7 +28,7 @@ jobs:
run: |
cd dependencies/vcpkg
git fetch --unshallow
- git pull --all
+ git checkout 431eb6bda0950874c8d4ed929cc66e15d8aae46f
- name: Setup release mode parameters (for deploy)
if: ${{ inputs.deploymode == 'release' }}
@@ -133,7 +133,7 @@ jobs:
run: |
cd dependencies/vcpkg
git fetch --unshallow
- git pull --all
+ git checkout 431eb6bda0950874c8d4ed929cc66e15d8aae46f
- name: Setup release mode parameters (for deploy)
if: ${{ inputs.deploymode == 'release' }}
From 6fa77feba3ec7437b57b6c4c221cde9eb07cd399 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Tue, 12 Mar 2024 05:52:53 +0100
Subject: [PATCH 058/319] Latte: Fix regression in dd7cb74
---
src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp | 2 +-
src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp | 6 +++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
index 8c29ccc5..d7c5408f 100644
--- a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
@@ -618,7 +618,7 @@ bool LatteMRT::UpdateCurrentFBO()
}
// set effective size
sint32 effectiveWidth, effectiveHeight;
- depthBufferView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, depthBufferViewFirstSlice);
+ depthBufferView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0);
if (rtEffectiveSize->width == 0 && rtEffectiveSize->height == 0)
{
rtEffectiveSize->width = effectiveWidth;
diff --git a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
index b35f608c..4e5c303c 100644
--- a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
@@ -206,7 +206,11 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u
bool isDepthSampler = shaderContext->textureUsesDepthCompare[textureIndex];
// look for already existing texture
- LatteTextureView* textureView = LatteTextureViewLookupCache::lookup(physAddr, width, height, depth, pitch, viewFirstMip, viewNumMips, viewFirstSlice, viewNumSlices, format, dim, isDepthSampler);
+ LatteTextureView* textureView;
+ if (isDepthSampler == false)
+ textureView = LatteTextureViewLookupCache::lookup(physAddr, width, height, depth, pitch, viewFirstMip, viewNumMips, viewFirstSlice, viewNumSlices, format, dim);
+ else
+ textureView = LatteTextureViewLookupCache::lookup(physAddr, width, height, depth, pitch, viewFirstMip, viewNumMips, viewFirstSlice, viewNumSlices, format, dim, true);
if (!textureView)
{
// view not found, create a new mapping which will also create a new texture if necessary
From 8bc444bb97cfeb747a66142ad31884323785af32 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Tue, 12 Mar 2024 16:16:52 +0100
Subject: [PATCH 059/319] Latte: Derive framebuffer size from correct mip of
depth buffer
---
src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp | 2 +-
src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp | 4 ++--
src/Cafe/HW/Latte/Core/LatteTextureView.cpp | 3 +--
src/Cafe/HW/Latte/Core/LatteTextureView.h | 2 +-
4 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
index d7c5408f..f84bbecd 100644
--- a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
@@ -618,7 +618,7 @@ bool LatteMRT::UpdateCurrentFBO()
}
// set effective size
sint32 effectiveWidth, effectiveHeight;
- depthBufferView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, 0);
+ depthBufferView->baseTexture->GetEffectiveSize(effectiveWidth, effectiveHeight, depthBufferView->firstMip);
if (rtEffectiveSize->width == 0 && rtEffectiveSize->height == 0)
{
rtEffectiveSize->width = effectiveWidth;
diff --git a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
index 4e5c303c..b9ccbac4 100644
--- a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
@@ -207,10 +207,10 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u
bool isDepthSampler = shaderContext->textureUsesDepthCompare[textureIndex];
// look for already existing texture
LatteTextureView* textureView;
- if (isDepthSampler == false)
+ if (!isDepthSampler)
textureView = LatteTextureViewLookupCache::lookup(physAddr, width, height, depth, pitch, viewFirstMip, viewNumMips, viewFirstSlice, viewNumSlices, format, dim);
else
- textureView = LatteTextureViewLookupCache::lookup(physAddr, width, height, depth, pitch, viewFirstMip, viewNumMips, viewFirstSlice, viewNumSlices, format, dim, true);
+ textureView = LatteTextureViewLookupCache::lookupWithColorOrDepthType(physAddr, width, height, depth, pitch, viewFirstMip, viewNumMips, viewFirstSlice, viewNumSlices, format, dim, true);
if (!textureView)
{
// view not found, create a new mapping which will also create a new texture if necessary
diff --git a/src/Cafe/HW/Latte/Core/LatteTextureView.cpp b/src/Cafe/HW/Latte/Core/LatteTextureView.cpp
index cac5bcce..2773a34d 100644
--- a/src/Cafe/HW/Latte/Core/LatteTextureView.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTextureView.cpp
@@ -143,7 +143,6 @@ void LatteTextureViewLookupCache::RemoveAll(LatteTextureView* view)
}
}
-
LatteTextureView* LatteTextureViewLookupCache::lookup(MPTR physAddr, sint32 width, sint32 height, sint32 depth, sint32 pitch, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, Latte::E_GX2SURFFMT format, Latte::E_DIM dim)
{
// todo - add tileMode param to this and the other lookup functions?
@@ -163,7 +162,7 @@ LatteTextureView* LatteTextureViewLookupCache::lookup(MPTR physAddr, sint32 widt
return nullptr;
}
-LatteTextureView* LatteTextureViewLookupCache::lookup(MPTR physAddr, sint32 width, sint32 height, sint32 depth, sint32 pitch, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, Latte::E_GX2SURFFMT format, Latte::E_DIM dim, bool isDepth)
+LatteTextureView* LatteTextureViewLookupCache::lookupWithColorOrDepthType(MPTR physAddr, sint32 width, sint32 height, sint32 depth, sint32 pitch, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, Latte::E_GX2SURFFMT format, Latte::E_DIM dim, bool isDepth)
{
cemu_assert_debug(firstSlice == 0);
uint32 key = _getViewBucketKey(physAddr, width, height, pitch);
diff --git a/src/Cafe/HW/Latte/Core/LatteTextureView.h b/src/Cafe/HW/Latte/Core/LatteTextureView.h
index a6d2e16c..abda084a 100644
--- a/src/Cafe/HW/Latte/Core/LatteTextureView.h
+++ b/src/Cafe/HW/Latte/Core/LatteTextureView.h
@@ -41,7 +41,7 @@ public:
static void RemoveAll(LatteTextureView* view);
static LatteTextureView* lookup(MPTR physAddr, sint32 width, sint32 height, sint32 depth, sint32 pitch, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, Latte::E_GX2SURFFMT format, Latte::E_DIM dim);
- static LatteTextureView* lookup(MPTR physAddr, sint32 width, sint32 height, sint32 depth, sint32 pitch, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, Latte::E_GX2SURFFMT format, Latte::E_DIM dim, bool isDepth);
+ static LatteTextureView* lookupWithColorOrDepthType(MPTR physAddr, sint32 width, sint32 height, sint32 depth, sint32 pitch, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, Latte::E_GX2SURFFMT format, Latte::E_DIM dim, bool isDepth);
static LatteTextureView* lookupSlice(MPTR physAddr, sint32 width, sint32 height, sint32 pitch, sint32 firstMip, sint32 firstSlice, Latte::E_GX2SURFFMT format);
static LatteTextureView* lookupSliceMinSize(MPTR physAddr, sint32 minWidth, sint32 minHeight, sint32 pitch, sint32 firstMip, sint32 firstSlice, Latte::E_GX2SURFFMT format);
static LatteTextureView* lookupSliceEx(MPTR physAddr, sint32 width, sint32 height, sint32 pitch, sint32 firstMip, sint32 firstSlice, Latte::E_GX2SURFFMT format, bool isDepth);
From bc04662525acbab50251a28a0a2b39d95fda7707 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Wed, 13 Mar 2024 02:41:42 +0100
Subject: [PATCH 060/319] Latte+GL+VK: Improve handling of gfx pack texture
overwrite format
Graphic packs can overwrite the format of a texture (e.g. for higher bitdepth to lessen banding) but the code for this wasn't correctly working anymore.
- Fixes overwrite format being ignored for texture views on Vulkan backend
- Fixes overwrite format not being used for texture views on OpenGL
Format aliasing is complicated enough as it is, even without overwrites, so this adds a new rule to make behavior more well defined: If two textures share memory but only one uses an overwrite format, then they are no longer synchronized and are considered separate textures.
Bonus fixes for OpenGL:
- Use fbo 0 instead of -1 as the default. This silences some warnings in debug output
- On OpenGL, bind new framebuffers on handle generation so they are considered created
---
src/Cafe/HW/Latte/Core/LatteTexture.cpp | 11 ++++++
.../Latte/Renderer/OpenGL/LatteTextureGL.cpp | 2 +-
.../Renderer/OpenGL/LatteTextureViewGL.cpp | 14 ++++---
.../Latte/Renderer/OpenGL/OpenGLRenderer.cpp | 37 ++++++++++---------
.../HW/Latte/Renderer/OpenGL/OpenGLRenderer.h | 2 +-
.../Renderer/Vulkan/LatteTextureViewVk.cpp | 7 +++-
6 files changed, 48 insertions(+), 25 deletions(-)
diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.cpp b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
index 91a1aa56..21b49c9a 100644
--- a/src/Cafe/HW/Latte/Core/LatteTexture.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
@@ -434,6 +434,11 @@ void LatteTexture_SyncSlice(LatteTexture* srcTexture, sint32 srcSliceIndex, sint
sint32 dstWidth = dstTexture->width;
sint32 dstHeight = dstTexture->height;
+ if(srcTexture->overwriteInfo.hasFormatOverwrite != dstTexture->overwriteInfo.hasFormatOverwrite)
+ return; // dont sync: format overwrite state needs to match. Not strictly necessary but it simplifies logic down the road
+ else if(srcTexture->overwriteInfo.hasFormatOverwrite && srcTexture->overwriteInfo.format != dstTexture->overwriteInfo.format)
+ return; // both are overwritten but with different formats
+
if (srcMipIndex == 0 && dstMipIndex == 0 && (srcTexture->tileMode == Latte::E_HWTILEMODE::TM_LINEAR_ALIGNED || srcTexture->tileMode == Latte::E_HWTILEMODE::TM_1D_TILED_THIN1) && srcTexture->height > dstTexture->height && (srcTexture->height % dstTexture->height) == 0)
{
bool isMatch = srcTexture->tileMode == Latte::E_HWTILEMODE::TM_LINEAR_ALIGNED;
@@ -816,6 +821,12 @@ VIEWCOMPATIBILITY LatteTexture_CanTextureBeRepresentedAsView(LatteTexture* baseT
{
relativeMipIndex = 0;
relativeSliceIndex = 0;
+ if (baseTexture->overwriteInfo.hasFormatOverwrite)
+ {
+ // if the base format is overwritten, then we only allow aliasing if the view format matches the base format
+ if (baseTexture->format != format)
+ return VIEW_NOT_COMPATIBLE;
+ }
if (LatteTexture_IsFormatViewCompatible(baseTexture->format, format) == false)
return VIEW_NOT_COMPATIBLE;
if (baseTexture->physAddress == physAddr && baseTexture->pitch == pitch)
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp
index 584af40c..cd363612 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp
@@ -26,7 +26,7 @@ LatteTextureGL::LatteTextureGL(Latte::E_DIM dim, MPTR physAddress, MPTR physMipA
GenerateEmptyTextureFromGX2Dim(dim, this->glId_texture, this->glTexTarget, true);
// set format info
FormatInfoGL glFormatInfo;
- GetOpenGLFormatInfo(isDepth, format, dim, &glFormatInfo);
+ GetOpenGLFormatInfo(isDepth, overwriteInfo.hasFormatOverwrite ? (Latte::E_GX2SURFFMT)overwriteInfo.format : format, dim, &glFormatInfo);
this->glInternalFormat = glFormatInfo.glInternalFormat;
this->isAlternativeFormat = glFormatInfo.isUsingAlternativeFormat;
this->hasStencil = glFormatInfo.hasStencil; // todo - should get this from the GX2 format?
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.cpp
index 29085642..3e8abe8e 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureViewGL.cpp
@@ -55,12 +55,16 @@ LatteTextureViewGL::~LatteTextureViewGL()
void LatteTextureViewGL::InitAliasView()
{
const auto texture = (LatteTextureGL*)baseTexture;
- // get internal format
- if (baseTexture->isDepth)
+ // compute internal format
+ if(texture->overwriteInfo.hasFormatOverwrite)
+ {
+ cemu_assert_debug(format == texture->format);
+ glInternalFormat = texture->glInternalFormat; // for format overwrite no aliasing is allowed and thus we always inherit the internal format of the base texture
+ }
+ else if (baseTexture->isDepth)
{
// depth is handled differently
- cemuLog_logDebug(LogType::Force, "Creating depth view");
- cemu_assert(format == texture->format); // todo
+ cemu_assert(format == texture->format); // is depth alias with different format intended?
glInternalFormat = texture->glInternalFormat;
}
else
@@ -73,7 +77,7 @@ void LatteTextureViewGL::InitAliasView()
catchOpenGLError();
if (firstMip >= texture->maxPossibleMipLevels)
{
- cemuLog_logDebug(LogType::Force, "_createNewView: Out of bounds mip level requested");
+ cemuLog_logDebug(LogType::Force, "InitAliasView(): Out of bounds mip level requested");
glTextureView(glTexId, glTexTarget, texture->glId_texture, glInternalFormat, texture->maxPossibleMipLevels - 1, numMip, firstSlice, this->numSlice);
}
else
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
index 68d7def6..943e39a0 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
@@ -330,13 +330,14 @@ void OpenGLRenderer::Initialize()
lock.unlock();
// create framebuffer for fast clearing (avoid glClearTexSubImage on Nvidia)
- if (this->m_vendor == GfxVendor::Nvidia || glClearTexSubImage == nullptr)
+ if (glCreateFramebuffers)
+ glCreateFramebuffers(1, &glRendererState.clearFBO);
+ else
{
- // generate framebuffer
- if (glCreateFramebuffers && false)
- glCreateFramebuffers(1, &glRendererState.clearFBO);
- else
- glGenFramebuffers(1, &glRendererState.clearFBO);
+ glGenFramebuffers(1, &glRendererState.clearFBO);
+ // bind to initialize
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, glRendererState.clearFBO);
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
}
draw_init();
@@ -425,9 +426,12 @@ void _glDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GL
return;
if (LatteGPUState.glVendor == GLVENDOR_NVIDIA && strstr(message, "Dithering is enabled"))
return;
-
+ if (LatteGPUState.glVendor == GLVENDOR_NVIDIA && strstr(message, "Blending is enabled, but is not supported for integer framebuffers"))
+ return;
if (LatteGPUState.glVendor == GLVENDOR_NVIDIA && strstr(message, "does not have a defined base level"))
return;
+ if(LatteGPUState.glVendor == GLVENDOR_NVIDIA && strstr(message, "has depth comparisons disabled, with a texture object"))
+ return;
cemuLog_log(LogType::Force, "GLDEBUG: {}", message);
@@ -670,7 +674,10 @@ void OpenGLRenderer::rendertarget_deleteCachedFBO(LatteCachedFBO* cfbo)
{
auto cfboGL = (CachedFBOGL*)cfbo;
if (prevBoundFBO == cfboGL->glId_fbo)
- prevBoundFBO = -1;
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
+ prevBoundFBO = 0;
+ }
glDeleteFramebuffers(1, &cfboGL->glId_fbo);
}
@@ -1013,9 +1020,6 @@ void OpenGLRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTextureGeneri
effectiveBaseHeight = hostTexture->overwriteInfo.height;
effectiveBaseDepth = hostTexture->overwriteInfo.depth;
}
- // get format info
- LatteTextureGL::FormatInfoGL glFormatInfo;
- LatteTextureGL::GetOpenGLFormatInfo(hostTexture->isDepth, hostTexture->overwriteInfo.hasFormatOverwrite ? (Latte::E_GX2SURFFMT)hostTexture->overwriteInfo.format : hostTexture->format, hostTexture->dim, &glFormatInfo);
// calculate mip count
sint32 mipLevels = std::min(hostTexture->mipLevels, hostTexture->maxPossibleMipLevels);
mipLevels = std::max(mipLevels, 1);
@@ -1023,25 +1027,25 @@ void OpenGLRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTextureGeneri
if (hostTexture->dim == Latte::E_DIM::DIM_2D || hostTexture->dim == Latte::E_DIM::DIM_2D_MSAA)
{
cemu_assert_debug(effectiveBaseDepth == 1);
- glTextureStorage2DWrapper(GL_TEXTURE_2D, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight);
+ glTextureStorage2DWrapper(GL_TEXTURE_2D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight);
}
else if (hostTexture->dim == Latte::E_DIM::DIM_1D)
{
cemu_assert_debug(effectiveBaseHeight == 1);
cemu_assert_debug(effectiveBaseDepth == 1);
- glTextureStorage1DWrapper(GL_TEXTURE_1D, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth);
+ glTextureStorage1DWrapper(GL_TEXTURE_1D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth);
}
else if (hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY || hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY_MSAA)
{
- glTextureStorage3DWrapper(GL_TEXTURE_2D_ARRAY, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
+ glTextureStorage3DWrapper(GL_TEXTURE_2D_ARRAY, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
}
else if (hostTexture->dim == Latte::E_DIM::DIM_3D)
{
- glTextureStorage3DWrapper(GL_TEXTURE_3D, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
+ glTextureStorage3DWrapper(GL_TEXTURE_3D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
}
else if (hostTexture->dim == Latte::E_DIM::DIM_CUBEMAP)
{
- glTextureStorage3DWrapper(GL_TEXTURE_CUBE_MAP_ARRAY, hostTexture->glId_texture, mipLevels, glFormatInfo.glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, effectiveBaseDepth);
+ glTextureStorage3DWrapper(GL_TEXTURE_CUBE_MAP_ARRAY, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, effectiveBaseDepth);
}
else
{
@@ -1279,7 +1283,6 @@ void OpenGLRenderer::texture_copyImageSubData(LatteTexture* src, sint32 srcMip,
{
auto srcGL = (LatteTextureGL*)src;
auto dstGL = (LatteTextureGL*)dst;
-
if ((srcGL->isAlternativeFormat || dstGL->isAlternativeFormat) && (srcGL->glInternalFormat != dstGL->glInternalFormat))
{
if (srcGL->format == Latte::E_GX2SURFFMT::R16_G16_B16_A16_UINT && dstGL->format == Latte::E_GX2SURFFMT::BC4_UNORM)
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
index 8a4b1a1d..026264cf 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
@@ -195,7 +195,7 @@ private:
GLuint glStreamoutCacheRingBuffer;
// cfbo
- GLuint prevBoundFBO = -1;
+ GLuint prevBoundFBO = 0;
GLuint glId_fbo = 0;
// renderstate
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureViewVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureViewVk.cpp
index d87d9ea7..aae7e9d1 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureViewVk.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureViewVk.cpp
@@ -57,7 +57,12 @@ uint32 LatteTextureVk_AdjustTextureCompSel(Latte::E_GX2SURFFMT format, uint32 co
LatteTextureViewVk::LatteTextureViewVk(VkDevice device, LatteTextureVk* texture, Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount)
: LatteTextureView(texture, firstMip, mipCount, firstSlice, sliceCount, dim, format), m_device(device)
{
- if (dim != texture->dim || format != texture->format)
+ if(texture->overwriteInfo.hasFormatOverwrite)
+ {
+ cemu_assert_debug(format == texture->format); // if format overwrite is used, the texture is no longer taking part in aliasing and the format of any view has to match
+ m_format = texture->GetFormat();
+ }
+ else if (dim != texture->dim || format != texture->format)
{
VulkanRenderer::FormatInfoVK texFormatInfo;
VulkanRenderer::GetInstance()->GetTextureFormatInfoVK(format, texture->isDepth, dim, 0, 0, &texFormatInfo);
From 193767e6cccafd971e9028386fdfe7f8f46b2d21 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Thu, 14 Mar 2024 01:04:05 +0100
Subject: [PATCH 061/319] Latte+Vulkan: Code cleanup
Besides a general cleanup:
- Remove deprecated resource destruction queues
- Move functionality from renderer into Latte base classes to deduplicate code
---
src/Cafe/HW/Latte/Core/Latte.h | 2 +-
.../HW/Latte/Core/LatteCommandProcessor.cpp | 12 +--
src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp | 43 ++-------
src/Cafe/HW/Latte/Core/LatteTexture.cpp | 10 +++
src/Cafe/HW/Latte/Core/LatteTexture.h | 2 +
src/Cafe/HW/Latte/Core/LatteTextureCache.cpp | 2 +-
src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp | 2 +-
.../Latte/Renderer/OpenGL/LatteTextureGL.cpp | 73 +++++++++++-----
.../HW/Latte/Renderer/OpenGL/LatteTextureGL.h | 12 +--
.../Latte/Renderer/OpenGL/OpenGLRenderer.cpp | 51 -----------
.../HW/Latte/Renderer/OpenGL/OpenGLRenderer.h | 3 -
src/Cafe/HW/Latte/Renderer/Renderer.h | 3 -
.../HW/Latte/Renderer/Vulkan/CachedFBOVk.cpp | 4 +-
.../Renderer/Vulkan/LatteTextureViewVk.cpp | 6 +-
.../Latte/Renderer/Vulkan/LatteTextureVk.cpp | 14 ++-
.../HW/Latte/Renderer/Vulkan/LatteTextureVk.h | 5 +-
.../Renderer/Vulkan/RendererShaderVk.cpp | 3 +-
.../Latte/Renderer/Vulkan/VKRPipelineInfo.cpp | 2 +-
.../Vulkan/VulkanPipelineStableCache.cpp | 2 +-
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 87 +------------------
.../HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 25 +-----
.../Renderer/Vulkan/VulkanSurfaceCopy.cpp | 8 +-
src/imgui/imgui_impl_vulkan.cpp | 13 +--
23 files changed, 115 insertions(+), 269 deletions(-)
diff --git a/src/Cafe/HW/Latte/Core/Latte.h b/src/Cafe/HW/Latte/Core/Latte.h
index dc3cbc91..d9419a6a 100644
--- a/src/Cafe/HW/Latte/Core/Latte.h
+++ b/src/Cafe/HW/Latte/Core/Latte.h
@@ -98,7 +98,7 @@ void LatteRenderTarget_copyToBackbuffer(LatteTextureView* textureView, bool isPa
void LatteRenderTarget_GetCurrentVirtualViewportSize(sint32* viewportWidth, sint32* viewportHeight);
void LatteRenderTarget_itHLESwapScanBuffer();
-void LatteRenderTarget_itHLEClearColorDepthStencil(uint32 clearMask, MPTR colorBufferMPTR, MPTR colorBufferFormat, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferPitch, uint32 colorBufferViewFirstSlice, uint32 colorBufferViewNumSlice, MPTR depthBufferMPTR, MPTR depthBufferFormat, Latte::E_HWTILEMODE depthBufferTileMode, sint32 depthBufferWidth, sint32 depthBufferHeight, sint32 depthBufferPitch, sint32 depthBufferViewFirstSlice, sint32 depthBufferViewNumSlice, float r, float g, float b, float a, float clearDepth, uint32 clearStencil);
+void LatteRenderTarget_itHLEClearColorDepthStencil(uint32 clearMask, MPTR colorBufferMPTR, Latte::E_GX2SURFFMT colorBufferFormat, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferPitch, uint32 colorBufferViewFirstSlice, uint32 colorBufferViewNumSlice, MPTR depthBufferMPTR, Latte::E_GX2SURFFMT depthBufferFormat, Latte::E_HWTILEMODE depthBufferTileMode, sint32 depthBufferWidth, sint32 depthBufferHeight, sint32 depthBufferPitch, sint32 depthBufferViewFirstSlice, sint32 depthBufferViewNumSlice, float r, float g, float b, float a, float clearDepth, uint32 clearStencil);
void LatteRenderTarget_itHLECopyColorBufferToScanBuffer(MPTR colorBufferPtr, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferSliceIndex, uint32 colorBufferFormat, uint32 colorBufferPitch, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferSwizzle, uint32 renderTarget);
void LatteRenderTarget_unloadAll();
diff --git a/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp b/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp
index 60e5935c..c928f89f 100644
--- a/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp
@@ -864,8 +864,8 @@ LatteCMDPtr LatteCP_itHLEClearColorDepthStencil(LatteCMDPtr cmd, uint32 nWords)
cemu_assert_debug(nWords == 23);
uint32 clearMask = LatteReadCMD(); // color (1), depth (2), stencil (4)
// color buffer
- MPTR colorBufferMPTR = LatteReadCMD(); // MPTR for color buffer (physical address)
- MPTR colorBufferFormat = LatteReadCMD(); // format for color buffer
+ MPTR colorBufferMPTR = LatteReadCMD(); // physical address for color buffer
+ Latte::E_GX2SURFFMT colorBufferFormat = (Latte::E_GX2SURFFMT)LatteReadCMD();
Latte::E_HWTILEMODE colorBufferTilemode = (Latte::E_HWTILEMODE)LatteReadCMD();
uint32 colorBufferWidth = LatteReadCMD();
uint32 colorBufferHeight = LatteReadCMD();
@@ -873,8 +873,8 @@ LatteCMDPtr LatteCP_itHLEClearColorDepthStencil(LatteCMDPtr cmd, uint32 nWords)
uint32 colorBufferViewFirstSlice = LatteReadCMD();
uint32 colorBufferViewNumSlice = LatteReadCMD();
// depth buffer
- MPTR depthBufferMPTR = LatteReadCMD(); // MPTR for depth buffer (physical address)
- MPTR depthBufferFormat = LatteReadCMD(); // format for depth buffer
+ MPTR depthBufferMPTR = LatteReadCMD(); // physical address for depth buffer
+ Latte::E_GX2SURFFMT depthBufferFormat = (Latte::E_GX2SURFFMT)LatteReadCMD();
Latte::E_HWTILEMODE depthBufferTileMode = (Latte::E_HWTILEMODE)LatteReadCMD();
uint32 depthBufferWidth = LatteReadCMD();
uint32 depthBufferHeight = LatteReadCMD();
@@ -893,8 +893,8 @@ LatteCMDPtr LatteCP_itHLEClearColorDepthStencil(LatteCMDPtr cmd, uint32 nWords)
LatteRenderTarget_itHLEClearColorDepthStencil(
clearMask,
- colorBufferMPTR, colorBufferFormat, colorBufferTilemode, colorBufferWidth, colorBufferHeight, colorBufferPitch, colorBufferViewFirstSlice, colorBufferViewNumSlice,
- depthBufferMPTR, depthBufferFormat, depthBufferTileMode, depthBufferWidth, depthBufferHeight, depthBufferPitch, depthBufferViewFirstSlice, depthBufferViewNumSlice,
+ colorBufferMPTR, colorBufferFormat, colorBufferTilemode, colorBufferWidth, colorBufferHeight, colorBufferPitch, colorBufferViewFirstSlice, colorBufferViewNumSlice,
+ depthBufferMPTR, depthBufferFormat, depthBufferTileMode, depthBufferWidth, depthBufferHeight, depthBufferPitch, depthBufferViewFirstSlice, depthBufferViewNumSlice,
r, g, b, a,
clearDepth, clearStencil);
return cmd;
diff --git a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
index f84bbecd..30069712 100644
--- a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
@@ -221,35 +221,9 @@ void LatteMRT::BindDepthBufferOnly(LatteTextureView* view)
ApplyCurrentState();
}
-/***************************************************/
-
-LatteTextureView* LatteMRT_FindColorBufferForClearing(MPTR colorBufferPtr, sint32 colorBufferWidth, sint32 colorBufferHeight, sint32 colorBufferPitch, uint32 format, sint32 sliceIndex, sint32* searchIndex)
-{
- LatteTextureView* view = LatteTC_LookupTextureByData(colorBufferPtr, colorBufferWidth, colorBufferHeight, colorBufferPitch, 0, 1, sliceIndex, 1, searchIndex);
- if (view == nullptr)
- return nullptr;
- return view;
-}
-
-LatteTextureView* LatteMRT_CreateColorBuffer(MPTR colorBufferPhysMem, uint32 width, uint32 height, uint32 pitch, Latte::E_GX2SURFFMT format, Latte::E_HWTILEMODE tileMode, uint32 swizzle, uint32 viewSlice)
-{
- cemu_assert_debug(colorBufferPhysMem != MPTR_NULL);
- LatteTextureView* textureView;
- if(viewSlice != 0)
- textureView = LatteTexture_CreateMapping(colorBufferPhysMem, MPTR_NULL, width, height, viewSlice+1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D_ARRAY, Latte::E_DIM::DIM_2D, false);
- else
- textureView = LatteTexture_CreateMapping(colorBufferPhysMem, MPTR_NULL, width, height, 1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, false);
- return textureView;
-}
-
LatteTextureView* LatteMRT_CreateDepthBuffer(MPTR depthBufferPhysMem, uint32 width, uint32 height, uint32 pitch, Latte::E_HWTILEMODE tileMode, Latte::E_GX2SURFFMT format, uint32 swizzle, sint32 viewSlice)
{
- LatteTextureView* textureView;
- if(viewSlice == 0)
- textureView = LatteTexture_CreateMapping(depthBufferPhysMem, MPTR_NULL, width, height, 1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true);
- else
- textureView = LatteTexture_CreateMapping(depthBufferPhysMem, MPTR_NULL, width, height, viewSlice+1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, Latte::E_DIM::DIM_2D_ARRAY, Latte::E_DIM::DIM_2D, true);
-
+ LatteTextureView* textureView = LatteTexture_CreateMapping(depthBufferPhysMem, MPTR_NULL, width, height, viewSlice+1, pitch, tileMode, swizzle, 0, 1, viewSlice, 1, format, viewSlice > 0 ? Latte::E_DIM::DIM_2D_ARRAY : Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true);
LatteMRT::SetDepthAndStencilAttachment(textureView, textureView->baseTexture->hasStencil);
return textureView;
}
@@ -605,7 +579,7 @@ bool LatteMRT::UpdateCurrentFBO()
if (depthBufferPhysMem != MPTR_NULL)
{
LatteTextureView* depthBufferView = LatteTextureViewLookupCache::lookupSliceEx(depthBufferPhysMem, depthBufferWidth, depthBufferHeight, depthBufferPitch, 0, depthBufferViewFirstSlice, depthBufferFormat, true);
- if (depthBufferView == nullptr)
+ if (!depthBufferView)
{
// create new depth buffer view and if it doesn't exist then also create the texture
depthBufferView = LatteTexture_CreateMapping(depthBufferPhysMem, 0, depthBufferWidth, depthBufferHeight, depthBufferViewFirstSlice+1, depthBufferPitch, depthBufferTileMode, depthBufferSwizzle, 0, 1, depthBufferViewFirstSlice, 1, depthBufferFormat, depthBufferViewFirstSlice > 0 ? Latte::E_DIM::DIM_2D_ARRAY : Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true);
@@ -768,7 +742,10 @@ void LatteRenderTarget_applyTextureDepthClear(LatteTexture* texture, uint32 slic
LatteTexture_MarkDynamicTextureAsChanged(texture->baseView, sliceIndex, mipIndex, eventCounter);
}
-void LatteRenderTarget_itHLEClearColorDepthStencil(uint32 clearMask, MPTR colorBufferMPTR, MPTR colorBufferFormat, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferPitch, uint32 colorBufferViewFirstSlice, uint32 colorBufferViewNumSlice, MPTR depthBufferMPTR, MPTR depthBufferFormat, Latte::E_HWTILEMODE depthBufferTileMode, sint32 depthBufferWidth, sint32 depthBufferHeight, sint32 depthBufferPitch, sint32 depthBufferViewFirstSlice, sint32 depthBufferViewNumSlice, float r, float g, float b, float a, float clearDepth, uint32 clearStencil)
+void LatteRenderTarget_itHLEClearColorDepthStencil(uint32 clearMask,
+ MPTR colorBufferMPTR, Latte::E_GX2SURFFMT colorBufferFormat, Latte::E_HWTILEMODE colorBufferTilemode, uint32 colorBufferWidth, uint32 colorBufferHeight, uint32 colorBufferPitch, uint32 colorBufferViewFirstSlice, uint32 colorBufferViewNumSlice,
+ MPTR depthBufferMPTR, Latte::E_GX2SURFFMT depthBufferFormat, Latte::E_HWTILEMODE depthBufferTileMode, sint32 depthBufferWidth, sint32 depthBufferHeight, sint32 depthBufferPitch, sint32 depthBufferViewFirstSlice, sint32 depthBufferViewNumSlice,
+ float r, float g, float b, float a, float clearDepth, uint32 clearStencil)
{
uint32 depthBufferMipIndex = 0; // todo
uint32 colorBufferMipIndex = 0; // todo
@@ -803,13 +780,11 @@ void LatteRenderTarget_itHLEClearColorDepthStencil(uint32 clearMask, MPTR colorB
bool targetFound = false;
while (true)
{
- LatteTextureView* colorView = LatteMRT_FindColorBufferForClearing(colorBufferMPTR, colorBufferWidth, colorBufferHeight, colorBufferPitch, colorBufferFormat, colorBufferViewFirstSlice, &searchIndex);
+ LatteTextureView* colorView = LatteTC_LookupTextureByData(colorBufferMPTR, colorBufferWidth, colorBufferHeight, colorBufferPitch, 0, 1, colorBufferViewFirstSlice, 1, &searchIndex);
if (!colorView)
break;
- if (Latte::GetFormatBits((Latte::E_GX2SURFFMT)colorBufferFormat) != Latte::GetFormatBits(colorView->baseTexture->format))
- {
+ if (Latte::GetFormatBits(colorBufferFormat) != Latte::GetFormatBits(colorView->baseTexture->format))
continue;
- }
if (colorView->baseTexture->pitch == colorBufferPitch && colorView->baseTexture->height == colorBufferHeight)
targetFound = true;
@@ -821,7 +796,7 @@ void LatteRenderTarget_itHLEClearColorDepthStencil(uint32 clearMask, MPTR colorB
{
// create new texture with matching format
cemu_assert_debug(colorBufferViewNumSlice <= 1);
- LatteTextureView* newColorView = LatteMRT_CreateColorBuffer(colorBufferMPTR, colorBufferWidth, colorBufferHeight, colorBufferPitch, (Latte::E_GX2SURFFMT)colorBufferFormat, colorBufferTilemode, colorBufferSwizzle, colorBufferViewFirstSlice);
+ LatteTextureView* newColorView = LatteTexture_CreateMapping(colorBufferMPTR, MPTR_NULL, colorBufferWidth, colorBufferHeight, colorBufferViewFirstSlice+1, colorBufferPitch, colorBufferTilemode, colorBufferSwizzle, 0, 1, colorBufferViewFirstSlice, 1, colorBufferFormat, colorBufferViewFirstSlice > 0 ? Latte::E_DIM::DIM_2D_ARRAY : Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, false);
LatteRenderTarget_applyTextureColorClear(newColorView->baseTexture, colorBufferViewFirstSlice, colorBufferMipIndex, r, g, b, a, eventCounter);
}
}
diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.cpp b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
index 21b49c9a..d6f576d4 100644
--- a/src/Cafe/HW/Latte/Core/LatteTexture.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
@@ -1199,6 +1199,15 @@ std::vector& LatteTexture::GetAllTextures()
return sAllTextures;
}
+bool LatteTexture_GX2FormatHasStencil(bool isDepth, Latte::E_GX2SURFFMT format)
+{
+ if (!isDepth)
+ return false;
+ return format == Latte::E_GX2SURFFMT::D24_S8_UNORM ||
+ format == Latte::E_GX2SURFFMT::D24_S8_FLOAT ||
+ format == Latte::E_GX2SURFFMT::D32_S8_FLOAT;
+}
+
LatteTexture::LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
Latte::E_HWTILEMODE tileMode, bool isDepth)
{
@@ -1217,6 +1226,7 @@ LatteTexture::LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddre
this->mipLevels = mipLevels;
this->tileMode = tileMode;
this->isDepth = isDepth;
+ this->hasStencil = LatteTexture_GX2FormatHasStencil(isDepth, format);
this->physMipAddress = physMipAddress;
this->lastUpdateEventCounter = LatteTexture_getNextUpdateEventCounter();
this->lastWriteEventCounter = LatteTexture_getNextUpdateEventCounter();
diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.h b/src/Cafe/HW/Latte/Core/LatteTexture.h
index b46c1323..6c09e840 100644
--- a/src/Cafe/HW/Latte/Core/LatteTexture.h
+++ b/src/Cafe/HW/Latte/Core/LatteTexture.h
@@ -27,6 +27,8 @@ public:
LatteTexture(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth);
virtual ~LatteTexture();
+ virtual void AllocateOnHost() = 0;
+
LatteTextureView* GetOrCreateView(Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount)
{
for (auto& itr : views)
diff --git a/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp b/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp
index a71bd6a6..3145e90e 100644
--- a/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp
@@ -316,7 +316,7 @@ void LatteTexture_Delete(LatteTexture* texture)
delete[] texture->sliceMipInfo;
texture->sliceMipInfo = nullptr;
}
- g_renderer->texture_destroy(texture);
+ delete texture;
}
/*
diff --git a/src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp b/src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp
index 862fff06..c06a3bf1 100644
--- a/src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp
@@ -621,7 +621,7 @@ void LatteTextureLoader_UpdateTextureSliceData(LatteTexture* tex, uint32 sliceIn
if (tex->isDataDefined == false)
{
- g_renderer->texture_reserveTextureOnGPU(tex);
+ tex->AllocateOnHost();
tex->isDataDefined = true;
// if decoder is not set then clear texture
// on Vulkan this is used to make sure the texture is no longer in UNDEFINED layout
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp
index cd363612..58805925 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp
@@ -5,20 +5,6 @@
#include "config/LaunchSettings.h"
-GLuint texIdPool[64];
-sint32 texIdPoolIndex = 64;
-
-static GLuint _genTextureHandleGL()
-{
- if (texIdPoolIndex == 64)
- {
- glGenTextures(64, texIdPool);
- texIdPoolIndex = 0;
- }
- texIdPoolIndex++;
- return texIdPool[texIdPoolIndex - 1];
-}
-
LatteTextureGL::LatteTextureGL(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle,
Latte::E_HWTILEMODE tileMode, bool isDepth)
: LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth)
@@ -29,7 +15,6 @@ LatteTextureGL::LatteTextureGL(Latte::E_DIM dim, MPTR physAddress, MPTR physMipA
GetOpenGLFormatInfo(isDepth, overwriteInfo.hasFormatOverwrite ? (Latte::E_GX2SURFFMT)overwriteInfo.format : format, dim, &glFormatInfo);
this->glInternalFormat = glFormatInfo.glInternalFormat;
this->isAlternativeFormat = glFormatInfo.isUsingAlternativeFormat;
- this->hasStencil = glFormatInfo.hasStencil; // todo - should get this from the GX2 format?
// set debug name
bool useGLDebugNames = false;
#ifdef CEMU_DEBUG_ASSERT
@@ -88,34 +73,34 @@ void LatteTextureGL::GetOpenGLFormatInfo(bool isDepth, Latte::E_GX2SURFFMT forma
{
if (format == Latte::E_GX2SURFFMT::D24_S8_UNORM)
{
- formatInfoOut->setDepthFormat(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, true);
+ formatInfoOut->setFormat(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
return;
}
else if (format == Latte::E_GX2SURFFMT::D24_S8_FLOAT)
{
- formatInfoOut->setDepthFormat(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, true);
+ formatInfoOut->setFormat(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
formatInfoOut->markAsAlternativeFormat();
return;
}
else if (format == Latte::E_GX2SURFFMT::D32_S8_FLOAT)
{
- formatInfoOut->setDepthFormat(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, true);
+ formatInfoOut->setFormat(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
return;
}
else if (format == Latte::E_GX2SURFFMT::D32_FLOAT)
{
- formatInfoOut->setDepthFormat(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, false);
+ formatInfoOut->setFormat(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT);
return;
}
else if (format == Latte::E_GX2SURFFMT::D16_UNORM)
{
- formatInfoOut->setDepthFormat(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, false);
+ formatInfoOut->setFormat(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
return;
}
// unsupported depth format
cemuLog_log(LogType::Force, "OpenGL: Unsupported texture depth format 0x{:04x}", (uint32)format);
// use placeholder format
- formatInfoOut->setDepthFormat(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, false);
+ formatInfoOut->setFormat(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
formatInfoOut->markAsAlternativeFormat();
return;
}
@@ -496,3 +481,49 @@ void LatteTextureGL::GetOpenGLFormatInfo(bool isDepth, Latte::E_GX2SURFFMT forma
formatInfoOut->glIsCompressed = glIsCompressed;
formatInfoOut->isUsingAlternativeFormat = isUsingAlternativeFormat;
}
+
+void LatteTextureGL::AllocateOnHost()
+{
+ auto hostTexture = this;
+ cemu_assert_debug(hostTexture->isDataDefined == false);
+ sint32 effectiveBaseWidth = hostTexture->width;
+ sint32 effectiveBaseHeight = hostTexture->height;
+ sint32 effectiveBaseDepth = hostTexture->depth;
+ if (hostTexture->overwriteInfo.hasResolutionOverwrite)
+ {
+ effectiveBaseWidth = hostTexture->overwriteInfo.width;
+ effectiveBaseHeight = hostTexture->overwriteInfo.height;
+ effectiveBaseDepth = hostTexture->overwriteInfo.depth;
+ }
+ // calculate mip count
+ sint32 mipLevels = std::min(hostTexture->mipLevels, hostTexture->maxPossibleMipLevels);
+ mipLevels = std::max(mipLevels, 1);
+ // create immutable storage
+ if (hostTexture->dim == Latte::E_DIM::DIM_2D || hostTexture->dim == Latte::E_DIM::DIM_2D_MSAA)
+ {
+ cemu_assert_debug(effectiveBaseDepth == 1);
+ glTextureStorage2DWrapper(GL_TEXTURE_2D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight);
+ }
+ else if (hostTexture->dim == Latte::E_DIM::DIM_1D)
+ {
+ cemu_assert_debug(effectiveBaseHeight == 1);
+ cemu_assert_debug(effectiveBaseDepth == 1);
+ glTextureStorage1DWrapper(GL_TEXTURE_1D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth);
+ }
+ else if (hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY || hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY_MSAA)
+ {
+ glTextureStorage3DWrapper(GL_TEXTURE_2D_ARRAY, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
+ }
+ else if (hostTexture->dim == Latte::E_DIM::DIM_3D)
+ {
+ glTextureStorage3DWrapper(GL_TEXTURE_3D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
+ }
+ else if (hostTexture->dim == Latte::E_DIM::DIM_CUBEMAP)
+ {
+ glTextureStorage3DWrapper(GL_TEXTURE_CUBE_MAP_ARRAY, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, effectiveBaseDepth);
+ }
+ else
+ {
+ cemu_assert_unimplemented();
+ }
+}
\ No newline at end of file
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.h b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.h
index 9169bb29..abfb0d43 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.h
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.h
@@ -11,6 +11,8 @@ public:
~LatteTextureGL();
+ void AllocateOnHost() override;
+
static void GenerateEmptyTextureFromGX2Dim(Latte::E_DIM dim, GLuint& texId, GLint& texTarget, bool createForTargetType);
protected:
@@ -23,7 +25,6 @@ public:
sint32 glSuppliedFormat;
sint32 glSuppliedFormatType;
bool glIsCompressed;
- bool hasStencil{};
bool isUsingAlternativeFormat{};
void setFormat(sint32 glInternalFormat, sint32 glSuppliedFormat, sint32 glSuppliedFormatType)
@@ -34,15 +35,6 @@ public:
this->glIsCompressed = false;
}
- void setDepthFormat(sint32 glInternalFormat, sint32 glSuppliedFormat, sint32 glSuppliedFormatType, bool hasStencil)
- {
- this->glInternalFormat = glInternalFormat;
- this->glSuppliedFormat = glSuppliedFormat;
- this->glSuppliedFormatType = glSuppliedFormatType;
- this->glIsCompressed = false;
- this->hasStencil = hasStencil;
- }
-
void setCompressed(sint32 glInternalFormat, sint32 glSuppliedFormat, sint32 glSuppliedFormatType)
{
setFormat(glInternalFormat, glSuppliedFormat, glSuppliedFormatType);
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
index 943e39a0..604744cf 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
@@ -1002,57 +1002,6 @@ TextureDecoder* OpenGLRenderer::texture_chooseDecodedFormat(Latte::E_GX2SURFFMT
return texDecoder;
}
-void OpenGLRenderer::texture_destroy(LatteTexture* hostTexture)
-{
- delete hostTexture;
-}
-
-void OpenGLRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTextureGeneric)
-{
- auto hostTexture = (LatteTextureGL*)hostTextureGeneric;
- cemu_assert_debug(hostTexture->isDataDefined == false);
- sint32 effectiveBaseWidth = hostTexture->width;
- sint32 effectiveBaseHeight = hostTexture->height;
- sint32 effectiveBaseDepth = hostTexture->depth;
- if (hostTexture->overwriteInfo.hasResolutionOverwrite)
- {
- effectiveBaseWidth = hostTexture->overwriteInfo.width;
- effectiveBaseHeight = hostTexture->overwriteInfo.height;
- effectiveBaseDepth = hostTexture->overwriteInfo.depth;
- }
- // calculate mip count
- sint32 mipLevels = std::min(hostTexture->mipLevels, hostTexture->maxPossibleMipLevels);
- mipLevels = std::max(mipLevels, 1);
- // create immutable storage
- if (hostTexture->dim == Latte::E_DIM::DIM_2D || hostTexture->dim == Latte::E_DIM::DIM_2D_MSAA)
- {
- cemu_assert_debug(effectiveBaseDepth == 1);
- glTextureStorage2DWrapper(GL_TEXTURE_2D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight);
- }
- else if (hostTexture->dim == Latte::E_DIM::DIM_1D)
- {
- cemu_assert_debug(effectiveBaseHeight == 1);
- cemu_assert_debug(effectiveBaseDepth == 1);
- glTextureStorage1DWrapper(GL_TEXTURE_1D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth);
- }
- else if (hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY || hostTexture->dim == Latte::E_DIM::DIM_2D_ARRAY_MSAA)
- {
- glTextureStorage3DWrapper(GL_TEXTURE_2D_ARRAY, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
- }
- else if (hostTexture->dim == Latte::E_DIM::DIM_3D)
- {
- glTextureStorage3DWrapper(GL_TEXTURE_3D, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, std::max(1, effectiveBaseDepth));
- }
- else if (hostTexture->dim == Latte::E_DIM::DIM_CUBEMAP)
- {
- glTextureStorage3DWrapper(GL_TEXTURE_CUBE_MAP_ARRAY, hostTexture->glId_texture, mipLevels, hostTexture->glInternalFormat, effectiveBaseWidth, effectiveBaseHeight, effectiveBaseDepth);
- }
- else
- {
- cemu_assert_unimplemented();
- }
-}
-
// use standard API to upload texture data
void OpenGLRenderer_texture_loadSlice_normal(LatteTexture* hostTextureGeneric, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 imageSize)
{
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
index 026264cf..3a892191 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
@@ -66,14 +66,11 @@ public:
void renderstate_updateTextureSettingsGL(LatteDecompilerShader* shaderContext, LatteTextureView* _hostTextureView, uint32 hostTextureUnit, const Latte::LATTE_SQ_TEX_RESOURCE_WORD4_N texUnitWord4, uint32 texUnitIndex, bool isDepthSampler);
// texture functions
- void texture_destroy(LatteTexture* hostTexture) override;
-
void* texture_acquireTextureUploadBuffer(uint32 size) override;
void texture_releaseTextureUploadBuffer(uint8* mem) override;
TextureDecoder* texture_chooseDecodedFormat(Latte::E_GX2SURFFMT format, bool isDepth, Latte::E_DIM dim, uint32 width, uint32 height) override;
- void texture_reserveTextureOnGPU(LatteTexture* hostTexture) override;
void texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex) override;
void texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize) override;
void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) override;
diff --git a/src/Cafe/HW/Latte/Renderer/Renderer.h b/src/Cafe/HW/Latte/Renderer/Renderer.h
index 93edaf8d..2a9a1d1b 100644
--- a/src/Cafe/HW/Latte/Renderer/Renderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Renderer.h
@@ -97,14 +97,11 @@ public:
virtual void rendertarget_bindFramebufferObject(LatteCachedFBO* cfbo) = 0;
// texture functions
- virtual void texture_destroy(LatteTexture* hostTexture) = 0;
-
virtual void* texture_acquireTextureUploadBuffer(uint32 size) = 0;
virtual void texture_releaseTextureUploadBuffer(uint8* mem) = 0;
virtual TextureDecoder* texture_chooseDecodedFormat(Latte::E_GX2SURFFMT format, bool isDepth, Latte::E_DIM dim, uint32 width, uint32 height) = 0;
- virtual void texture_reserveTextureOnGPU(LatteTexture* hostTexture) = 0;
virtual void texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex) = 0;
virtual void texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize) = 0;
virtual void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) = 0;
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.cpp
index 66f7ba95..8a999000 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.cpp
@@ -44,9 +44,9 @@ CachedFBOVk::~CachedFBOVk()
while (!m_usedByPipelines.empty())
delete m_usedByPipelines[0];
auto vkr = VulkanRenderer::GetInstance();
- vkr->releaseDestructibleObject(m_vkrObjFramebuffer);
+ vkr->ReleaseDestructibleObject(m_vkrObjFramebuffer);
m_vkrObjFramebuffer = nullptr;
- vkr->releaseDestructibleObject(m_vkrObjRenderPass);
+ vkr->ReleaseDestructibleObject(m_vkrObjRenderPass);
m_vkrObjRenderPass = nullptr;
}
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureViewVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureViewVk.cpp
index aae7e9d1..f0e2295e 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureViewVk.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureViewVk.cpp
@@ -79,14 +79,14 @@ LatteTextureViewVk::~LatteTextureViewVk()
delete list_descriptorSets[0];
if (m_smallCacheView0)
- VulkanRenderer::GetInstance()->releaseDestructibleObject(m_smallCacheView0);
+ VulkanRenderer::GetInstance()->ReleaseDestructibleObject(m_smallCacheView0);
if (m_smallCacheView1)
- VulkanRenderer::GetInstance()->releaseDestructibleObject(m_smallCacheView1);
+ VulkanRenderer::GetInstance()->ReleaseDestructibleObject(m_smallCacheView1);
if (m_fallbackCache)
{
for (auto& itr : *m_fallbackCache)
- VulkanRenderer::GetInstance()->releaseDestructibleObject(itr.second);
+ VulkanRenderer::GetInstance()->ReleaseDestructibleObject(itr.second);
delete m_fallbackCache;
m_fallbackCache = nullptr;
}
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp
index b5f62707..a62741e4 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.cpp
@@ -46,7 +46,7 @@ LatteTextureVk::LatteTextureVk(class VulkanRenderer* vkRenderer, Latte::E_DIM di
VulkanRenderer::FormatInfoVK texFormatInfo;
vkRenderer->GetTextureFormatInfoVK(format, isDepth, dim, effectiveBaseWidth, effectiveBaseHeight, &texFormatInfo);
- hasStencil = (texFormatInfo.vkImageAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
+ cemu_assert_debug(hasStencil == ((texFormatInfo.vkImageAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0));
imageInfo.format = texFormatInfo.vkImageFormat;
vkObjTex->m_imageAspect = texFormatInfo.vkImageAspect;
@@ -117,7 +117,7 @@ LatteTextureVk::~LatteTextureVk()
m_vkr->surfaceCopy_notifyTextureRelease(this);
- VulkanRenderer::GetInstance()->releaseDestructibleObject(vkObjTex);
+ VulkanRenderer::GetInstance()->ReleaseDestructibleObject(vkObjTex);
vkObjTex = nullptr;
}
@@ -130,12 +130,8 @@ LatteTextureView* LatteTextureVk::CreateView(Latte::E_DIM dim, Latte::E_GX2SURFF
return new LatteTextureViewVk(m_vkr->GetLogicalDevice(), this, dim, format, firstMip, mipCount, firstSlice, sliceCount);
}
-void LatteTextureVk::setAllocation(struct VkImageMemAllocation* memAllocation)
+void LatteTextureVk::AllocateOnHost()
{
- vkObjTex->m_allocation = memAllocation;
-}
-
-struct VkImageMemAllocation* LatteTextureVk::getAllocation() const
-{
- return vkObjTex->m_allocation;
+ auto allocationInfo = VulkanRenderer::GetInstance()->GetMemoryManager()->imageMemoryAllocate(GetImageObj()->m_image);
+ vkObjTex->m_allocation = allocationInfo;
}
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.h b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.h
index 714c4e17..612e2e70 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.h
@@ -14,14 +14,13 @@ public:
~LatteTextureVk();
+ void AllocateOnHost() override;
+
VKRObjectTexture* GetImageObj() const { return vkObjTex; };
VkFormat GetFormat() const { return vkObjTex->m_format; }
VkImageAspectFlags GetImageAspect() const { return vkObjTex->m_imageAspect; }
- void setAllocation(struct VkImageMemAllocation* memAllocation);
- struct VkImageMemAllocation* getAllocation() const;
-
VkImageLayout GetImageLayout(VkImageSubresource& subresource)
{
cemu_assert_debug(subresource.mipLevel < m_layoutsMips);
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
index 437ef51d..15ea6e89 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
@@ -207,7 +207,8 @@ RendererShaderVk::RendererShaderVk(ShaderType type, uint64 baseHash, uint64 auxH
RendererShaderVk::~RendererShaderVk()
{
- VulkanRenderer::GetInstance()->destroyShader(this);
+ while (!list_pipelineInfo.empty())
+ delete list_pipelineInfo[0];
}
void RendererShaderVk::Init()
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp
index 72a1be4c..fd5a5b78 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VKRPipelineInfo.cpp
@@ -84,7 +84,7 @@ PipelineInfo::~PipelineInfo()
// queue pipeline for destruction
if (m_vkrObjPipeline)
{
- VulkanRenderer::GetInstance()->releaseDestructibleObject(m_vkrObjPipeline);
+ VulkanRenderer::GetInstance()->ReleaseDestructibleObject(m_vkrObjPipeline);
m_vkrObjPipeline = nullptr;
}
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp
index 0ee9f023..2be9a2f4 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp
@@ -300,7 +300,7 @@ void VulkanPipelineStableCache::LoadPipelineFromCache(std::span fileData)
delete pipelineInfo;
delete lcr;
delete cachedPipeline;
- VulkanRenderer::GetInstance()->releaseDestructibleObject(renderPass);
+ VulkanRenderer::GetInstance()->ReleaseDestructibleObject(renderPass);
s_spinlockSharedInternal.unlock();
}
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index c7f8c043..d0305317 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -1803,44 +1803,6 @@ void VulkanRenderer::PreparePresentationFrame(bool mainWindow)
AcquireNextSwapchainImage(mainWindow);
}
-void VulkanRenderer::ProcessDestructionQueues(size_t commandBufferIndex)
-{
- auto& current_descriptor_cache = m_destructionQueues.m_cmd_descriptor_set_objects[commandBufferIndex];
- if (!current_descriptor_cache.empty())
- {
- assert_dbg();
- //for (const auto& descriptor : current_descriptor_cache)
- //{
- // vkFreeDescriptorSets(m_logicalDevice, m_descriptorPool, 1, &descriptor);
- // performanceMonitor.vk.numDescriptorSets.decrement();
- //}
-
- current_descriptor_cache.clear();
- }
-
- // destroy buffers
- for (auto& itr : m_destructionQueues.m_buffers[commandBufferIndex])
- vkDestroyBuffer(m_logicalDevice, itr, nullptr);
- m_destructionQueues.m_buffers[commandBufferIndex].clear();
-
- // destroy device memory objects
- for (auto& itr : m_destructionQueues.m_memory[commandBufferIndex])
- vkFreeMemory(m_logicalDevice, itr, nullptr);
- m_destructionQueues.m_memory[commandBufferIndex].clear();
-
- // destroy image views
- for (auto& itr : m_destructionQueues.m_cmd_image_views[commandBufferIndex])
- vkDestroyImageView(m_logicalDevice, itr, nullptr);
- m_destructionQueues.m_cmd_image_views[commandBufferIndex].clear();
-
- // destroy host textures
- for (auto itr : m_destructionQueues.m_host_textures[commandBufferIndex])
- delete itr;
- m_destructionQueues.m_host_textures[commandBufferIndex].clear();
-
- ProcessDestructionQueue2();
-}
-
void VulkanRenderer::InitFirstCommandBuffer()
{
cemu_assert_debug(m_state.currentCommandBuffer == nullptr);
@@ -1869,7 +1831,7 @@ void VulkanRenderer::ProcessFinishedCommandBuffers()
VkResult fenceStatus = vkGetFenceStatus(m_logicalDevice, m_cmd_buffer_fences[m_commandBufferSyncIndex]);
if (fenceStatus == VK_SUCCESS)
{
- ProcessDestructionQueues(m_commandBufferSyncIndex);
+ ProcessDestructionQueue();
m_commandBufferSyncIndex = (m_commandBufferSyncIndex + 1) % m_commandBuffers.size();
memoryManager->cleanupBuffers(m_countCommandBufferFinished);
m_countCommandBufferFinished++;
@@ -3035,48 +2997,7 @@ TextureDecoder* VulkanRenderer::texture_chooseDecodedFormat(Latte::E_GX2SURFFMT
return texFormatInfo.decoder;
}
-void VulkanRenderer::texture_reserveTextureOnGPU(LatteTexture* hostTexture)
-{
- LatteTextureVk* vkTexture = (LatteTextureVk*)hostTexture;
- auto allocationInfo = memoryManager->imageMemoryAllocate(vkTexture->GetImageObj()->m_image);
- vkTexture->setAllocation(allocationInfo);
-}
-
-void VulkanRenderer::texture_destroy(LatteTexture* hostTexture)
-{
- LatteTextureVk* texVk = (LatteTextureVk*)hostTexture;
- delete texVk;
-}
-
-void VulkanRenderer::destroyViewDepr(VkImageView imageView)
-{
- cemu_assert_debug(false);
-
- m_destructionQueues.m_cmd_image_views[m_commandBufferIndex].emplace_back(imageView);
-}
-
-void VulkanRenderer::destroyBuffer(VkBuffer buffer)
-{
- m_destructionQueues.m_buffers[m_commandBufferIndex].emplace_back(buffer);
-}
-
-void VulkanRenderer::destroyDeviceMemory(VkDeviceMemory mem)
-{
- m_destructionQueues.m_memory[m_commandBufferIndex].emplace_back(mem);
-}
-
-void VulkanRenderer::destroyPipelineInfo(PipelineInfo* pipelineInfo)
-{
- cemu_assert_debug(false);
-}
-
-void VulkanRenderer::destroyShader(RendererShaderVk* shader)
-{
- while (!shader->list_pipelineInfo.empty())
- delete shader->list_pipelineInfo[0];
-}
-
-void VulkanRenderer::releaseDestructibleObject(VKRDestructibleObject* destructibleObject)
+void VulkanRenderer::ReleaseDestructibleObject(VKRDestructibleObject* destructibleObject)
{
// destroy immediately if possible
if (destructibleObject->canDestroy())
@@ -3090,7 +3011,7 @@ void VulkanRenderer::releaseDestructibleObject(VKRDestructibleObject* destructib
m_spinlockDestructionQueue.unlock();
}
-void VulkanRenderer::ProcessDestructionQueue2()
+void VulkanRenderer::ProcessDestructionQueue()
{
m_spinlockDestructionQueue.lock();
for (auto it = m_destructionQueue.begin(); it != m_destructionQueue.end();)
@@ -3139,7 +3060,7 @@ VkDescriptorSetInfo::~VkDescriptorSetInfo()
performanceMonitor.vk.numDescriptorDynUniformBuffers.decrement(statsNumDynUniformBuffers);
performanceMonitor.vk.numDescriptorStorageBuffers.decrement(statsNumStorageBuffers);
- VulkanRenderer::GetInstance()->releaseDestructibleObject(m_vkObjDescriptorSet);
+ VulkanRenderer::GetInstance()->ReleaseDestructibleObject(m_vkObjDescriptorSet);
m_vkObjDescriptorSet = nullptr;
}
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
index 226edad6..e0a4c75b 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
@@ -231,7 +231,6 @@ public:
void DrawEmptyFrame(bool mainWindow) override;
void PreparePresentationFrame(bool mainWindow);
- void ProcessDestructionQueues(size_t commandBufferIndex);
void InitFirstCommandBuffer();
void ProcessFinishedCommandBuffers();
void WaitForNextFinishedCommandBuffer();
@@ -244,15 +243,9 @@ public:
bool HasCommandBufferFinished(uint64 commandBufferId) const;
void WaitCommandBufferFinished(uint64 commandBufferId);
- // clean up (deprecated)
- void destroyViewDepr(VkImageView imageView);
- void destroyBuffer(VkBuffer buffer);
- void destroyDeviceMemory(VkDeviceMemory mem);
- void destroyPipelineInfo(PipelineInfo* pipelineInfo);
- void destroyShader(RendererShaderVk* shader);
- // clean up (new)
- void releaseDestructibleObject(VKRDestructibleObject* destructibleObject);
- void ProcessDestructionQueue2();
+ // resource destruction queue
+ void ReleaseDestructibleObject(VKRDestructibleObject* destructibleObject);
+ void ProcessDestructionQueue();
FSpinlock m_spinlockDestructionQueue;
std::vector m_destructionQueue;
@@ -290,9 +283,6 @@ public:
TextureDecoder* texture_chooseDecodedFormat(Latte::E_GX2SURFFMT format, bool isDepth, Latte::E_DIM dim, uint32 width, uint32 height) override;
- void texture_reserveTextureOnGPU(LatteTexture* hostTexture) override;
- void texture_destroy(LatteTexture* hostTexture) override;
-
void texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex) override;
void texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) override;
void texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sliceIndex, sint32 mipIndex, bool clearDepth, bool clearStencil, float depthValue, uint32 stencilValue) override;
@@ -634,15 +624,6 @@ private:
// command buffer, garbage collection, synchronization
static constexpr uint32 kCommandBufferPoolSize = 128;
- struct
- {
- std::array, kCommandBufferPoolSize> m_cmd_descriptor_set_objects;
- std::array, kCommandBufferPoolSize> m_cmd_image_views;
- std::array, kCommandBufferPoolSize> m_host_textures;
- std::array, kCommandBufferPoolSize> m_buffers;
- std::array, kCommandBufferPoolSize> m_memory;
- }m_destructionQueues;
-
size_t m_commandBufferIndex = 0; // current buffer being filled
size_t m_commandBufferSyncIndex = 0; // latest buffer that finished execution (updated on submit)
std::array m_cmd_buffer_fences;
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp
index 479b7e60..bf33ed90 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanSurfaceCopy.cpp
@@ -813,9 +813,9 @@ void VulkanRenderer::surfaceCopy_notifyTextureRelease(LatteTextureVk* hostTextur
{
if (p)
{
- VulkanRenderer::GetInstance()->releaseDestructibleObject(p->vkObjDescriptorSet);
+ VulkanRenderer::GetInstance()->ReleaseDestructibleObject(p->vkObjDescriptorSet);
p->vkObjDescriptorSet = nullptr;
- VulkanRenderer::GetInstance()->releaseDestructibleObject(p->vkObjImageView);
+ VulkanRenderer::GetInstance()->ReleaseDestructibleObject(p->vkObjImageView);
p->vkObjImageView = nullptr;
}
}
@@ -829,9 +829,9 @@ void VulkanRenderer::surfaceCopy_notifyTextureRelease(LatteTextureVk* hostTextur
{
if (p)
{
- VulkanRenderer::GetInstance()->releaseDestructibleObject(p->vkObjFramebuffer);
+ VulkanRenderer::GetInstance()->ReleaseDestructibleObject(p->vkObjFramebuffer);
p->vkObjFramebuffer = nullptr;
- VulkanRenderer::GetInstance()->releaseDestructibleObject(p->vkObjImageView);
+ VulkanRenderer::GetInstance()->ReleaseDestructibleObject(p->vkObjImageView);
p->vkObjImageView = nullptr;
}
}
diff --git a/src/imgui/imgui_impl_vulkan.cpp b/src/imgui/imgui_impl_vulkan.cpp
index f0006b45..723f153c 100644
--- a/src/imgui/imgui_impl_vulkan.cpp
+++ b/src/imgui/imgui_impl_vulkan.cpp
@@ -245,18 +245,13 @@ static void check_vk_result(VkResult err)
static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage)
{
- VulkanRenderer* vkRenderer = VulkanRenderer::GetInstance();
-
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
+ ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
+ vkDeviceWaitIdle(v->Device); // make sure previously created buffer is not in use anymore
VkResult err;
if (buffer != VK_NULL_HANDLE)
- {
- vkRenderer->destroyBuffer(buffer);
- }
+ vkDestroyBuffer(v->Device, buffer, v->Allocator);
if (buffer_memory != VK_NULL_HANDLE)
- {
- vkRenderer->destroyDeviceMemory(buffer_memory);
- }
+ vkFreeMemory(v->Device, buffer_memory, v->Allocator);
VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / g_BufferMemoryAlignment + 1) * g_BufferMemoryAlignment;
VkBufferCreateInfo buffer_info = {};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
From 731713de3ac97e6cee2504fd6ce3e7ca943fc282 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Thu, 14 Mar 2024 03:10:10 +0100
Subject: [PATCH 062/319] OpenGL: Remove "-legacy" flag
"Intel legacy mode" was a special mode to workaround various Intel OpenGL driver limitations during the earlier years of Cemu. It's been unmaintained for years and no longer serves a purpose.
If we ever bring back compatibility with ancient Intel GPUs it should be done in a more structured way than a blunt yes/no flag.
---
src/Cafe/GraphicPack/GraphicPack2.cpp | 3 -
src/Cafe/HW/Latte/Core/LatteConst.h | 2 -
src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp | 21 +++----
src/Cafe/HW/Latte/Core/LatteThread.cpp | 8 +--
.../Latte/Renderer/OpenGL/LatteTextureGL.cpp | 62 +++++--------------
.../Latte/Renderer/OpenGL/OpenGLRenderer.cpp | 44 +------------
.../Renderer/OpenGL/OpenGLRendererCore.cpp | 2 +-
src/Cafe/HW/Latte/Renderer/Renderer.h | 2 -
src/config/LaunchSettings.cpp | 2 -
src/config/LaunchSettings.h | 2 -
src/gui/guiWrapper.cpp | 4 --
11 files changed, 26 insertions(+), 126 deletions(-)
diff --git a/src/Cafe/GraphicPack/GraphicPack2.cpp b/src/Cafe/GraphicPack/GraphicPack2.cpp
index 365e6e3e..b581316e 100644
--- a/src/Cafe/GraphicPack/GraphicPack2.cpp
+++ b/src/Cafe/GraphicPack/GraphicPack2.cpp
@@ -878,9 +878,6 @@ bool GraphicPack2::Activate()
if (m_gfx_vendor.has_value())
{
auto vendor = g_renderer->GetVendor();
- if (vendor == GfxVendor::IntelLegacy || vendor == GfxVendor::IntelNoLegacy)
- vendor = GfxVendor::Intel;
-
if (m_gfx_vendor.value() != vendor)
return false;
}
diff --git a/src/Cafe/HW/Latte/Core/LatteConst.h b/src/Cafe/HW/Latte/Core/LatteConst.h
index 04c7b888..ebe741e9 100644
--- a/src/Cafe/HW/Latte/Core/LatteConst.h
+++ b/src/Cafe/HW/Latte/Core/LatteConst.h
@@ -82,8 +82,6 @@
#define GLVENDOR_UNKNOWN (0)
#define GLVENDOR_AMD (1) // AMD/ATI
#define GLVENDOR_NVIDIA (2)
-#define GLVENDOR_INTEL_LEGACY (3)
-#define GLVENDOR_INTEL_NOLEGACY (4)
#define GLVENDOR_INTEL (5)
#define GLVENDOR_APPLE (6)
diff --git a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
index b9ccbac4..50aa4d87 100644
--- a/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTextureLegacy.cpp
@@ -229,21 +229,16 @@ void LatteTexture_updateTexturesForStage(LatteDecompilerShader* shaderContext, u
// if this texture is bound multiple times then use alternative views
if (textureView->lastTextureBindIndex == LatteGPUState.textureBindCounter)
{
- // Intel driver has issues with textures that have multiple views bound and used by a shader, causes a softlock in BotW
- // therefore we disable this on Intel
- if (LatteGPUState.glVendor != GLVENDOR_INTEL_NOLEGACY)
+ LatteTextureViewGL* textureViewGL = (LatteTextureViewGL*)textureView;
+ // get next unused alternative texture view
+ while (true)
{
- LatteTextureViewGL* textureViewGL = (LatteTextureViewGL*)textureView;
- // get next unused alternative texture view
- while (true)
- {
- textureViewGL = textureViewGL->GetAlternativeView();
- if (textureViewGL->lastTextureBindIndex != LatteGPUState.textureBindCounter)
- break;
- }
- textureView = textureViewGL;
+ textureViewGL = textureViewGL->GetAlternativeView();
+ if (textureViewGL->lastTextureBindIndex != LatteGPUState.textureBindCounter)
+ break;
}
- }
+ textureView = textureViewGL;
+ }
textureView->lastTextureBindIndex = LatteGPUState.textureBindCounter;
rendererGL->renderstate_updateTextureSettingsGL(shaderContext, textureView, textureIndex + glBackendBaseTexUnit, word4, textureIndex, isDepthSampler);
}
diff --git a/src/Cafe/HW/Latte/Core/LatteThread.cpp b/src/Cafe/HW/Latte/Core/LatteThread.cpp
index 60b32ec4..bd312d93 100644
--- a/src/Cafe/HW/Latte/Core/LatteThread.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteThread.cpp
@@ -140,13 +140,7 @@ int Latte_ThreadEntry()
case GfxVendor::AMD:
LatteGPUState.glVendor = GLVENDOR_AMD;
break;
- case GfxVendor::IntelLegacy:
- LatteGPUState.glVendor = GLVENDOR_INTEL_LEGACY;
- break;
- case GfxVendor::IntelNoLegacy:
- LatteGPUState.glVendor = GLVENDOR_INTEL_NOLEGACY;
- break;
- case GfxVendor::Intel:
+ case GfxVendor::Intel:
LatteGPUState.glVendor = GLVENDOR_INTEL;
break;
case GfxVendor::Nvidia:
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp
index 58805925..fb025eba 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/LatteTextureGL.cpp
@@ -110,10 +110,6 @@ void LatteTextureGL::GetOpenGLFormatInfo(bool isDepth, Latte::E_GX2SURFFMT forma
sint32 glInternalFormat;
sint32 glSuppliedFormat;
sint32 glSuppliedFormatType;
- // check if compressed textures should be used
- bool allowCompressedGLFormat = true;
- if (LatteGPUState.glVendor == GLVENDOR_INTEL_LEGACY)
- allowCompressedGLFormat = false; // compressed formats seem to cause more harm than good on Intel
// get format information
if (format == Latte::E_GX2SURFFMT::R4_G4_UNORM)
{
@@ -149,20 +145,11 @@ void LatteTextureGL::GetOpenGLFormatInfo(bool isDepth, Latte::E_GX2SURFFMT forma
else if (format == Latte::E_GX2SURFFMT::BC1_UNORM ||
format == Latte::E_GX2SURFFMT::BC1_SRGB)
{
- if (allowCompressedGLFormat)
- {
- if (format == Latte::E_GX2SURFFMT::BC1_SRGB)
- formatInfoOut->setCompressed(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, -1, -1);
- else
- formatInfoOut->setCompressed(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, -1, -1);
- return;
- }
+ if (format == Latte::E_GX2SURFFMT::BC1_SRGB)
+ formatInfoOut->setCompressed(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, -1, -1);
else
- {
- formatInfoOut->setFormat(GL_RGBA16F, GL_RGBA, GL_FLOAT);
- formatInfoOut->markAsAlternativeFormat();
- return;
- }
+ formatInfoOut->setCompressed(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, -1, -1);
+ return;
}
else if (format == Latte::E_GX2SURFFMT::BC2_UNORM || format == Latte::E_GX2SURFFMT::BC2_SRGB)
{
@@ -173,28 +160,18 @@ void LatteTextureGL::GetOpenGLFormatInfo(bool isDepth, Latte::E_GX2SURFFMT forma
}
else if (format == Latte::E_GX2SURFFMT::BC3_UNORM || format == Latte::E_GX2SURFFMT::BC3_SRGB)
{
- if (allowCompressedGLFormat)
- {
- if (format == Latte::E_GX2SURFFMT::BC3_SRGB)
- formatInfoOut->setCompressed(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, -1, -1);
- else
- formatInfoOut->setCompressed(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, -1, -1);
- return;
- }
+ if (format == Latte::E_GX2SURFFMT::BC3_SRGB)
+ formatInfoOut->setCompressed(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, -1, -1);
else
- {
- // todo: SRGB support
- formatInfoOut->setFormat(GL_RGBA16F, GL_RGBA, GL_FLOAT);
- formatInfoOut->markAsAlternativeFormat();
- return;
- }
+ formatInfoOut->setCompressed(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, -1, -1);
+ return;
}
else if (format == Latte::E_GX2SURFFMT::BC4_UNORM || format == Latte::E_GX2SURFFMT::BC4_SNORM)
{
+ bool allowCompressed = true;
if (dim != Latte::E_DIM::DIM_2D && dim != Latte::E_DIM::DIM_2D_ARRAY)
- allowCompressedGLFormat = false; // RGTC1 does not support non-2D textures
-
- if (allowCompressedGLFormat)
+ allowCompressed = false; // RGTC1 does not support non-2D textures
+ if (allowCompressed)
{
if (format == Latte::E_GX2SURFFMT::BC4_UNORM)
formatInfoOut->setCompressed(GL_COMPRESSED_RED_RGTC1, -1, -1);
@@ -211,20 +188,11 @@ void LatteTextureGL::GetOpenGLFormatInfo(bool isDepth, Latte::E_GX2SURFFMT forma
}
else if (format == Latte::E_GX2SURFFMT::BC5_UNORM || format == Latte::E_GX2SURFFMT::BC5_SNORM)
{
- if (allowCompressedGLFormat)
- {
- if (format == Latte::E_GX2SURFFMT::BC5_SNORM)
- formatInfoOut->setCompressed(GL_COMPRESSED_SIGNED_RG_RGTC2, -1, -1);
- else
- formatInfoOut->setCompressed(GL_COMPRESSED_RG_RGTC2, -1, -1);
- return;
- }
+ if (format == Latte::E_GX2SURFFMT::BC5_SNORM)
+ formatInfoOut->setCompressed(GL_COMPRESSED_SIGNED_RG_RGTC2, -1, -1);
else
- {
- formatInfoOut->setFormat(GL_RG16F, GL_RG, GL_FLOAT);
- formatInfoOut->markAsAlternativeFormat();
- return;
- }
+ formatInfoOut->setCompressed(GL_COMPRESSED_RG_RGTC2, -1, -1);
+ return;
}
else if (format == Latte::E_GX2SURFFMT::R32_FLOAT)
{
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
index 604744cf..28e91b8a 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp
@@ -407,10 +407,7 @@ void OpenGLRenderer::GetVendorInformation()
}
else if (memcmp(glVendorString, "Intel", 5) == 0)
{
- if (LaunchSettings::ForceIntelLegacyEnabled())
- m_vendor = GfxVendor::IntelLegacy;
- else
- m_vendor = GfxVendor::IntelNoLegacy;
+ m_vendor = GfxVendor::Intel;
return;
}
}
@@ -849,45 +846,6 @@ TextureDecoder* OpenGLRenderer::texture_chooseDecodedFormat(Latte::E_GX2SURFFMT
}
return nullptr;
}
-
- if (LatteGPUState.glVendor == GLVENDOR_INTEL_LEGACY)
- {
- if (format == Latte::E_GX2SURFFMT::BC1_UNORM)
- {
- texDecoder = TextureDecoder_BC1_UNORM_uncompress::getInstance();
- }
- else if (format == Latte::E_GX2SURFFMT::BC1_SRGB)
- {
- texDecoder = TextureDecoder_BC1_SRGB_uncompress::getInstance();
- }
- else if (format == Latte::E_GX2SURFFMT::BC3_UNORM)
- {
- texDecoder = TextureDecoder_BC3_UNORM_uncompress::getInstance();
- }
- else if (format == Latte::E_GX2SURFFMT::BC3_SRGB)
- {
- texDecoder = TextureDecoder_BC3_SRGB_uncompress::getInstance();
- }
- else if (format == Latte::E_GX2SURFFMT::BC4_UNORM)
- {
- texDecoder = TextureDecoder_BC4_UNORM_uncompress::getInstance();
- }
- else if (format == Latte::E_GX2SURFFMT::BC4_SNORM)
- {
- cemu_assert_debug(false); // todo
- }
- else if (format == Latte::E_GX2SURFFMT::BC5_UNORM)
- {
- texDecoder = TextureDecoder_BC5_UNORM_uncompress::getInstance();
- }
- else if (format == Latte::E_GX2SURFFMT::BC5_SNORM)
- {
- texDecoder = TextureDecoder_BC5_SNORM_uncompress::getInstance();
- }
- if (texDecoder)
- return texDecoder;
- }
-
if (format == Latte::E_GX2SURFFMT::R4_G4_UNORM)
texDecoder = TextureDecoder_R4_G4_UNORM_To_RGBA4::getInstance();
else if (format == Latte::E_GX2SURFFMT::R4_G4_B4_A4_UNORM)
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp
index 51d0d206..571961f4 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp
@@ -950,7 +950,7 @@ void OpenGLRenderer::draw_genericDrawHandler(uint32 baseVertex, uint32 baseInsta
bool streamoutEnable = LatteGPUState.contextRegister[mmVGT_STRMOUT_EN] != 0;
if (streamoutEnable)
{
- if (glBeginTransformFeedback == nullptr || LatteGPUState.glVendor == GLVENDOR_INTEL_NOLEGACY)
+ if (glBeginTransformFeedback == nullptr)
{
cemu_assert_debug(false);
return; // transform feedback not supported
diff --git a/src/Cafe/HW/Latte/Renderer/Renderer.h b/src/Cafe/HW/Latte/Renderer/Renderer.h
index 2a9a1d1b..0b694bb9 100644
--- a/src/Cafe/HW/Latte/Renderer/Renderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Renderer.h
@@ -21,8 +21,6 @@ enum class GfxVendor
Generic,
AMD,
- IntelLegacy,
- IntelNoLegacy,
Intel,
Nvidia,
Apple,
diff --git a/src/config/LaunchSettings.cpp b/src/config/LaunchSettings.cpp
index fdd4cc65..b7a79a11 100644
--- a/src/config/LaunchSettings.cpp
+++ b/src/config/LaunchSettings.cpp
@@ -174,8 +174,6 @@ bool LaunchSettings::HandleCommandline(const std::vector& args)
if (vm.count("nsight"))
s_nsight_mode = vm["nsight"].as();
- if (vm.count("legacy"))
- s_force_intel_legacy = vm["legacy"].as();
if(vm.count("force-interpreter"))
s_force_interpreter = vm["force-interpreter"].as();
diff --git a/src/config/LaunchSettings.h b/src/config/LaunchSettings.h
index f87dc609..be989e6a 100644
--- a/src/config/LaunchSettings.h
+++ b/src/config/LaunchSettings.h
@@ -24,7 +24,6 @@ public:
static bool GDBStubEnabled() { return s_enable_gdbstub; }
static bool NSightModeEnabled() { return s_nsight_mode; }
- static bool ForceIntelLegacyEnabled() { return s_force_intel_legacy; }
static bool ForceInterpreter() { return s_force_interpreter; };
@@ -44,7 +43,6 @@ private:
inline static bool s_enable_gdbstub = false;
inline static bool s_nsight_mode = false;
- inline static bool s_force_intel_legacy = false;
inline static bool s_force_interpreter = false;
diff --git a/src/gui/guiWrapper.cpp b/src/gui/guiWrapper.cpp
index 68f97590..ce043bab 100644
--- a/src/gui/guiWrapper.cpp
+++ b/src/gui/guiWrapper.cpp
@@ -93,10 +93,6 @@ void gui_updateWindowTitles(bool isIdle, bool isLoading, double fps)
const char* graphicMode = "[Generic]";
if (LatteGPUState.glVendor == GLVENDOR_AMD)
graphicMode = "[AMD GPU]";
- else if (LatteGPUState.glVendor == GLVENDOR_INTEL_LEGACY)
- graphicMode = "[Intel GPU - Legacy]";
- else if (LatteGPUState.glVendor == GLVENDOR_INTEL_NOLEGACY)
- graphicMode = "[Intel GPU]";
else if (LatteGPUState.glVendor == GLVENDOR_INTEL)
graphicMode = "[Intel GPU]";
else if (LatteGPUState.glVendor == GLVENDOR_NVIDIA)
From eaa82817dd235b5067002df76b06e66a550ac1d3 Mon Sep 17 00:00:00 2001
From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com>
Date: Fri, 15 Mar 2024 23:06:48 +0100
Subject: [PATCH 063/319] Update thread names (#1120)
---
src/Cafe/HW/Espresso/Debugger/GDBStub.cpp | 2 +-
src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp | 2 +-
src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp | 2 ++
.../HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp | 2 ++
src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp | 1 +
src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp | 1 +
src/Cafe/IOSU/ODM/iosu_odm.cpp | 2 ++
src/Cafe/IOSU/PDM/iosu_pdm.cpp | 2 ++
src/Cafe/IOSU/nn/iosu_nn_service.cpp | 1 +
src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp | 2 +-
src/Cafe/TitleList/SaveList.cpp | 2 ++
src/Cafe/TitleList/TitleList.cpp | 1 +
src/Cemu/FileCache/FileCache.cpp | 2 +-
src/gui/components/wxGameList.cpp | 1 +
src/gui/guiWrapper.cpp | 2 +-
src/input/InputManager.cpp | 2 +-
src/input/api/DSU/DSUControllerProvider.cpp | 4 ++--
src/input/api/SDL/SDLControllerProvider.cpp | 2 +-
src/input/api/Wiimote/WiimoteControllerProvider.cpp | 4 ++--
src/util/helpers/helpers.cpp | 4 +++-
20 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp b/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp
index 6cddae01..e54fae1b 100644
--- a/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp
+++ b/src/Cafe/HW/Espresso/Debugger/GDBStub.cpp
@@ -297,7 +297,7 @@ bool GDBServer::Initialize()
void GDBServer::ThreadFunc()
{
- SetThreadName("GDBServer::ThreadFunc");
+ SetThreadName("GDBServer");
while (!m_stopRequested)
{
diff --git a/src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp b/src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp
index f4d063fa..24e87bd1 100644
--- a/src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp
+++ b/src/Cafe/HW/Espresso/Recompiler/PPCRecompiler.cpp
@@ -294,7 +294,7 @@ std::atomic_bool s_recompilerThreadStopSignal{false};
void PPCRecompiler_thread()
{
- SetThreadName("PPCRecompiler_thread");
+ SetThreadName("PPCRecompiler");
while (true)
{
if(s_recompilerThreadStopSignal)
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
index 15ea6e89..50f2c2d6 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
@@ -8,6 +8,7 @@
#include
#include
+#include
bool s_isLoadingShadersVk{ false };
class FileCache* s_spirvCache{nullptr};
@@ -155,6 +156,7 @@ public:
void CompilerThreadFunc()
{
+ SetThreadName("vkShaderComp");
while (m_threadsActive.load(std::memory_order::relaxed))
{
s_compilationQueueCount.decrementWithWait();
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp
index 2be9a2f4..123120d3 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanPipelineStableCache.cpp
@@ -408,6 +408,7 @@ bool VulkanPipelineStableCache::DeserializePipeline(MemStreamReader& memReader,
int VulkanPipelineStableCache::CompilerThread()
{
+ SetThreadName("plCacheCompiler");
while (m_numCompilationThreads != 0)
{
std::vector pipelineData = m_compilationQueue.pop();
@@ -421,6 +422,7 @@ int VulkanPipelineStableCache::CompilerThread()
void VulkanPipelineStableCache::WorkerThread()
{
+ SetThreadName("plCacheWriter");
while (true)
{
CachedPipeline* job;
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index d0305317..d62b61a6 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -1986,6 +1986,7 @@ void VulkanRenderer::WaitCommandBufferFinished(uint64 commandBufferId)
void VulkanRenderer::PipelineCacheSaveThread(size_t cache_size)
{
+ SetThreadName("vkDriverPlCache");
const auto dir = ActiveSettings::GetCachePath("shaderCache/driver/vk");
if (!fs::exists(dir))
{
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp
index 320357f1..d510140b 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp
@@ -190,6 +190,7 @@ std::queue g_compilePipelineRequests;
void compilePipeline_thread(sint32 threadIndex)
{
+ SetThreadName("compilePl");
#ifdef _WIN32
// one thread runs at normal priority while the others run at lower priority
if(threadIndex != 0)
diff --git a/src/Cafe/IOSU/ODM/iosu_odm.cpp b/src/Cafe/IOSU/ODM/iosu_odm.cpp
index 3dc8e431..aae3c503 100644
--- a/src/Cafe/IOSU/ODM/iosu_odm.cpp
+++ b/src/Cafe/IOSU/ODM/iosu_odm.cpp
@@ -1,3 +1,4 @@
+#include
#include "iosu_odm.h"
#include "config/ActiveSettings.h"
#include "Common/FileStream.h"
@@ -79,6 +80,7 @@ namespace iosu
void ODMServiceThread()
{
+ SetThreadName("ODMService");
s_msgQueueId = IOS_CreateMessageQueue(_s_msgBuffer.GetPtr(), _s_msgBuffer.GetCount());
cemu_assert(!IOS_ResultIsError((IOS_ERROR)s_msgQueueId));
IOS_ERROR r = IOS_RegisterResourceManager(s_devicePath.c_str(), s_msgQueueId);
diff --git a/src/Cafe/IOSU/PDM/iosu_pdm.cpp b/src/Cafe/IOSU/PDM/iosu_pdm.cpp
index e54529a9..d94b1dbf 100644
--- a/src/Cafe/IOSU/PDM/iosu_pdm.cpp
+++ b/src/Cafe/IOSU/PDM/iosu_pdm.cpp
@@ -1,3 +1,4 @@
+#include
#include "iosu_pdm.h"
#include "Cafe/CafeSystem.h"
#include "config/ActiveSettings.h"
@@ -387,6 +388,7 @@ namespace iosu
void TimeTrackingThread(uint64 titleId)
{
+ SetThreadName("PlayDiaryThread");
PlayStatsEntry* playStatsEntry = PlayStats_BeginNewTracking(titleId);
auto startTime = std::chrono::steady_clock::now();
diff --git a/src/Cafe/IOSU/nn/iosu_nn_service.cpp b/src/Cafe/IOSU/nn/iosu_nn_service.cpp
index b3b2d4c9..1fb5c77a 100644
--- a/src/Cafe/IOSU/nn/iosu_nn_service.cpp
+++ b/src/Cafe/IOSU/nn/iosu_nn_service.cpp
@@ -155,6 +155,7 @@ namespace iosu
void IPCService::ServiceThread()
{
+ SetThreadName("IPCService");
m_msgQueueId = IOS_CreateMessageQueue(_m_msgBuffer.GetPtr(), _m_msgBuffer.GetCount());
cemu_assert(!IOS_ResultIsError((IOS_ERROR)m_msgQueueId));
IOS_ERROR r = IOS_RegisterResourceManager(m_devicePath.c_str(), m_msgQueueId);
diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp
index 3701a4d7..8ce5de07 100644
--- a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp
+++ b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp
@@ -1168,7 +1168,7 @@ namespace coreinit
void OSSchedulerCoreEmulationThread(void* _assignedCoreIndex)
{
- SetThreadName(fmt::format("OSSchedulerThread[core={}]", (uintptr_t)_assignedCoreIndex).c_str());
+ SetThreadName(fmt::format("OSSched[core={}]", (uintptr_t)_assignedCoreIndex).c_str());
t_assignedCoreIndex = (sint32)(uintptr_t)_assignedCoreIndex;
#if defined(ARCH_X86_64)
_mm_setcsr(_mm_getcsr() | 0x8000); // flush denormals to zero
diff --git a/src/Cafe/TitleList/SaveList.cpp b/src/Cafe/TitleList/SaveList.cpp
index a86e8498..d0c0e3e2 100644
--- a/src/Cafe/TitleList/SaveList.cpp
+++ b/src/Cafe/TitleList/SaveList.cpp
@@ -1,5 +1,6 @@
#include "SaveList.h"
#include
+#include
std::mutex sSLMutex;
fs::path sSLMLCPath;
@@ -44,6 +45,7 @@ void CafeSaveList::Refresh()
void CafeSaveList::RefreshThreadWorker()
{
+ SetThreadName("SaveListWorker");
// clear save list
for (auto& itSaveInfo : sSLList)
{
diff --git a/src/Cafe/TitleList/TitleList.cpp b/src/Cafe/TitleList/TitleList.cpp
index 1cc084b8..c288dd13 100644
--- a/src/Cafe/TitleList/TitleList.cpp
+++ b/src/Cafe/TitleList/TitleList.cpp
@@ -258,6 +258,7 @@ void CafeTitleList::AddTitleFromPath(fs::path path)
bool CafeTitleList::RefreshWorkerThread()
{
+ SetThreadName("TitleListWorker");
while (sTLRefreshRequests.load())
{
sTLRefreshRequests.store(0);
diff --git a/src/Cemu/FileCache/FileCache.cpp b/src/Cemu/FileCache/FileCache.cpp
index aa7770a3..b284b66b 100644
--- a/src/Cemu/FileCache/FileCache.cpp
+++ b/src/Cemu/FileCache/FileCache.cpp
@@ -50,7 +50,7 @@ struct _FileCacheAsyncWriter
private:
void FileCacheThread()
{
- SetThreadName("fileCache_thread");
+ SetThreadName("fileCache");
while (true)
{
std::unique_lock lock(m_fileCacheMutex);
diff --git a/src/gui/components/wxGameList.cpp b/src/gui/components/wxGameList.cpp
index 88934cd8..8e8f3c4d 100644
--- a/src/gui/components/wxGameList.cpp
+++ b/src/gui/components/wxGameList.cpp
@@ -1194,6 +1194,7 @@ void wxGameList::RemoveCache(const std::list& cachePaths, const std::s
void wxGameList::AsyncWorkerThread()
{
+ SetThreadName("GameListWorker");
while (m_async_worker_active)
{
m_async_task_count.decrementWithWait();
diff --git a/src/gui/guiWrapper.cpp b/src/gui/guiWrapper.cpp
index ce043bab..d887e89a 100644
--- a/src/gui/guiWrapper.cpp
+++ b/src/gui/guiWrapper.cpp
@@ -37,7 +37,7 @@ void _wxLaunch()
void gui_create()
{
- SetThreadName("MainThread");
+ SetThreadName("cemu");
#if BOOST_OS_WINDOWS
// on Windows wxWidgets there is a bug where wxDirDialog->ShowModal will deadlock in Windows internals somehow
// moving the UI thread off the main thread fixes this
diff --git a/src/input/InputManager.cpp b/src/input/InputManager.cpp
index 4e7848ce..d928e46c 100644
--- a/src/input/InputManager.cpp
+++ b/src/input/InputManager.cpp
@@ -934,7 +934,7 @@ std::optional InputManager::get_right_down_mouse_info(bool* is_pad)
void InputManager::update_thread()
{
- SetThreadName("InputManager::update_thread");
+ SetThreadName("Input_update");
while (!m_update_thread_shutdown.load(std::memory_order::relaxed))
{
std::shared_lock lock(m_mutex);
diff --git a/src/input/api/DSU/DSUControllerProvider.cpp b/src/input/api/DSU/DSUControllerProvider.cpp
index 0fa93e25..37f92774 100644
--- a/src/input/api/DSU/DSUControllerProvider.cpp
+++ b/src/input/api/DSU/DSUControllerProvider.cpp
@@ -250,7 +250,7 @@ MotionSample DSUControllerProvider::get_motion_sample(uint8_t index) const
void DSUControllerProvider::reader_thread()
{
- SetThreadName("DSUControllerProvider::reader_thread");
+ SetThreadName("DSU-reader");
bool first_read = true;
while (m_running.load(std::memory_order_relaxed))
{
@@ -383,7 +383,7 @@ void DSUControllerProvider::reader_thread()
void DSUControllerProvider::writer_thread()
{
- SetThreadName("DSUControllerProvider::writer_thread");
+ SetThreadName("DSU-writer");
while (m_running.load(std::memory_order_relaxed))
{
std::unique_lock lock(m_writer_mutex);
diff --git a/src/input/api/SDL/SDLControllerProvider.cpp b/src/input/api/SDL/SDLControllerProvider.cpp
index 9e0c09b5..9b21b306 100644
--- a/src/input/api/SDL/SDLControllerProvider.cpp
+++ b/src/input/api/SDL/SDLControllerProvider.cpp
@@ -124,7 +124,7 @@ MotionSample SDLControllerProvider::motion_sample(int diid)
void SDLControllerProvider::event_thread()
{
- SetThreadName("SDLControllerProvider::event_thread");
+ SetThreadName("SDL_events");
while (m_running.load(std::memory_order_relaxed))
{
SDL_Event event{};
diff --git a/src/input/api/Wiimote/WiimoteControllerProvider.cpp b/src/input/api/Wiimote/WiimoteControllerProvider.cpp
index 55f28c01..5aac3fe4 100644
--- a/src/input/api/Wiimote/WiimoteControllerProvider.cpp
+++ b/src/input/api/Wiimote/WiimoteControllerProvider.cpp
@@ -143,7 +143,7 @@ WiimoteControllerProvider::WiimoteState WiimoteControllerProvider::get_state(siz
void WiimoteControllerProvider::reader_thread()
{
- SetThreadName("WiimoteControllerProvider::reader_thread");
+ SetThreadName("Wiimote-reader");
std::chrono::steady_clock::time_point lastCheck = {};
while (m_running.load(std::memory_order_relaxed))
{
@@ -878,7 +878,7 @@ void WiimoteControllerProvider::set_motion_plus(size_t index, bool state)
void WiimoteControllerProvider::writer_thread()
{
- SetThreadName("WiimoteControllerProvider::writer_thread");
+ SetThreadName("Wiimote-writer");
while (m_running.load(std::memory_order_relaxed))
{
std::unique_lock writer_lock(m_writer_mutex);
diff --git a/src/util/helpers/helpers.cpp b/src/util/helpers/helpers.cpp
index b556db36..7e22e9fb 100644
--- a/src/util/helpers/helpers.cpp
+++ b/src/util/helpers/helpers.cpp
@@ -155,7 +155,9 @@ void SetThreadName(const char* name)
#elif BOOST_OS_MACOS
pthread_setname_np(name);
#else
- pthread_setname_np(pthread_self(), name);
+ if(std::strlen(name) > 15)
+ cemuLog_log(LogType::Force, "Truncating thread name {} because it was longer than 15 characters", name);
+ pthread_setname_np(pthread_self(), std::string{name}.substr(0,15).c_str());
#endif
}
From 42d14eec96c6e63ea93cfb7daa49655b7139c997 Mon Sep 17 00:00:00 2001
From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com>
Date: Mon, 18 Mar 2024 09:18:02 +0100
Subject: [PATCH 064/319] Minor code improvements (#1124)
---
.../LatteDecompilerEmitGLSL.cpp | 2 +-
.../HW/Latte/Renderer/OpenGL/OpenGLRenderer.h | 2 --
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 10 +++++-----
.../HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 3 +--
src/input/motion/MotionSample.h | 20 +++++++++----------
5 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp
index f3d2c7a8..e19535be 100644
--- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp
+++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitGLSL.cpp
@@ -973,7 +973,7 @@ void _emitOperandInputCode(LatteDecompilerShaderContext* shaderContext, LatteDec
}
else
{
- cemuLog_log(LogType::Force, "Unsupported shader ALU operand sel 0x%x\n", aluInstruction->sourceOperand[operandIndex].sel);
+ cemuLog_log(LogType::Force, "Unsupported shader ALU operand sel {:#x}\n", aluInstruction->sourceOperand[operandIndex].sel);
debugBreakpoint();
}
diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
index 3a892191..313ea3c0 100644
--- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.h
@@ -30,8 +30,6 @@ public:
void Flush(bool waitIdle = false) override;
void NotifyLatteCommandProcessorIdle() override;
- void UpdateVSyncState();
-
void EnableDebugMode() override;
void SwapBuffers(bool swapTV = true, bool swapDRC = true) override;
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index d62b61a6..02bb1e71 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -706,8 +706,8 @@ SwapchainInfoVk& VulkanRenderer::GetChainInfo(bool mainWindow) const
void VulkanRenderer::StopUsingPadAndWait()
{
- m_destroyPadSwapchainNextAcquire = true;
- m_padCloseReadySemaphore.wait();
+ m_destroyPadSwapchainNextAcquire.test_and_set();
+ m_destroyPadSwapchainNextAcquire.wait(true);
}
bool VulkanRenderer::IsPadWindowActive()
@@ -2557,11 +2557,11 @@ bool VulkanRenderer::AcquireNextSwapchainImage(bool mainWindow)
if(!IsSwapchainInfoValid(mainWindow))
return false;
- if(!mainWindow && m_destroyPadSwapchainNextAcquire)
+ if(!mainWindow && m_destroyPadSwapchainNextAcquire.test())
{
RecreateSwapchain(mainWindow, true);
- m_destroyPadSwapchainNextAcquire = false;
- m_padCloseReadySemaphore.notify();
+ m_destroyPadSwapchainNextAcquire.clear();
+ m_destroyPadSwapchainNextAcquire.notify_all();
return false;
}
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
index e0a4c75b..47097dfa 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
@@ -414,8 +414,7 @@ private:
}m_state;
std::unique_ptr m_mainSwapchainInfo{}, m_padSwapchainInfo{};
- Semaphore m_padCloseReadySemaphore;
- bool m_destroyPadSwapchainNextAcquire = false;
+ std::atomic_flag m_destroyPadSwapchainNextAcquire{};
bool IsSwapchainInfoValid(bool mainWindow) const;
VkRenderPass m_imguiRenderPass = VK_NULL_HANDLE;
diff --git a/src/input/motion/MotionSample.h b/src/input/motion/MotionSample.h
index bb47f784..0697711b 100644
--- a/src/input/motion/MotionSample.h
+++ b/src/input/motion/MotionSample.h
@@ -258,48 +258,48 @@ DRC flat on table, screen facing up. Top pointing away (away from person, pointi
0.03 0.99 -0.13
0.01 0.13 0.99
-Turned 45 to the right:
+Turned 45° to the right:
0.71 -0.03 0.71
0.12 0.99 -0.08
-0.70 0.14 0.70
-Turned 45 to the right (top of GamePad pointing right now):
+Turned 45° to the right (top of GamePad pointing right now):
0.08 -0.03 1.00 -> Z points towards person
0.15 0.99 0.01
-0.99 0.15 0.09 -> DRC Z-Axis now points towards X-minus
-Turned 90 to the right (top of gamepad now pointing towards holder, away from monitor):
+Turned 90° to the right (top of gamepad now pointing towards holder, away from monitor):
-1.00 -0.01 0.06
0.00 0.99 0.15
-0.06 0.15 -0.99
-Turned 90 to the right (pointing left):
+Turned 90° to the right (pointing left):
-0.17 -0.01 -0.99
-0.13 0.99 0.02
0.98 0.13 -0.17
-After another 90 we end up in the initial position:
+After another 90° we end up in the initial position:
0.99 -0.03 -0.11
0.01 0.99 -0.13
0.12 0.12 0.99
------
-From initial position, lean the GamePad on its left side. 45 up. So the screen is pointing to the top left
+From initial position, lean the GamePad on its left side. 45° up. So the screen is pointing to the top left
0.66 -0.75 -0.03
0.74 0.66 -0.11
0.10 0.05 0.99
-Further 45, GamePad now on its left, screen pointing left:
+Further 45°, GamePad now on its left, screen pointing left:
-0.03 -1.00 -0.00
0.99 -0.03 -0.15
0.15 -0.01 0.99
-From initial position, lean the GamePad on its right side. 45 up. So the screen is pointing to the top right
+From initial position, lean the GamePad on its right side. 45° up. So the screen is pointing to the top right
0.75 0.65 -0.11
-0.65 0.76 0.07
0.12 0.02 0.99
-From initial position, tilt the GamePad up 90 (bottom side remains in touch with surface):
+From initial position, tilt the GamePad up 90° (bottom side remains in touch with surface):
0.99 -0.05 -0.10
-0.10 0.01 -0.99
0.05 1.00 0.01
@@ -309,7 +309,7 @@ From initial position, stand the GamePad on its top side:
0.09 -0.01 1.00
-0.01 -1.00 -0.01
-Rotate GamePad 180 around x axis, so it now lies on its screen (top of GamePad pointing to holder):
+Rotate GamePad 180° around x axis, so it now lies on its screen (top of GamePad pointing to holder):
0.99 -0.03 -0.15
-0.04 -1.00 -0.08
-0.15 0.09 -0.99
From 4d609f06b810a6bc686aa783a2b716e3cd280f0e Mon Sep 17 00:00:00 2001
From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com>
Date: Wed, 20 Mar 2024 10:22:48 +0100
Subject: [PATCH 065/319] InputSettings: Fix controller type counter to restore
WPAD limit (#1118)
---
src/gui/input/InputSettings2.cpp | 32 ++++----------------------------
src/gui/input/InputSettings2.h | 3 ---
2 files changed, 4 insertions(+), 31 deletions(-)
diff --git a/src/gui/input/InputSettings2.cpp b/src/gui/input/InputSettings2.cpp
index 58c168a3..72bf4f7d 100644
--- a/src/gui/input/InputSettings2.cpp
+++ b/src/gui/input/InputSettings2.cpp
@@ -295,32 +295,6 @@ wxWindow* InputSettings2::initialize_page(size_t index)
return page;
}
-std::pair InputSettings2::get_emulated_controller_types() const
-{
- size_t vpad = 0, wpad = 0;
- for(size_t i = 0; i < m_notebook->GetPageCount(); ++i)
- {
- auto* page = m_notebook->GetPage(i);
- auto* page_data = (wxControllerPageData*)page->GetClientObject();
- if (!page_data)
- continue;
-
- if (!page_data->ref().m_controller) // = disabled
- continue;
-
- const auto api_type = page_data->ref().m_controller->type();
- if (api_type)
- continue;
-
- if (api_type == EmulatedController::VPAD)
- ++vpad;
- else
- ++wpad;
- }
-
- return std::make_pair(vpad, wpad);
-}
-
std::shared_ptr InputSettings2::get_active_controller() const
{
auto& page_data = get_current_page_data();
@@ -771,14 +745,16 @@ void InputSettings2::on_emulated_controller_dropdown(wxCommandEvent& event)
wxWindowUpdateLocker lock(emulated_controllers);
bool is_gamepad_selected = false;
+ bool is_wpad_selected = false;
const auto selected = emulated_controllers->GetSelection();
const auto selected_value = emulated_controllers->GetStringSelection();
if(selected != wxNOT_FOUND)
{
is_gamepad_selected = selected_value == to_wxString(EmulatedController::type_to_string(EmulatedController::Type::VPAD));
+ is_wpad_selected = !is_gamepad_selected && selected != 0;
}
- const auto [vpad_count, wpad_count] = get_emulated_controller_types();
+ const auto [vpad_count, wpad_count] = InputManager::instance().get_controller_count();
emulated_controllers->Clear();
emulated_controllers->AppendString(_("Disabled"));
@@ -786,7 +762,7 @@ void InputSettings2::on_emulated_controller_dropdown(wxCommandEvent& event)
if (vpad_count < InputManager::kMaxVPADControllers || is_gamepad_selected)
emulated_controllers->Append(to_wxString(EmulatedController::type_to_string(EmulatedController::Type::VPAD)));
- if (wpad_count < InputManager::kMaxWPADControllers || !is_gamepad_selected)
+ if (wpad_count < InputManager::kMaxWPADControllers || is_wpad_selected)
{
emulated_controllers->AppendString(to_wxString(EmulatedController::type_to_string(EmulatedController::Type::Pro)));
emulated_controllers->AppendString(to_wxString(EmulatedController::type_to_string(EmulatedController::Type::Classic)));
diff --git a/src/gui/input/InputSettings2.h b/src/gui/input/InputSettings2.h
index 01313653..1a3c8bb1 100644
--- a/src/gui/input/InputSettings2.h
+++ b/src/gui/input/InputSettings2.h
@@ -27,9 +27,6 @@ private:
wxWindow* initialize_page(size_t index);
- // count active controllers
- std::pair get_emulated_controller_types() const;
-
// currently selected controller from active tab
std::shared_ptr get_active_controller() const;
From 17060752b6d5bc952446e26c4cd4b0d259653ced Mon Sep 17 00:00:00 2001
From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com>
Date: Sun, 24 Mar 2024 10:57:08 +0100
Subject: [PATCH 066/319] Vulkan: Several swapchain fixes and refactors (#1132)
---
.../Latte/Renderer/Vulkan/SwapchainInfoVk.cpp | 91 +++++++++----------
.../Latte/Renderer/Vulkan/SwapchainInfoVk.h | 25 ++---
.../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 54 ++++++++---
.../HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 13 ++-
4 files changed, 99 insertions(+), 84 deletions(-)
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp
index 14b7a17c..b00f5490 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp
@@ -1,15 +1,34 @@
#include "SwapchainInfoVk.h"
#include "config/CemuConfig.h"
+#include "gui/guiWrapper.h"
#include "Cafe/HW/Latte/Core/Latte.h"
#include "Cafe/HW/Latte/Core/LatteTiming.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
+#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h"
-void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDevice)
+SwapchainInfoVk::SwapchainInfoVk(bool mainWindow, Vector2i size) : mainWindow(mainWindow), m_desiredExtent(size)
{
- m_physicalDevice = physicalDevice;
- m_logicalDevice = logicalDevice;
- const auto details = QuerySwapchainSupport(surface, physicalDevice);
+ auto& windowHandleInfo = mainWindow ? gui_getWindowInfo().canvas_main : gui_getWindowInfo().canvas_pad;
+ auto renderer = VulkanRenderer::GetInstance();
+ m_instance = renderer->GetVkInstance();
+ m_logicalDevice = renderer->GetLogicalDevice();
+ m_physicalDevice = renderer->GetPhysicalDevice();
+
+ m_surface = renderer->CreateFramebufferSurface(m_instance, windowHandleInfo);
+}
+
+
+SwapchainInfoVk::~SwapchainInfoVk()
+{
+ Cleanup();
+ if(m_surface != VK_NULL_HANDLE)
+ vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
+}
+
+void SwapchainInfoVk::Create()
+{
+ const auto details = QuerySwapchainSupport(m_surface, m_physicalDevice);
m_surfaceFormat = ChooseSurfaceFormat(details.formats);
m_actualExtent = ChooseSwapExtent(details.capabilities);
@@ -20,28 +39,28 @@ void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDe
if(image_count < 2)
cemuLog_log(LogType::Force, "Vulkan: Swapchain image count less than 2 may cause problems");
- VkSwapchainCreateInfoKHR create_info = CreateSwapchainCreateInfo(surface, details, m_surfaceFormat, image_count, m_actualExtent);
+ VkSwapchainCreateInfoKHR create_info = CreateSwapchainCreateInfo(m_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);
+ VkResult result = vkCreateSwapchainKHR(m_logicalDevice, &create_info, nullptr, &m_swapchain);
if (result != VK_SUCCESS)
UnrecoverableError("Error attempting to create a swapchain");
- result = vkGetSwapchainImagesKHR(logicalDevice, swapchain, &image_count, nullptr);
+ result = vkGetSwapchainImagesKHR(m_logicalDevice, m_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());
+ result = vkGetSwapchainImagesKHR(m_logicalDevice, m_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.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
@@ -62,7 +81,7 @@ void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDe
renderPassInfo.pAttachments = &colorAttachment;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
- result = vkCreateRenderPass(logicalDevice, &renderPassInfo, nullptr, &m_swapchainRenderPass);
+ result = vkCreateRenderPass(m_logicalDevice, &renderPassInfo, nullptr, &m_swapchainRenderPass);
if (result != VK_SUCCESS)
UnrecoverableError("Failed to create renderpass for swapchain");
@@ -84,7 +103,7 @@ void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDe
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
- result = vkCreateImageView(logicalDevice, &createInfo, nullptr, &m_swapchainImageViews[i]);
+ result = vkCreateImageView(m_logicalDevice, &createInfo, nullptr, &m_swapchainImageViews[i]);
if (result != VK_SUCCESS)
UnrecoverableError("Failed to create imageviews for swapchain");
}
@@ -104,7 +123,7 @@ void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDe
framebufferInfo.width = m_actualExtent.width;
framebufferInfo.height = m_actualExtent.height;
framebufferInfo.layers = 1;
- result = vkCreateFramebuffer(logicalDevice, &framebufferInfo, nullptr, &m_swapchainFramebuffers[i]);
+ result = vkCreateFramebuffer(m_logicalDevice, &framebufferInfo, nullptr, &m_swapchainFramebuffers[i]);
if (result != VK_SUCCESS)
UnrecoverableError("Failed to create framebuffer for swapchain");
}
@@ -114,7 +133,7 @@ void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDe
VkSemaphoreCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
for (auto& semaphore : m_presentSemaphores){
- if (vkCreateSemaphore(logicalDevice, &info, nullptr, &semaphore) != VK_SUCCESS)
+ if (vkCreateSemaphore(m_logicalDevice, &info, nullptr, &semaphore) != VK_SUCCESS)
UnrecoverableError("Failed to create semaphore for swapchain present");
}
@@ -123,14 +142,14 @@ void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDe
info = {};
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
for (auto& semaphore : m_acquireSemaphores){
- if (vkCreateSemaphore(logicalDevice, &info, nullptr, &semaphore) != VK_SUCCESS)
+ if (vkCreateSemaphore(m_logicalDevice, &info, nullptr, &semaphore) != VK_SUCCESS)
UnrecoverableError("Failed to create semaphore for swapchain acquire");
}
VkFenceCreateInfo fenceInfo = {};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
- result = vkCreateFence(logicalDevice, &fenceInfo, nullptr, &m_imageAvailableFence);
+ result = vkCreateFence(m_logicalDevice, &fenceInfo, nullptr, &m_imageAvailableFence);
if (result != VK_SUCCESS)
UnrecoverableError("Failed to create fence for swapchain");
@@ -167,19 +186,20 @@ void SwapchainInfoVk::Cleanup()
if (m_imageAvailableFence)
{
+ WaitAvailableFence();
vkDestroyFence(m_logicalDevice, m_imageAvailableFence, nullptr);
m_imageAvailableFence = nullptr;
}
- if (swapchain)
+ if (m_swapchain)
{
- vkDestroySwapchainKHR(m_logicalDevice, swapchain, nullptr);
- swapchain = VK_NULL_HANDLE;
+ vkDestroySwapchainKHR(m_logicalDevice, m_swapchain, nullptr);
+ m_swapchain = VK_NULL_HANDLE;
}
}
bool SwapchainInfoVk::IsValid() const
{
- return swapchain && !m_acquireSemaphores.empty();
+ return m_swapchain && !m_acquireSemaphores.empty();
}
void SwapchainInfoVk::WaitAvailableFence()
@@ -207,7 +227,7 @@ bool SwapchainInfoVk::AcquireImage(uint64 timeout)
ResetAvailableFence();
VkSemaphore acquireSemaphore = m_acquireSemaphores[m_acquireIndex];
- VkResult result = vkAcquireNextImageKHR(m_logicalDevice, swapchain, timeout, acquireSemaphore, m_imageAvailableFence, &swapchainImageIndex);
+ VkResult result = vkAcquireNextImageKHR(m_logicalDevice, m_swapchain, timeout, acquireSemaphore, m_imageAvailableFence, &swapchainImageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
m_shouldRecreate = true;
if (result < 0)
@@ -231,35 +251,6 @@ void SwapchainInfoVk::UnrecoverableError(const char* errMsg)
throw std::runtime_error(errMsg);
}
-SwapchainInfoVk::QueueFamilyIndices SwapchainInfoVk::FindQueueFamilies(VkSurfaceKHR surface, VkPhysicalDevice device)
-{
- uint32_t queueFamilyCount = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
-
- std::vector 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)
{
@@ -391,7 +382,7 @@ VkSwapchainCreateInfoKHR SwapchainInfoVk::CreateSwapchainCreateInfo(VkSurfaceKHR
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
- const QueueFamilyIndices indices = FindQueueFamilies(surface, m_physicalDevice);
+ const VulkanRenderer::QueueFamilyIndices indices = VulkanRenderer::GetInstance()->FindQueueFamilies(surface, m_physicalDevice);
m_swapchainQueueFamilyIndices = { (uint32)indices.graphicsFamily, (uint32)indices.presentFamily };
if (indices.graphicsFamily != indices.presentFamily)
{
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h b/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h
index 26dbc7d1..0e8c2ade 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h
@@ -14,14 +14,6 @@ struct SwapchainInfoVk
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;
@@ -30,7 +22,7 @@ struct SwapchainInfoVk
};
void Cleanup();
- void Create(VkPhysicalDevice physicalDevice, VkDevice logicalDevice);
+ void Create();
bool IsValid() const;
@@ -45,8 +37,6 @@ struct SwapchainInfoVk
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& modes);
@@ -61,14 +51,10 @@ struct SwapchainInfoVk
return m_actualExtent;
}
- SwapchainInfoVk(VkSurfaceKHR surface, bool mainWindow)
- : surface(surface), mainWindow(mainWindow) {}
+ SwapchainInfoVk(bool mainWindow, Vector2i size);
SwapchainInfoVk(const SwapchainInfoVk&) = delete;
SwapchainInfoVk(SwapchainInfoVk&&) noexcept = default;
- ~SwapchainInfoVk()
- {
- Cleanup();
- }
+ ~SwapchainInfoVk();
bool mainWindow{};
@@ -77,11 +63,12 @@ struct SwapchainInfoVk
VSync m_vsyncState = VSync::Immediate;
bool hasDefinedSwapchainImage{}; // indicates if the swapchain image is in a defined state
+ VkInstance m_instance{};
VkPhysicalDevice m_physicalDevice{};
VkDevice m_logicalDevice{};
- VkSurfaceKHR surface{};
+ VkSurfaceKHR m_surface{};
VkSurfaceFormatKHR m_surfaceFormat{};
- VkSwapchainKHR swapchain{};
+ VkSwapchainKHR m_swapchain{};
Vector2i m_desiredExtent{};
uint32 swapchainImageIndex = (uint32)-1;
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
index 02bb1e71..e0ebda2a 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp
@@ -167,6 +167,7 @@ std::vector VulkanRenderer::GetDevices()
result.emplace_back(physDeviceProps.properties.deviceName, physDeviceIDProps.deviceUUID);
}
}
+ vkDestroySurfaceKHR(instance, surface, nullptr);
}
catch (...)
{
@@ -441,7 +442,7 @@ VulkanRenderer::VulkanRenderer()
}
// create logical device
- m_indices = SwapchainInfoVk::FindQueueFamilies(surface, m_physicalDevice);
+ m_indices = FindQueueFamilies(surface, m_physicalDevice);
std::set uniqueQueueFamilies = { m_indices.graphicsFamily, m_indices.presentFamily };
std::vector queueCreateInfos = CreateQueueCreateInfos(uniqueQueueFamilies);
VkPhysicalDeviceFeatures deviceFeatures = {};
@@ -510,7 +511,7 @@ VulkanRenderer::VulkanRenderer()
PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = reinterpret_cast(vkGetInstanceProcAddr(m_instance, "vkCreateDebugUtilsMessengerEXT"));
VkDebugUtilsMessengerCreateInfoEXT debugCallback{};
- debugCallback.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
+ debugCallback.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
debugCallback.pNext = nullptr;
debugCallback.flags = 0;
debugCallback.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
@@ -673,24 +674,19 @@ VulkanRenderer* VulkanRenderer::GetInstance()
void VulkanRenderer::InitializeSurface(const Vector2i& size, bool mainWindow)
{
- auto& windowHandleInfo = mainWindow ? gui_getWindowInfo().canvas_main : gui_getWindowInfo().canvas_pad;
-
- const auto surface = CreateFramebufferSurface(m_instance, windowHandleInfo);
if (mainWindow)
{
- m_mainSwapchainInfo = std::make_unique(surface, mainWindow);
- m_mainSwapchainInfo->m_desiredExtent = size;
- m_mainSwapchainInfo->Create(m_physicalDevice, m_logicalDevice);
+ m_mainSwapchainInfo = std::make_unique(mainWindow, size);
+ m_mainSwapchainInfo->Create();
// aquire first command buffer
InitFirstCommandBuffer();
}
else
{
- m_padSwapchainInfo = std::make_unique(surface, mainWindow);
- m_padSwapchainInfo->m_desiredExtent = size;
+ m_padSwapchainInfo = std::make_unique(mainWindow, size);
// todo: figure out a way to exclusively create swapchain on main LatteThread
- m_padSwapchainInfo->Create(m_physicalDevice, m_logicalDevice);
+ m_padSwapchainInfo->Create();
}
}
@@ -1074,6 +1070,36 @@ RendererShader* VulkanRenderer::shader_create(RendererShader::ShaderType type, u
return new RendererShaderVk(type, baseHash, auxHash, isGameShader, isGfxPackShader, source);
}
+VulkanRenderer::QueueFamilyIndices VulkanRenderer::FindQueueFamilies(VkSurfaceKHR surface, VkPhysicalDevice device)
+{
+ uint32_t queueFamilyCount = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
+
+ std::vector 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;
+}
+
bool VulkanRenderer::CheckDeviceExtensionSupport(const VkPhysicalDevice device, FeatureControl& info)
{
std::vector availableDeviceExtensions;
@@ -1215,7 +1241,7 @@ std::vector VulkanRenderer::CheckInstanceExtensionSupport(FeatureCo
bool VulkanRenderer::IsDeviceSuitable(VkSurfaceKHR surface, const VkPhysicalDevice& device)
{
- if (!SwapchainInfoVk::FindQueueFamilies(surface, device).IsComplete())
+ if (!FindQueueFamilies(surface, device).IsComplete())
return false;
// check API version (using Vulkan 1.0 way of querying properties)
@@ -2605,7 +2631,7 @@ void VulkanRenderer::RecreateSwapchain(bool mainWindow, bool skipCreate)
chainInfo.m_desiredExtent = size;
if(!skipCreate)
{
- chainInfo.Create(m_physicalDevice, m_logicalDevice);
+ chainInfo.Create();
}
if (mainWindow)
@@ -2675,7 +2701,7 @@ void VulkanRenderer::SwapBuffer(bool mainWindow)
VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.swapchainCount = 1;
- presentInfo.pSwapchains = &chainInfo.swapchain;
+ presentInfo.pSwapchains = &chainInfo.m_swapchain;
presentInfo.pImageIndices = &chainInfo.swapchainImageIndex;
// wait on command buffer semaphore
presentInfo.waitSemaphoreCount = 1;
diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
index 47097dfa..2491d052 100644
--- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
+++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h
@@ -127,7 +127,6 @@ class VulkanRenderer : public Renderer
friend class PipelineCompiler;
using VSync = SwapchainInfoVk::VSync;
- using QueueFamilyIndices = SwapchainInfoVk::QueueFamilyIndices;
static const inline int UNIFORMVAR_RINGBUFFER_SIZE = 1024 * 1024 * 16; // 16MB
@@ -421,6 +420,18 @@ private:
VkDescriptorPool m_descriptorPool;
+ public:
+ struct QueueFamilyIndices
+ {
+ int32_t graphicsFamily = -1;
+ int32_t presentFamily = -1;
+
+ bool IsComplete() const { return graphicsFamily >= 0 && presentFamily >= 0; }
+ };
+ static QueueFamilyIndices FindQueueFamilies(VkSurfaceKHR surface, VkPhysicalDevice device);
+
+ private:
+
struct FeatureControl
{
struct
From 241915e1a6bfd92e4ffd0d6961a178335300e83f Mon Sep 17 00:00:00 2001
From: capitalistspz
Date: Sun, 24 Mar 2024 10:11:18 +0000
Subject: [PATCH 067/319] Gamelist: Display title long names + improvements for
shortcuts (#1126)
- Windows icons are stored as .ico files to %LOCALAPPDATA%/Cemu/icons/
- Long title names chosen as some games (NSMBU + NSLU) add trailing dots for their shortnames
- Long title names have their newlines replaced with spaces at parsing
- Linux shortcut paths are saved with UTF-8 encoding
- Game titles are copied and saved with UTF-8 encoding
---
src/Cafe/TitleList/ParsedMetaXml.h | 7 +-
src/Cafe/TitleList/TitleInfo.cpp | 4 +-
src/gui/CemuApp.cpp | 7 +-
src/gui/components/wxGameList.cpp | 272 ++++++++++++++++-------------
4 files changed, 168 insertions(+), 122 deletions(-)
diff --git a/src/Cafe/TitleList/ParsedMetaXml.h b/src/Cafe/TitleList/ParsedMetaXml.h
index 7537d603..f1aee37e 100644
--- a/src/Cafe/TitleList/ParsedMetaXml.h
+++ b/src/Cafe/TitleList/ParsedMetaXml.h
@@ -90,8 +90,11 @@ struct ParsedMetaXml
else if (boost::starts_with(name, "longname_"))
{
const sint32 index = GetLanguageIndex(name.substr(std::size("longname_") - 1));
- if (index != -1)
- parsedMetaXml->m_long_name[index] = child.text().as_string();
+ if (index != -1){
+ std::string longname = child.text().as_string();
+ std::replace_if(longname.begin(), longname.end(), [](char c) { return c == '\r' || c == '\n';}, ' ');
+ parsedMetaXml->m_long_name[index] = longname;
+ }
}
else if (boost::starts_with(name, L"shortname_"))
{
diff --git a/src/Cafe/TitleList/TitleInfo.cpp b/src/Cafe/TitleList/TitleInfo.cpp
index ff457575..d23e1d0a 100644
--- a/src/Cafe/TitleList/TitleInfo.cpp
+++ b/src/Cafe/TitleList/TitleInfo.cpp
@@ -637,9 +637,9 @@ std::string TitleInfo::GetMetaTitleName() const
if (m_parsedMetaXml)
{
std::string titleNameCfgLanguage;
- titleNameCfgLanguage = m_parsedMetaXml->GetShortName(GetConfig().console_language);
+ titleNameCfgLanguage = m_parsedMetaXml->GetLongName(GetConfig().console_language);
if (titleNameCfgLanguage.empty()) //Get English Title
- titleNameCfgLanguage = m_parsedMetaXml->GetShortName(CafeConsoleLanguage::EN);
+ titleNameCfgLanguage = m_parsedMetaXml->GetLongName(CafeConsoleLanguage::EN);
if (titleNameCfgLanguage.empty()) //Unknown Title
titleNameCfgLanguage = "Unknown Title";
return titleNameCfgLanguage;
diff --git a/src/gui/CemuApp.cpp b/src/gui/CemuApp.cpp
index fde4bcc0..7f11d4c6 100644
--- a/src/gui/CemuApp.cpp
+++ b/src/gui/CemuApp.cpp
@@ -59,7 +59,12 @@ bool CemuApp::OnInit()
fs::path user_data_path, config_path, cache_path, data_path;
auto standardPaths = wxStandardPaths::Get();
fs::path exePath(wxHelper::MakeFSPath(standardPaths.GetExecutablePath()));
-
+#if BOOST_OS_LINUX
+ // GetExecutablePath returns the AppImage's temporary mount location
+ wxString appImagePath;
+ if (wxGetEnv(("APPIMAGE"), &appImagePath))
+ exePath = wxHelper::MakeFSPath(appImagePath);
+#endif
// Try a portable path first, if it exists.
user_data_path = config_path = cache_path = data_path = exePath.parent_path() / "portable";
#if BOOST_OS_MACOS
diff --git a/src/gui/components/wxGameList.cpp b/src/gui/components/wxGameList.cpp
index 8e8f3c4d..73bcd98d 100644
--- a/src/gui/components/wxGameList.cpp
+++ b/src/gui/components/wxGameList.cpp
@@ -19,7 +19,6 @@
#include
#include
-
#include
#include
@@ -526,7 +525,6 @@ void wxGameList::OnKeyDown(wxListEvent& event)
}
}
-
enum ContextMenuEntries
{
kContextMenuRefreshGames = wxID_HIGHEST + 1,
@@ -732,7 +730,7 @@ void wxGameList::OnContextMenuSelected(wxCommandEvent& event)
{
if (wxTheClipboard->Open())
{
- wxTheClipboard->SetData(new wxTextDataObject(gameInfo.GetTitleName()));
+ wxTheClipboard->SetData(new wxTextDataObject(wxString::FromUTF8(gameInfo.GetTitleName())));
wxTheClipboard->Close();
}
break;
@@ -1276,129 +1274,169 @@ void wxGameList::DeleteCachedStrings()
m_name_cache.clear();
}
-#if BOOST_OS_LINUX || BOOST_OS_WINDOWS
-void wxGameList::CreateShortcut(GameInfo2& gameInfo) {
- const auto title_id = gameInfo.GetBaseTitleId();
- const auto title_name = gameInfo.GetTitleName();
- auto exe_path = ActiveSettings::GetExecutablePath();
- const char *flatpak_id = getenv("FLATPAK_ID");
-
- // GetExecutablePath returns the AppImage's temporary mount location, instead of its actual path
- wxString appimage_path;
- if (wxGetEnv(("APPIMAGE"), &appimage_path)) {
- exe_path = appimage_path.utf8_string();
- }
-
#if BOOST_OS_LINUX
- const wxString desktop_entry_name = wxString::Format("%s.desktop", title_name);
- wxFileDialog entry_dialog(this, _("Choose desktop entry location"), "~/.local/share/applications", desktop_entry_name,
- "Desktop file (*.desktop)|*.desktop", wxFD_SAVE | wxFD_CHANGE_DIR | wxFD_OVERWRITE_PROMPT);
-#elif BOOST_OS_WINDOWS
- // Get '%APPDATA%\Microsoft\Windows\Start Menu\Programs' path
- PWSTR user_shortcut_folder;
- SHGetKnownFolderPath(FOLDERID_Programs, 0, NULL, &user_shortcut_folder);
- const wxString shortcut_name = wxString::Format("%s.lnk", title_name);
- wxFileDialog entry_dialog(this, _("Choose shortcut location"), _pathToUtf8(user_shortcut_folder), shortcut_name,
- "Shortcut (*.lnk)|*.lnk", wxFD_SAVE | wxFD_CHANGE_DIR | wxFD_OVERWRITE_PROMPT);
-#endif
- const auto result = entry_dialog.ShowModal();
- if (result == wxID_CANCEL)
- return;
- const auto output_path = entry_dialog.GetPath();
+void wxGameList::CreateShortcut(GameInfo2& gameInfo)
+{
+ const auto titleId = gameInfo.GetBaseTitleId();
+ const auto titleName = wxString::FromUTF8(gameInfo.GetTitleName());
+ auto exePath = ActiveSettings::GetExecutablePath();
+ const char* flatpakId = getenv("FLATPAK_ID");
-#if BOOST_OS_LINUX
- std::optional icon_path;
- // Obtain and convert icon
- {
- m_icon_cache_mtx.lock();
- const auto icon_iter = m_icon_cache.find(title_id);
- const auto result_index = (icon_iter != m_icon_cache.cend()) ? std::optional(icon_iter->second.first) : std::nullopt;
- m_icon_cache_mtx.unlock();
+ const wxString desktopEntryName = wxString::Format("%s.desktop", titleName);
+ wxFileDialog entryDialog(this, _("Choose desktop entry location"), "~/.local/share/applications", desktopEntryName,
+ "Desktop file (*.desktop)|*.desktop", wxFD_SAVE | wxFD_CHANGE_DIR | wxFD_OVERWRITE_PROMPT);
+ const auto result = entryDialog.ShowModal();
+ if (result == wxID_CANCEL)
+ return;
+ const auto output_path = entryDialog.GetPath();
- // In most cases it should find it
- if (!result_index){
- wxMessageBox(_("Icon is yet to load, so will not be used by the shortcut"), _("Warning"), wxOK | wxCENTRE | wxICON_WARNING);
- }
- else {
- const fs::path out_icon_dir = ActiveSettings::GetUserDataPath("icons");
+ std::optional iconPath;
+ // Obtain and convert icon
+ [&]()
+ {
+ int iconIndex, smallIconIndex;
- if (!fs::exists(out_icon_dir) && !fs::create_directories(out_icon_dir)){
- wxMessageBox(_("Cannot access the icon directory, the shortcut will have no icon"), _("Warning"), wxOK | wxCENTRE | wxICON_WARNING);
- }
- else {
- icon_path = out_icon_dir / fmt::format("{:016x}.png", gameInfo.GetBaseTitleId());
+ if (!QueryIconForTitle(titleId, iconIndex, smallIconIndex))
+ {
+ cemuLog_log(LogType::Force, "Icon hasn't loaded");
+ return;
+ }
+ const fs::path outIconDir = ActiveSettings::GetUserDataPath("icons");
- auto image = m_image_list->GetIcon(result_index.value()).ConvertToImage();
+ if (!fs::exists(outIconDir) && !fs::create_directories(outIconDir))
+ {
+ cemuLog_log(LogType::Force, "Failed to create icon directory");
+ return;
+ }
- wxFileOutputStream png_file(_pathToUtf8(icon_path.value()));
- wxPNGHandler pngHandler;
- if (!pngHandler.SaveFile(&image, png_file, false)) {
- icon_path = std::nullopt;
- wxMessageBox(_("The icon was unable to be saved, the shortcut will have no icon"), _("Warning"), wxOK | wxCENTRE | wxICON_WARNING);
- }
- }
- }
- }
+ iconPath = outIconDir / fmt::format("{:016x}.png", gameInfo.GetBaseTitleId());
+ wxFileOutputStream pngFileStream(_pathToUtf8(iconPath.value()));
- std::string desktop_exec_entry;
- if (flatpak_id)
- desktop_exec_entry = fmt::format("/usr/bin/flatpak run {0} --title-id {1:016x}", flatpak_id, title_id);
- else
- desktop_exec_entry = fmt::format("{0:?} --title-id {1:016x}", _pathToUtf8(exe_path), title_id);
+ auto image = m_image_list->GetIcon(iconIndex).ConvertToImage();
+ wxPNGHandler pngHandler;
+ if (!pngHandler.SaveFile(&image, pngFileStream, false))
+ {
+ iconPath = std::nullopt;
+ cemuLog_log(LogType::Force, "Icon failed to save");
+ }
+ }();
- // 'Icon' accepts spaces in file name, does not accept quoted file paths
- // 'Exec' does not accept non-escaped spaces, and can accept quoted file paths
- auto desktop_entry_string =
- fmt::format("[Desktop Entry]\n"
- "Name={0}\n"
- "Comment=Play {0} on Cemu\n"
- "Exec={1}\n"
- "Icon={2}\n"
- "Terminal=false\n"
- "Type=Application\n"
- "Categories=Game;\n",
- title_name,
- desktop_exec_entry,
- _pathToUtf8(icon_path.value_or("")));
+ std::string desktopExecEntry = flatpakId ? fmt::format("/usr/bin/flatpak run {0} --title-id {1:016x}", flatpakId, titleId)
+ : fmt::format("{0:?} --title-id {1:016x}", _pathToUtf8(exePath), titleId);
- if (flatpak_id)
- desktop_entry_string += fmt::format("X-Flatpak={}\n", flatpak_id);
+ // 'Icon' accepts spaces in file name, does not accept quoted file paths
+ // 'Exec' does not accept non-escaped spaces, and can accept quoted file paths
+ auto desktopEntryString = fmt::format(
+ "[Desktop Entry]\n"
+ "Name={0}\n"
+ "Comment=Play {0} on Cemu\n"
+ "Exec={1}\n"
+ "Icon={2}\n"
+ "Terminal=false\n"
+ "Type=Application\n"
+ "Categories=Game;\n",
+ titleName.utf8_string(),
+ desktopExecEntry,
+ _pathToUtf8(iconPath.value_or("")));
- std::ofstream output_stream(output_path);
- if (!output_stream.good())
- {
- auto errorMsg = formatWxString(_("Failed to save desktop entry to {}"), output_path.utf8_string());
- wxMessageBox(errorMsg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
- return;
- }
- output_stream << desktop_entry_string;
+ if (flatpakId)
+ desktopEntryString += fmt::format("X-Flatpak={}\n", flatpakId);
-#elif BOOST_OS_WINDOWS
- IShellLinkW *shell_link;
- HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, reinterpret_cast(&shell_link));
- if (SUCCEEDED(hres))
- {
- const auto description = wxString::Format("Play %s on Cemu", title_name);
- const auto args = wxString::Format("-t %016llx", title_id);
-
- shell_link->SetPath(exe_path.wstring().c_str());
- shell_link->SetDescription(description.wc_str());
- shell_link->SetArguments(args.wc_str());
- shell_link->SetWorkingDirectory(exe_path.parent_path().wstring().c_str());
- // Use icon from Cemu exe for now since we can't embed icons into the shortcut
- // in the future we could convert and store icons in AppData or ProgramData
- shell_link->SetIconLocation(exe_path.wstring().c_str(), 0);
-
- IPersistFile *shell_link_file;
- // save the shortcut
- hres = shell_link->QueryInterface(IID_IPersistFile, reinterpret_cast(&shell_link_file));
- if (SUCCEEDED(hres))
- {
- hres = shell_link_file->Save(output_path.wc_str(), TRUE);
- shell_link_file->Release();
- }
- shell_link->Release();
- }
-#endif
+ std::ofstream outputStream(output_path.utf8_string());
+ if (!outputStream.good())
+ {
+ auto errorMsg = formatWxString(_("Failed to save desktop entry to {}"), output_path.utf8_string());
+ wxMessageBox(errorMsg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
+ return;
+ }
+ outputStream << desktopEntryString;
}
-#endif
+#elif BOOST_OS_WINDOWS
+void wxGameList::CreateShortcut(GameInfo2& gameInfo)
+{
+ const auto titleId = gameInfo.GetBaseTitleId();
+ const auto titleName = wxString::FromUTF8(gameInfo.GetTitleName());
+ auto exePath = ActiveSettings::GetExecutablePath();
+
+ // Get '%APPDATA%\Microsoft\Windows\Start Menu\Programs' path
+ PWSTR userShortcutFolder;
+ SHGetKnownFolderPath(FOLDERID_Programs, 0, NULL, &userShortcutFolder);
+ const wxString shortcutName = wxString::Format("%s.lnk", titleName);
+ wxFileDialog shortcutDialog(this, _("Choose shortcut location"), _pathToUtf8(userShortcutFolder), shortcutName,
+ "Shortcut (*.lnk)|*.lnk", wxFD_SAVE | wxFD_CHANGE_DIR | wxFD_OVERWRITE_PROMPT);
+
+ const auto result = shortcutDialog.ShowModal();
+ if (result == wxID_CANCEL)
+ return;
+ const auto outputPath = shortcutDialog.GetPath();
+
+ std::optional icon_path = std::nullopt;
+ [&]()
+ {
+ int iconIdx;
+ int smallIconIdx;
+ if (!QueryIconForTitle(titleId, iconIdx, smallIconIdx))
+ {
+ cemuLog_log(LogType::Force, "Icon hasn't loaded");
+ return;
+ }
+ const auto icon = m_image_list->GetIcon(iconIdx);
+ PWSTR localAppData;
+ const auto hres = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData);
+ wxBitmap bitmap{};
+ auto folder = fs::path(localAppData) / "Cemu" / "icons";
+ if (!SUCCEEDED(hres) || (!fs::exists(folder) && !fs::create_directories(folder)))
+ {
+ cemuLog_log(LogType::Force, "Failed to create icon directory");
+ return;
+ }
+ if (!bitmap.CopyFromIcon(icon))
+ {
+ cemuLog_log(LogType::Force, "Failed to copy icon");
+ return;
+ }
+
+ icon_path = folder / fmt::format("{:016x}.ico", titleId);
+ auto stream = wxFileOutputStream(_pathToUtf8(*icon_path));
+ auto image = bitmap.ConvertToImage();
+ wxICOHandler icohandler{};
+ if (!icohandler.SaveFile(&image, stream, false))
+ {
+ icon_path = std::nullopt;
+ cemuLog_log(LogType::Force, "Icon failed to save");
+ }
+ }();
+
+ IShellLinkW* shellLink;
+ HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, reinterpret_cast(&shellLink));
+ if (SUCCEEDED(hres))
+ {
+ const auto description = wxString::Format("Play %s on Cemu", titleName);
+ const auto args = wxString::Format("-t %016llx", titleId);
+
+ shellLink->SetPath(exePath.wstring().c_str());
+ shellLink->SetDescription(description.wc_str());
+ shellLink->SetArguments(args.wc_str());
+ shellLink->SetWorkingDirectory(exePath.parent_path().wstring().c_str());
+
+ if (icon_path)
+ shellLink->SetIconLocation(icon_path->wstring().c_str(), 0);
+ else
+ shellLink->SetIconLocation(exePath.wstring().c_str(), 0);
+
+ IPersistFile* shellLinkFile;
+ // save the shortcut
+ hres = shellLink->QueryInterface(IID_IPersistFile, reinterpret_cast(&shellLinkFile));
+ if (SUCCEEDED(hres))
+ {
+ hres = shellLinkFile->Save(outputPath.wc_str(), TRUE);
+ shellLinkFile->Release();
+ }
+ shellLink->Release();
+ }
+ if (!SUCCEEDED(hres)) {
+ auto errorMsg = formatWxString(_("Failed to save shortcut to {}"), outputPath);
+ wxMessageBox(errorMsg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
+ }
+}
+#endif
\ No newline at end of file
From 4d148b369660db629c225bf1ff0e354d025e7902 Mon Sep 17 00:00:00 2001
From: Francesco Saltori
Date: Mon, 25 Mar 2024 21:34:40 +0100
Subject: [PATCH 068/319] Add supported locales to macOS plist (#1133)
---
src/resource/MacOSXBundleInfo.plist.in | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/src/resource/MacOSXBundleInfo.plist.in b/src/resource/MacOSXBundleInfo.plist.in
index 98064735..ccd1c922 100644
--- a/src/resource/MacOSXBundleInfo.plist.in
+++ b/src/resource/MacOSXBundleInfo.plist.in
@@ -30,6 +30,28 @@
${MACOSX_BUNDLE_CATEGORY}
LSMinimumSystemVersion
${MACOSX_MINIMUM_SYSTEM_VERSION}
+ CFBundleLocalizations
+
+ ca
+ de
+ en
+ es
+ fr
+ he
+ hu
+ it
+ ja
+ ko
+ nb
+ nl
+ pl
+ pt
+ ru
+ sv
+ tr
+ uk
+ zh
+
CFBundleDocumentTypes
From 4b7d2f88ae044a590dfa7faeadee1e03047492f0 Mon Sep 17 00:00:00 2001
From: Exzap <13877693+Exzap@users.noreply.github.com>
Date: Mon, 25 Mar 2024 21:02:37 +0100
Subject: [PATCH 069/319] Latte: Enable colorbuffer optimization if gfx packs
are aware
The optimization for colorbuffer resolution introduced in PR #706 is now enabled. This optimization changes the resolution of certain framebuffer textures, which may conflict with the texture resolution rules set by some graphic packs. As a result, if a graphic pack that specifies texture resolution rules is in use, the optimization will automatically be turned off to prevent any issues.
To circumvent this, graphic packs can now include the setting "colorbufferOptimizationAware = true" in their rules.txt. This setting indicates that the pack has been updated to handle the resolution changes introduced by the optimization. Cemu will allow the optimization to remain enabled if resolution packs have this flag set.
---
src/Cafe/GraphicPack/GraphicPack2.cpp | 4 ++++
src/Cafe/GraphicPack/GraphicPack2.h | 3 +++
src/Cafe/HW/Latte/Core/Latte.h | 2 ++
src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp | 21 ++++++++++----------
src/Cafe/HW/Latte/Core/LatteTexture.cpp | 7 ++++---
src/Cafe/HW/Latte/Core/LatteThread.cpp | 17 ++++++++++++++++
6 files changed, 41 insertions(+), 13 deletions(-)
diff --git a/src/Cafe/GraphicPack/GraphicPack2.cpp b/src/Cafe/GraphicPack/GraphicPack2.cpp
index b581316e..27d423b9 100644
--- a/src/Cafe/GraphicPack/GraphicPack2.cpp
+++ b/src/Cafe/GraphicPack/GraphicPack2.cpp
@@ -280,6 +280,10 @@ GraphicPack2::GraphicPack2(fs::path rulesPath, IniParser& rules)
m_enabled = m_default_enabled;
}
+ auto option_allowRendertargetSizeOptimization = rules.FindOption("colorbufferOptimizationAware");
+ if (option_allowRendertargetSizeOptimization)
+ m_allowRendertargetSizeOptimization = boost::iequals(*option_allowRendertargetSizeOptimization, "true") || boost::iequals(*option_allowRendertargetSizeOptimization, "1");
+
auto option_vendorFilter = rules.FindOption("vendorFilter");
if (option_vendorFilter)
{
diff --git a/src/Cafe/GraphicPack/GraphicPack2.h b/src/Cafe/GraphicPack/GraphicPack2.h
index 6b07cce9..9b6a86d4 100644
--- a/src/Cafe/GraphicPack/GraphicPack2.h
+++ b/src/Cafe/GraphicPack/GraphicPack2.h
@@ -113,6 +113,7 @@ public:
const std::string& GetVirtualPath() const { return m_virtualPath; } // returns the path in the gfx tree hierarchy
const std::string& GetDescription() const { return m_description; }
bool IsDefaultEnabled() const { return m_default_enabled; }
+ bool AllowRendertargetSizeOptimization() const { return m_allowRendertargetSizeOptimization; }
void SetEnabled(bool state) { m_enabled = state; }
@@ -217,6 +218,8 @@ private:
bool m_default_enabled = false;
+ bool m_allowRendertargetSizeOptimization = false; // gfx pack supports framebuffers with non-padded sizes, which is an optional optimization introduced with Cemu 2.0-74
+
// filter
std::optional m_renderer_api;
std::optional m_gfx_vendor;
diff --git a/src/Cafe/HW/Latte/Core/Latte.h b/src/Cafe/HW/Latte/Core/Latte.h
index d9419a6a..e8cb2be4 100644
--- a/src/Cafe/HW/Latte/Core/Latte.h
+++ b/src/Cafe/HW/Latte/Core/Latte.h
@@ -25,6 +25,8 @@ struct LatteGPUState_t
// context control
uint32 contextControl0;
uint32 contextControl1;
+ // optional features
+ bool allowFramebufferSizeOptimization{false}; // allow using scissor box as size hint to determine non-padded rendertarget size
// draw context
struct
{
diff --git a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
index 30069712..f165e257 100644
--- a/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteRenderTarget.cpp
@@ -267,14 +267,15 @@ LatteTextureView* LatteMRT::GetColorAttachmentTexture(uint32 index, bool createN
// colorbuffer width/height has to be padded to 8/32 alignment but the actual resolution might be smaller
// use the scissor box as a clue to figure out the original resolution if possible
-#if 0
- uint32 scissorBoxWidth = LatteGPUState.contextNew.PA_SC_GENERIC_SCISSOR_BR.get_BR_X();
- uint32 scissorBoxHeight = LatteGPUState.contextNew.PA_SC_GENERIC_SCISSOR_BR.get_BR_Y();
- if (((scissorBoxWidth + 7) & ~7) == colorBufferWidth)
- colorBufferWidth = scissorBoxWidth;
- if (((colorBufferHeight + 31) & ~31) == colorBufferHeight)
- colorBufferHeight = scissorBoxHeight;
-#endif
+ if(LatteGPUState.allowFramebufferSizeOptimization)
+ {
+ uint32 scissorBoxWidth = LatteGPUState.contextNew.PA_SC_GENERIC_SCISSOR_BR.get_BR_X();
+ uint32 scissorBoxHeight = LatteGPUState.contextNew.PA_SC_GENERIC_SCISSOR_BR.get_BR_Y();
+ if (((scissorBoxWidth + 7) & ~7) == colorBufferWidth)
+ colorBufferWidth = scissorBoxWidth;
+ if (((colorBufferHeight + 31) & ~31) == colorBufferHeight)
+ colorBufferHeight = scissorBoxHeight;
+ }
// log resolution changes if the above heuristic takes effect
// this is useful to find resolutions which need to be updated in gfx pack texture rules
@@ -303,7 +304,7 @@ LatteTextureView* LatteMRT::GetColorAttachmentTexture(uint32 index, bool createN
if (colorBufferView == nullptr)
{
// create color buffer view
- colorBufferView = LatteTexture_CreateMapping(colorBufferPhysMem, 0, colorBufferWidth, colorBufferHeight, (viewFirstSlice + viewNumSlices), colorBufferPitch, colorBufferTileMode, colorBufferSwizzle>>8, viewFirstMip, 1, viewFirstSlice, viewNumSlices, (Latte::E_GX2SURFFMT)colorBufferFormat, (viewFirstSlice + viewNumSlices)>1? Latte::E_DIM::DIM_2D_ARRAY: Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, false);
+ colorBufferView = LatteTexture_CreateMapping(colorBufferPhysMem, 0, colorBufferWidth, colorBufferHeight, (viewFirstSlice + viewNumSlices), colorBufferPitch, colorBufferTileMode, colorBufferSwizzle>>8, viewFirstMip, 1, viewFirstSlice, viewNumSlices, (Latte::E_GX2SURFFMT)colorBufferFormat, (viewFirstSlice + viewNumSlices)>1? Latte::E_DIM::DIM_2D_ARRAY: Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, false, true);
LatteGPUState.repeatTextureInitialization = true;
checkForTextureChanges = false;
}
@@ -582,7 +583,7 @@ bool LatteMRT::UpdateCurrentFBO()
if (!depthBufferView)
{
// create new depth buffer view and if it doesn't exist then also create the texture
- depthBufferView = LatteTexture_CreateMapping(depthBufferPhysMem, 0, depthBufferWidth, depthBufferHeight, depthBufferViewFirstSlice+1, depthBufferPitch, depthBufferTileMode, depthBufferSwizzle, 0, 1, depthBufferViewFirstSlice, 1, depthBufferFormat, depthBufferViewFirstSlice > 0 ? Latte::E_DIM::DIM_2D_ARRAY : Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true);
+ depthBufferView = LatteTexture_CreateMapping(depthBufferPhysMem, 0, depthBufferWidth, depthBufferHeight, depthBufferViewFirstSlice+1, depthBufferPitch, depthBufferTileMode, depthBufferSwizzle, 0, 1, depthBufferViewFirstSlice, 1, depthBufferFormat, depthBufferViewFirstSlice > 0 ? Latte::E_DIM::DIM_2D_ARRAY : Latte::E_DIM::DIM_2D, Latte::E_DIM::DIM_2D, true, true);
LatteGPUState.repeatTextureInitialization = true;
}
else
diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.cpp b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
index d6f576d4..3754fb19 100644
--- a/src/Cafe/HW/Latte/Core/LatteTexture.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteTexture.cpp
@@ -1,5 +1,4 @@
#include "Cafe/HW/Latte/Core/Latte.h"
-#include "Cafe/HW/Latte/Core/LatteDraw.h"
#include "Cafe/HW/Latte/Core/LatteShader.h"
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
#include "Cafe/HW/Latte/Core/LatteTexture.h"
@@ -9,6 +8,8 @@
#include "Cafe/GraphicPack/GraphicPack2.h"
+#include
+
struct TexMemOccupancyEntry
{
uint32 addrStart;
@@ -963,7 +964,7 @@ void LatteTexture_RecreateTextureWithDifferentMipSliceCount(LatteTexture* textur
}
// create new texture representation
-// if allowCreateNewDataTexture is true, a new texture will be created if necessary. If it is false, only existing textures may be used, except if a data-compatible version of the requested texture already exists and it's not view compatible
+// if allowCreateNewDataTexture is true, a new texture will be created if necessary. If it is false, only existing textures may be used, except if a data-compatible version of the requested texture already exists and it's not view compatible (todo - we should differentiate between Latte compatible views and renderer compatible)
// the returned view will map to the provided mip and slice range within the created texture, this is to match the behavior of lookupSliceEx
LatteTextureView* LatteTexture_CreateMapping(MPTR physAddr, MPTR physMipAddr, sint32 width, sint32 height, sint32 depth, sint32 pitch, Latte::E_HWTILEMODE tileMode, uint32 swizzle, sint32 firstMip, sint32 numMip, sint32 firstSlice, sint32 numSlice, Latte::E_GX2SURFFMT format, Latte::E_DIM dimBase, Latte::E_DIM dimView, bool isDepth, bool allowCreateNewDataTexture)
{
@@ -980,7 +981,7 @@ LatteTextureView* LatteTexture_CreateMapping(MPTR physAddr, MPTR physMipAddr, si
// todo, depth and numSlice are redundant
sint32 sliceCount = firstSlice + numSlice;
- std::vector list_overlappingTextures;
+ boost::container::small_vector list_overlappingTextures;
for (sint32 sliceIndex = 0; sliceIndex < sliceCount; sliceIndex++)
{
sint32 mipIndex = 0;
diff --git a/src/Cafe/HW/Latte/Core/LatteThread.cpp b/src/Cafe/HW/Latte/Core/LatteThread.cpp
index bd312d93..a23bd5be 100644
--- a/src/Cafe/HW/Latte/Core/LatteThread.cpp
+++ b/src/Cafe/HW/Latte/Core/LatteThread.cpp
@@ -175,6 +175,23 @@ int Latte_ThreadEntry()
// before doing anything with game specific shaders, we need to wait for graphic packs to finish loading
GraphicPack2::WaitUntilReady();
+ // if legacy packs are enabled we cannot use the colorbuffer resolution optimization
+ LatteGPUState.allowFramebufferSizeOptimization = true;
+ for(auto& pack : GraphicPack2::GetActiveGraphicPacks())
+ {
+ if(pack->AllowRendertargetSizeOptimization())
+ continue;
+ for(auto& rule : pack->GetTextureRules())
+ {
+ if(rule.filter_settings.width >= 0 || rule.filter_settings.height >= 0 || rule.filter_settings.depth >= 0 ||
+ rule.overwrite_settings.width >= 0 || rule.overwrite_settings.height >= 0 || rule.overwrite_settings.depth >= 0)
+ {
+ LatteGPUState.allowFramebufferSizeOptimization = false;
+ cemuLog_log(LogType::Force, "Graphic pack {} prevents rendertarget size optimization.", pack->GetName());
+ break;
+ }
+ }
+ }
// load disk shader cache
LatteShaderCache_Load();
// init registers
From fa4ad9b8c196c0821888c0d882154d10feee673b Mon Sep 17 00:00:00 2001
From: SSimco <37044560+SSimco@users.noreply.github.com>
Date: Mon, 25 Mar 2024 23:30:39 +0200
Subject: [PATCH 070/319] Gamelist: Add option to hide the icon column (#604)
---
src/config/CemuConfig.cpp | 3 +++
src/config/CemuConfig.h | 2 ++
src/gui/components/wxGameList.cpp | 15 +++++++++++++--
3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/src/config/CemuConfig.cpp b/src/config/CemuConfig.cpp
index 1801759a..e4be97a7 100644
--- a/src/config/CemuConfig.cpp
+++ b/src/config/CemuConfig.cpp
@@ -84,6 +84,8 @@ void CemuConfig::Load(XMLConfigParser& parser)
game_list_style = gamelist.get("style", 0);
game_list_column_order = gamelist.get("order", "");
+ show_icon_column = parser.get("show_icon_column", true);
+
// return default width if value in config file out of range
auto loadColumnSize = [&gamelist] (const char *name, uint32 defaultWidth)
{
@@ -385,6 +387,7 @@ void CemuConfig::Save(XMLConfigParser& parser)
psize.set("x", pad_size.x);
psize.set("y", pad_size.y);
config.set