17 Commits
Author SHA1 Message Date
goeiecool9999andGitHub 138510106c Vulkan: Fix freeze when closing pad view (#435) 2022-11-06 00:40:00 +01:00
Exzap 948460cad7 InputSettings: Refresh panels on profile load and other operations 2022-11-06 00:32:33 +01:00
Exzap 3df8217a02 SDLController: Do not manually recycle controller instance
SDL_GameControllerFromInstanceID does not increase internal ref counter.
Fixes a crash when removing an SDL controller that is in use by another profile
2022-11-06 00:32:33 +01:00
Exzap ec6726e85c Use generic EC_POINT_get_affine_coordinates 2022-11-06 00:32:33 +01:00
goeiecool9999andGitHub 348d86648f Vulkan: Refactor swapchain code (#399) 2022-11-04 15:22:29 +01:00
ExzapandGitHub 592c9b2776 Update build_check.yml 2022-11-04 15:09:25 +01:00
qurious-pixelandGitHub 5d156672e8 CI: Add AppImage Build (#452) 2022-11-04 15:07:17 +01:00
TillsunsetandGitHub 2f86622a68 Don't go to mount point for free space check (#450) 2022-11-04 14:34:32 +01:00
ExzapandGitHub a40b226e00 CubebInput: Avoid redundant CoInitializeEx (#449) 2022-11-03 18:29:21 +01:00
TillsunsetandGitHub 521f2fb707 MacOS: Workaround for Metal stride limitation (#445) 2022-11-03 12:51:32 +01:00
goeiecool9999andGitHub a129d22a57 Vulkan: Experimental fix for self-dependency barriers during renderpass (#431) 2022-11-03 00:43:26 +01:00
Adrian GraberandGitHub d4e14d2b05 Implement proper microphone support (#251) 2022-11-03 00:24:34 +01:00
goeiecool9999andGitHub dfa7774c4c Non-windows: Link fontawesome into executable. (#442) 2022-11-03 00:23:31 +01:00
goeiecool9999andGitHub c3182aedd9 GeneralSettings: Update vsync after settings close (#401) 2022-10-31 17:54:26 +01:00
Zhaohui ShiandGitHub f41f7b63e8 DSUController: fix crash when running on offline mode (#434) 2022-10-31 14:27:35 +01:00
TillsunsetandGitHub c143950dd1 Fix fullscreen on macos (#429) 2022-10-30 01:40:53 +02:00
jn64andGitHub 4e991d603a Add libpulse-dev to CI build (#430) 2022-10-30 01:39:39 +02:00
42 changed files with 1521 additions and 737 deletions
+38 -14
View File
@@ -22,34 +22,36 @@ jobs:
uses: actions/checkout@v3
with:
submodules: "recursive"
- name: Setup release mode parameters (for deploy)
if: ${{ inputs.deploymode == 'release' }}
run: |
echo "BUILD_MODE=release" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is release"
- name: Setup debug mode parameters (for continous build)
if: ${{ inputs.deploymode != 'release' }}
run: |
echo "BUILD_MODE=debug" >> $GITHUB_ENV
echo "BUILD_FLAGS=" >> $GITHUB_ENV
echo "Build mode is debug"
- name: Setup version for experimental
if: ${{ inputs.experimentalversion != '' }}
run: |
echo "[INFO] Experimental version ${{ inputs.experimentalversion }}"
echo "BUILD_FLAGS=${{ env.BUILD_FLAGS }} -DEXPERIMENTAL_VERSION=${{ inputs.experimentalversion }}" >> $GITHUB_ENV
- name: "Install system dependencies"
run: |
sudo apt update -qq
sudo apt install -y ninja-build cmake libgtk-3-dev libsecret-1-dev libgcrypt20-dev libsystemd-dev freeglut3-dev clang-12 nasm
sudo apt install -y clang-12 cmake freeglut3-dev libgcrypt20-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build
- name: "Bootstrap vcpkg"
run: |
bash ./dependencies/vcpkg/bootstrap-vcpkg.sh
- name: 'Setup NuGet Credentials for vcpkg'
shell: 'bash'
run: |
@@ -66,15 +68,12 @@ jobs:
- name: "cmake"
run: |
mkdir -p build
cd build
cmake .. ${{ env.BUILD_FLAGS }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} -DCMAKE_C_COMPILER=/usr/bin/clang-12 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-12 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja
cmake -S . -B build ${{ env.BUILD_FLAGS }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_MODE }} -DPORTABLE=OFF -DCMAKE_C_COMPILER=/usr/bin/clang-12 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-12 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja
- name: "Build Cemu"
run: |
cd build
ninja
cmake --build build
- name: Prepare artifact
if: ${{ inputs.deploymode == 'release' }}
run: mv bin/Cemu_release bin/Cemu
@@ -85,8 +84,33 @@ jobs:
with:
name: cemu-bin-linux-x64
path: ./bin/Cemu
build-appimage:
runs-on: ubuntu-20.04
needs: build-ubuntu
steps:
- name: Checkout Upstream Repo
uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: cemu-bin-linux-x64
path: bin
- name: "Install system dependencies"
run: |
sudo apt update -qq
sudo apt install -y clang-12 cmake freeglut3-dev libgcrypt20-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build
- name: "Build AppImage"
run: dist/linux/appimage.sh
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: cemu-appimage-x64
path: artifacts
build-windows:
runs-on: windows-2022
steps:
@@ -239,4 +263,4 @@ jobs:
if: ${{ inputs.deploymode == 'release' }}
with:
name: cemu-bin-macos-x64
path: ./bin/Cemu.dmg
path: ./bin/Cemu.dmg
@@ -13,13 +13,18 @@ jobs:
runs-on: ubuntu-20.04
needs: call-release-build
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: cemu-bin-linux-x64
path: cemu-bin-linux-x64
- uses: actions/download-artifact@v3
with:
name: cemu-appimage-x64
path: cemu-appimage-x64
- uses: actions/download-artifact@v3
with:
name: cemu-bin-windows-x64
@@ -53,7 +58,14 @@ jobs:
mv cemu-bin-windows-x64/Cemu.exe ./${{ env.CEMU_FOLDER_NAME }}/Cemu.exe
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create appimage
run: |
VERSION=${{ env.CEMU_VERSION }}
echo "Cemu Version is $VERSION"
ls cemu-appimage-x64
mv cemu-appimage-x64/Cemu-*-x86_64.AppImage upload/Cemu-$VERSION-x86_64.AppImage
- name: Create release from linux-bin
run: |
ls ./
+14 -6
View File
@@ -15,13 +15,18 @@ jobs:
runs-on: ubuntu-20.04
needs: call-release-build
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: cemu-bin-linux-x64
path: cemu-bin-linux-x64
- uses: actions/download-artifact@v3
with:
name: cemu-appimage-x64
path: cemu-appimage-x64
- uses: actions/download-artifact@v3
with:
name: cemu-bin-windows-x64
@@ -44,11 +49,7 @@ jobs:
echo "Cemu CI version: $(./getversion)"
echo "CEMU_FOLDER_NAME=Cemu_$(./getversion)" >> $GITHUB_ENV
echo "CEMU_VERSION=$(./getversion)" >> $GITHUB_ENV
- name: Create appimage
run: |
echo "to do"
- name: Create release from windows-bin
run: |
ls ./
@@ -57,6 +58,13 @@ jobs:
mv cemu-bin-windows-x64/Cemu.exe ./${{ env.CEMU_FOLDER_NAME }}/Cemu.exe
zip -9 -r upload/cemu-${{ env.CEMU_VERSION }}-windows-x64.zip ${{ env.CEMU_FOLDER_NAME }}
rm -r ./${{ env.CEMU_FOLDER_NAME }}
- name: Create appimage
run: |
VERSION=${{ env.CEMU_VERSION }}
echo "Cemu Version is $VERSION"
ls cemu-appimage-x64
mv cemu-appimage-x64/Cemu-*-x86_64.AppImage upload/Cemu-$VERSION-x86_64.AppImage
- name: Create release from ubuntu-bin
run: |
+3 -3
View File
@@ -25,7 +25,7 @@ To compile Cemu, a recent enough compiler and STL with C++20 support is required
### Installing dependencies
#### For Ubuntu and derivatives:
`sudo apt install -y git curl cmake ninja-build nasm libgtk-3-dev libsecret-1-dev libgcrypt20-dev libsystemd-dev freeglut3-dev libpulse-dev`
`sudo apt install -y cmake curl freeglut3-dev git libgcrypt20-dev libgtk-3-dev libpulse-dev libsecret-1-dev libsystemd-dev nasm ninja-build`
*Additionally, for Ubuntu 22.04 only:*
- `sudo apt install -y clang-12`
@@ -33,10 +33,10 @@ To compile Cemu, a recent enough compiler and STL with C++20 support is required
`cmake -S . -B build -DCMAKE_BUILD_TYPE=release -DCMAKE_C_COMPILER=/usr/bin/clang-12 -DCMAKE_CXX_COMPILER=/usr/bin/clang++-12 -G Ninja -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja`
#### For Arch and derivatives:
`sudo pacman -S --needed git cmake llvm clang ninja nasm base-devel linux-headers gtk3 libsecret libgcrypt systemd freeglut zip unzip libpulse`
`sudo pacman -S --needed base-devel clang cmake freeglut git gtk3 libgcrypt libpulse libsecret linux-headers llvm nasm ninja systemd unzip zip`
#### For Fedora and derivatives:
`sudo dnf install git cmake clang ninja-build nasm kernel-headers gtk3-devel libsecret-devel libgcrypt-devel systemd-devel freeglut-devel perl-core zlib-devel cubeb-devel`
`sudo dnf install clang cmake cubeb-devel freeglut-devel git gtk3-devel kernel-headers libgcrypt-devel libsecret-devel nasm ninja-build perl-core systemd-devel zlib-devel`
### Build Cemu using cmake and clang
1. `git clone --recursive https://github.com/cemu-project/Cemu`
Vendored Executable
+50
View File
@@ -0,0 +1,50 @@
#!/bin/bash
if [ -z "${GITHUB_WORKSPACE}" ]; then
export GITHUB_WORKSPACE="."
fi
curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
chmod a+x linuxdeploy*.AppImage
curl -sSfL https://github.com$(curl https://github.com/probonopd/go-appimage/releases/expanded_assets/continuous | grep "mkappimage-.*-x86_64.AppImage" | head -n 1 | cut -d '"' -f 2) -o mkappimage.AppImage
chmod a+x mkappimage.AppImage
curl -sSfLO "https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh"
chmod a+x linuxdeploy-plugin-gtk.sh
if [[ ! -e /usr/lib/x86_64-linux-gnu ]]; then
sed -i 's#lib\/x86_64-linux-gnu#lib64#g' linuxdeploy-plugin-gtk.sh
fi
mkdir -p AppDir/usr/
cp dist/linux/{info.cemu.Cemu.desktop,info.cemu.Cemu.png} AppDir/
mkdir -p AppDir/usr/share/applications
mkdir -p AppDir/usr/share/icons/hicolor/scalable/apps
mkdir -p AppDir/usr/lib
cp -r bin AppDir/usr/
cp /usr/lib/x86_64-linux-gnu/{libsepol.so.1,libffi.so.7,libpcre.so.3,libGLU.so.1} AppDir/usr/lib
chmod +x AppDir/usr/bin/Cemu
#chmod +x AppDir/AppRun
export UPD_INFO="gh-releases-zsync|cemu-project|Cemu|ci|Cemu.AppImage.zsync"
./linuxdeploy-x86_64.AppImage --appimage-extract-and-run\
--appdir="$GITHUB_WORKSPACE"/AppDir/ \
-d "$GITHUB_WORKSPACE"/AppDir/info.cemu.Cemu.desktop \
-i "$GITHUB_WORKSPACE"/AppDir/info.cemu.Cemu.png \
-e "$GITHUB_WORKSPACE"/AppDir/usr/bin/Cemu \
--plugin gtk
GITVERSION=$(git rev-parse --short HEAD)
echo $GITVERSION
if [[ -z ${GITVERSION} ]]; then
GITVERSION=experimental
fi
echo "Cemu Version Cemu-${GITVERSION}"
rm AppDir/usr/lib/libwayland-client.so.0
VERSION=${GITVERSION} ./mkappimage.AppImage --appimage-extract-and-run "$GITHUB_WORKSPACE"/AppDir
mkdir -p "$GITHUB_WORKSPACE"/artifacts/
mv Cemu-${GITVERSION}-x86_64.AppImage "$GITHUB_WORKSPACE"/artifacts/
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+2
View File
@@ -178,6 +178,8 @@ add_library(CemuCafe
HW/Latte/Renderer/Vulkan/LatteTextureVk.h
HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp
HW/Latte/Renderer/Vulkan/RendererShaderVk.h
HW/Latte/Renderer/Vulkan/SwapchainInfoVk.cpp
HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h
HW/Latte/Renderer/Vulkan/TextureReadbackVk.cpp
HW/Latte/Renderer/Vulkan/VKRBase.h
HW/Latte/Renderer/Vulkan/VKRMemoryManager.cpp
+2
View File
@@ -5,6 +5,7 @@
#include "Cafe/HW/Espresso/Interpreter/PPCInterpreterInternal.h"
#include "Cafe/HW/Espresso/Recompiler/PPCRecompiler.h"
#include "audio/IAudioAPI.h"
#include "audio/IAudioInputAPI.h"
#include "Cafe/HW/Espresso/Debugger/Debugger.h"
#include "config/ActiveSettings.h"
@@ -402,6 +403,7 @@ void cemu_initForGame()
GraphicPack2::ActivateForCurrentTitle();
// print audio log
IAudioAPI::PrintLogging();
IAudioInputAPI::PrintLogging();
// everything initialized
forceLog_printf("------- Run title -------");
// wait till GPU thread is initialized
@@ -352,14 +352,19 @@ void OpenGLRenderer::NotifyLatteCommandProcessorIdle()
glFlush();
}
void OpenGLRenderer::EnableVSync(int state)
void OpenGLRenderer::UpdateVSyncState()
{
int configValue = GetConfig().vsync.GetValue();
if(m_activeVSyncState != configValue)
{
#if BOOST_OS_WINDOWS
if(wglSwapIntervalEXT)
wglSwapIntervalEXT(state); // 1 = enabled, 0 = disabled
if(wglSwapIntervalEXT)
wglSwapIntervalEXT(configValue); // 1 = enabled, 0 = disabled
#else
cemuLog_log(LogType::Force, "OpenGL vsync not implemented");
cemuLog_log(LogType::Force, "OpenGL vsync not implemented");
#endif
m_activeVSyncState = configValue;
}
}
bool IsRunningInWine();
@@ -438,6 +443,7 @@ void OpenGLRenderer::EnableDebugMode()
void OpenGLRenderer::SwapBuffers(bool swapTV, bool swapDRC)
{
GLCanvas_SwapBuffers(swapTV, swapDRC);
UpdateVSyncState();
if (swapTV)
cleanupAfterFrame();
@@ -30,7 +30,7 @@ public:
void Flush(bool waitIdle = false) override;
void NotifyLatteCommandProcessorIdle() override;
void EnableVSync(int state) override;
void UpdateVSyncState();
void EnableDebugMode() override;
void SwapBuffers(bool swapTV = true, bool swapDRC = true) override;
@@ -168,6 +168,7 @@ private:
GLuint m_defaultFramebufferId;
GLuint m_pipeline = 0;
int m_activeVSyncState{};
bool m_isPadViewContext{};
// rendertarget viewport
@@ -282,4 +283,4 @@ private:
std::vector<bufferCacheReleaseQueueEntry_t> bufferCacheEntries;
}m_destructionQueues;
};
};
+1 -2
View File
@@ -58,7 +58,6 @@ public:
virtual bool GetVRAMInfo(int& usageInMB, int& totalInMB) const;
virtual void EnableDebugMode() {}
virtual void EnableVSync(int state) = 0;
virtual void ClearColorbuffer(bool padView) = 0;
virtual void DrawEmptyFrame(bool mainWindow) = 0;
@@ -176,4 +175,4 @@ protected:
#endif
};
extern std::unique_ptr<Renderer> g_renderer;
extern std::unique_ptr<Renderer> g_renderer;
@@ -0,0 +1,367 @@
#include "SwapchainInfoVk.h"
#include "config/CemuConfig.h"
#include "Cafe/HW/Latte/Core/Latte.h"
#include "Cafe/HW/Latte/Core/LatteTiming.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
void SwapchainInfoVk::Create(VkPhysicalDevice physicalDevice, VkDevice logicalDevice)
{
m_physicalDevice = physicalDevice;
m_logicalDevice = logicalDevice;
const auto details = QuerySwapchainSupport(surface, physicalDevice);
m_surfaceFormat = ChooseSurfaceFormat(details.formats);
swapchainExtent = ChooseSwapExtent(details.capabilities, getSize());
// calculate number of swapchain presentation images
uint32_t image_count = details.capabilities.minImageCount + 1;
if (details.capabilities.maxImageCount > 0 && image_count > details.capabilities.maxImageCount)
image_count = details.capabilities.maxImageCount;
VkSwapchainCreateInfoKHR create_info = CreateSwapchainCreateInfo(surface, details, m_surfaceFormat, image_count, swapchainExtent);
create_info.oldSwapchain = nullptr;
create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
VkResult result = vkCreateSwapchainKHR(logicalDevice, &create_info, nullptr, &swapchain);
if (result != VK_SUCCESS)
UnrecoverableError("Error attempting to create a swapchain");
sizeOutOfDate = false;
result = vkGetSwapchainImagesKHR(logicalDevice, swapchain, &image_count, nullptr);
if (result != VK_SUCCESS)
UnrecoverableError("Error attempting to retrieve the count of swapchain images");
m_swapchainImages.resize(image_count);
result = vkGetSwapchainImagesKHR(logicalDevice, swapchain, &image_count, m_swapchainImages.data());
if (result != VK_SUCCESS)
UnrecoverableError("Error attempting to retrieve swapchain images");
// create default renderpass
VkAttachmentDescription colorAttachment = {};
colorAttachment.format = m_surfaceFormat.format;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentReference colorAttachmentRef = {};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = &colorAttachment;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
result = vkCreateRenderPass(logicalDevice, &renderPassInfo, nullptr, &m_swapchainRenderPass);
if (result != VK_SUCCESS)
UnrecoverableError("Failed to create renderpass for swapchain");
// create swapchain image views
m_swapchainImageViews.resize(m_swapchainImages.size());
for (sint32 i = 0; i < m_swapchainImages.size(); i++)
{
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = m_swapchainImages[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = m_surfaceFormat.format;
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
result = vkCreateImageView(logicalDevice, &createInfo, nullptr, &m_swapchainImageViews[i]);
if (result != VK_SUCCESS)
UnrecoverableError("Failed to create imageviews for swapchain");
}
// create swapchain framebuffers
m_swapchainFramebuffers.resize(m_swapchainImages.size());
for (size_t i = 0; i < m_swapchainImages.size(); i++)
{
VkImageView attachments[1];
attachments[0] = m_swapchainImageViews[i];
// create framebuffer
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = m_swapchainRenderPass;
framebufferInfo.attachmentCount = 1;
framebufferInfo.pAttachments = attachments;
framebufferInfo.width = swapchainExtent.width;
framebufferInfo.height = swapchainExtent.height;
framebufferInfo.layers = 1;
result = vkCreateFramebuffer(logicalDevice, &framebufferInfo, nullptr, &m_swapchainFramebuffers[i]);
if (result != VK_SUCCESS)
UnrecoverableError("Failed to create framebuffer for swapchain");
}
m_swapchainPresentSemaphores.resize(m_swapchainImages.size());
// create present semaphore
VkSemaphoreCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
for (auto& semaphore : m_swapchainPresentSemaphores){
if (vkCreateSemaphore(logicalDevice, &info, nullptr, &semaphore) != VK_SUCCESS)
UnrecoverableError("Failed to create semaphore for swapchain present");
}
m_acquireSemaphores.resize(m_swapchainImages.size());
for (auto& semaphore : m_acquireSemaphores)
{
VkSemaphoreCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
if (vkCreateSemaphore(logicalDevice, &info, nullptr, &semaphore) != VK_SUCCESS)
UnrecoverableError("Failed to create semaphore for swapchain acquire");
}
m_acquireIndex = 0;
VkFenceCreateInfo fenceInfo = {};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
result = vkCreateFence(logicalDevice, &fenceInfo, nullptr, &m_imageAvailableFence);
if (result != VK_SUCCESS)
UnrecoverableError("Failed to create fence for swapchain");
}
void SwapchainInfoVk::Cleanup()
{
m_swapchainImages.clear();
for (auto& sem: m_swapchainPresentSemaphores)
vkDestroySemaphore(m_logicalDevice, sem, nullptr);
m_swapchainPresentSemaphores.clear();
for (auto& itr: m_acquireSemaphores)
vkDestroySemaphore(m_logicalDevice, itr, nullptr);
m_acquireSemaphores.clear();
if (m_swapchainRenderPass)
{
vkDestroyRenderPass(m_logicalDevice, m_swapchainRenderPass, nullptr);
m_swapchainRenderPass = nullptr;
}
for (auto& imageView : m_swapchainImageViews)
vkDestroyImageView(m_logicalDevice, imageView, nullptr);
m_swapchainImageViews.clear();
for (auto& framebuffer : m_swapchainFramebuffers)
vkDestroyFramebuffer(m_logicalDevice, framebuffer, nullptr);
m_swapchainFramebuffers.clear();
if (m_imageAvailableFence)
{
vkDestroyFence(m_logicalDevice, m_imageAvailableFence, nullptr);
m_imageAvailableFence = nullptr;
}
if (swapchain)
{
vkDestroySwapchainKHR(m_logicalDevice, swapchain, nullptr);
swapchain = VK_NULL_HANDLE;
}
}
bool SwapchainInfoVk::IsValid() const
{
return swapchain && m_imageAvailableFence;
}
void SwapchainInfoVk::UnrecoverableError(const char* errMsg)
{
forceLog_printf("Unrecoverable error in Vulkan swapchain");
forceLog_printf("Msg: %s", errMsg);
throw std::runtime_error(errMsg);
}
SwapchainInfoVk::QueueFamilyIndices SwapchainInfoVk::FindQueueFamilies(VkSurfaceKHR surface, VkPhysicalDevice device)
{
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
QueueFamilyIndices indices;
for (int i = 0; i < (int)queueFamilies.size(); ++i)
{
const auto& queueFamily = queueFamilies[i];
if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
indices.graphicsFamily = i;
VkBool32 presentSupport = false;
const VkResult result = vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
if (result != VK_SUCCESS)
throw std::runtime_error(fmt::format("Error while attempting to check if a surface supports presentation: {}", result));
if (queueFamily.queueCount > 0 && presentSupport)
indices.presentFamily = i;
if (indices.IsComplete())
break;
}
return indices;
}
SwapchainInfoVk::SwapchainSupportDetails SwapchainInfoVk::QuerySwapchainSupport(VkSurfaceKHR surface, const VkPhysicalDevice& device)
{
SwapchainSupportDetails details;
VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
if (result != VK_SUCCESS)
{
if (result != VK_ERROR_SURFACE_LOST_KHR)
forceLog_printf("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed. Error %d", (sint32)result);
throw std::runtime_error(fmt::format("Unable to retrieve physical device surface capabilities: {}", result));
}
uint32_t formatCount = 0;
result = vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
if (result != VK_SUCCESS)
{
forceLog_printf("vkGetPhysicalDeviceSurfaceFormatsKHR failed. Error %d", (sint32)result);
throw std::runtime_error(fmt::format("Unable to retrieve the number of formats for a surface on a physical device: {}", result));
}
if (formatCount != 0)
{
details.formats.resize(formatCount);
result = vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());
if (result != VK_SUCCESS)
{
forceLog_printf("vkGetPhysicalDeviceSurfaceFormatsKHR failed. Error %d", (sint32)result);
throw std::runtime_error(fmt::format("Unable to retrieve the formats for a surface on a physical device: {}", result));
}
}
uint32_t presentModeCount = 0;
result = vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
if (result != VK_SUCCESS)
{
forceLog_printf("vkGetPhysicalDeviceSurfacePresentModesKHR failed. Error %d", (sint32)result);
throw std::runtime_error(fmt::format("Unable to retrieve the count of present modes for a surface on a physical device: {}", result));
}
if (presentModeCount != 0)
{
details.presentModes.resize(presentModeCount);
result = vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());
if (result != VK_SUCCESS)
{
forceLog_printf("vkGetPhysicalDeviceSurfacePresentModesKHR failed. Error %d", (sint32)result);
throw std::runtime_error(fmt::format("Unable to retrieve the present modes for a surface on a physical device: {}", result));
}
}
return details;
}
VkSurfaceFormatKHR SwapchainInfoVk::ChooseSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& formats) const
{
if (formats.size() == 1 && formats[0].format == VK_FORMAT_UNDEFINED)
return{ VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
for (const auto& format : formats)
{
bool useSRGB = mainWindow ? LatteGPUState.tvBufferUsesSRGB : LatteGPUState.drcBufferUsesSRGB;
if (useSRGB)
{
if (format.format == VK_FORMAT_B8G8R8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
return format;
}
else
{
if (format.format == VK_FORMAT_B8G8R8A8_UNORM && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
return format;
}
}
return formats[0];
}
VkExtent2D SwapchainInfoVk::ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, const Vector2i& size) const
{
if (capabilities.currentExtent.width != std::numeric_limits<uint32>::max())
return capabilities.currentExtent;
VkExtent2D actualExtent = { (uint32)size.x, (uint32)size.y };
actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width));
actualExtent.height = std::max(capabilities.minImageExtent.height, std::min(capabilities.maxImageExtent.height, actualExtent.height));
return actualExtent;
}
VkPresentModeKHR SwapchainInfoVk::ChoosePresentMode(const std::vector<VkPresentModeKHR>& modes)
{
const auto vsyncState = (VSync)GetConfig().vsync.GetValue();
if (vsyncState == VSync::MAILBOX)
{
if (std::find(modes.cbegin(), modes.cend(), VK_PRESENT_MODE_MAILBOX_KHR) != modes.cend())
return VK_PRESENT_MODE_MAILBOX_KHR;
forceLog_printf("Vulkan: Can't find mailbox present mode");
}
else if (vsyncState == VSync::Immediate)
{
if (std::find(modes.cbegin(), modes.cend(), VK_PRESENT_MODE_IMMEDIATE_KHR) != modes.cend())
return VK_PRESENT_MODE_IMMEDIATE_KHR;
forceLog_printf("Vulkan: Can't find immediate present mode");
}
else if (vsyncState == VSync::SYNC_AND_LIMIT)
{
LatteTiming_EnableHostDrivenVSync();
// use immediate mode if available, other wise fall back to
//if (std::find(modes.cbegin(), modes.cend(), VK_PRESENT_MODE_IMMEDIATE_KHR) != modes.cend())
// return VK_PRESENT_MODE_IMMEDIATE_KHR;
//else
// forceLog_printf("Vulkan: Present mode 'immediate' not available. Vsync might not behave as intended");
return VK_PRESENT_MODE_FIFO_KHR;
}
return VK_PRESENT_MODE_FIFO_KHR;
}
VkSwapchainCreateInfoKHR SwapchainInfoVk::CreateSwapchainCreateInfo(VkSurfaceKHR surface, const SwapchainSupportDetails& swapchainSupport, const VkSurfaceFormatKHR& surfaceFormat, uint32 imageCount, const VkExtent2D& extent)
{
VkSwapchainCreateInfoKHR createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = surface;
createInfo.minImageCount = imageCount;
createInfo.imageFormat = surfaceFormat.format;
createInfo.imageExtent = extent;
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
const QueueFamilyIndices indices = FindQueueFamilies(surface, m_physicalDevice);
uint32_t queueFamilyIndices[] = { (uint32)indices.graphicsFamily, (uint32)indices.presentFamily };
if (indices.graphicsFamily != indices.presentFamily)
{
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
createInfo.queueFamilyIndexCount = 2;
createInfo.pQueueFamilyIndices = queueFamilyIndices;
}
else
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.preTransform = swapchainSupport.capabilities.currentTransform;
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createInfo.presentMode = ChoosePresentMode(swapchainSupport.presentModes);
createInfo.clipped = VK_TRUE;
forceLogDebug_printf("vulkan presentation mode: %d", createInfo.presentMode);
return createInfo;
}
@@ -0,0 +1,101 @@
#pragma once
#include "util/math/vector2.h"
#include <vulkan/vulkan_core.h>
struct SwapchainInfoVk
{
enum class VSync
{
// values here must match GeneralSettings2::m_vsync
Immediate = 0,
FIFO = 1,
MAILBOX = 2,
SYNC_AND_LIMIT = 3, // synchronize emulated vsync events to monitor vsync. But skip events if rate higher than virtual vsync period
};
struct QueueFamilyIndices
{
int32_t graphicsFamily = -1;
int32_t presentFamily = -1;
bool IsComplete() const { return graphicsFamily >= 0 && presentFamily >= 0; }
};
struct SwapchainSupportDetails
{
VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
};
void Cleanup();
void Create(VkPhysicalDevice physicalDevice, VkDevice logicalDevice);
bool IsValid() const;
static void UnrecoverableError(const char* errMsg);
// todo: move this function somewhere more sensible. Not directly swapchain related
static QueueFamilyIndices FindQueueFamilies(VkSurfaceKHR surface, VkPhysicalDevice device);
static SwapchainSupportDetails QuerySwapchainSupport(VkSurfaceKHR surface, const VkPhysicalDevice& device);
VkPresentModeKHR ChoosePresentMode(const std::vector<VkPresentModeKHR>& modes);
VkSurfaceFormatKHR ChooseSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& formats) const;
VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, const Vector2i& size) const;
VkSwapchainCreateInfoKHR CreateSwapchainCreateInfo(VkSurfaceKHR surface, const SwapchainSupportDetails& swapchainSupport, const VkSurfaceFormatKHR& surfaceFormat, uint32 imageCount, const VkExtent2D& extent);
void setSize(const Vector2i& newSize)
{
desiredExtent = newSize;
sizeOutOfDate = true;
}
const Vector2i& getSize() const
{
return desiredExtent;
}
SwapchainInfoVk(VkSurfaceKHR surface, bool mainWindow)
: surface(surface), mainWindow(mainWindow) {}
SwapchainInfoVk(const SwapchainInfoVk&) = delete;
SwapchainInfoVk(SwapchainInfoVk&&) noexcept = default;
~SwapchainInfoVk()
{
Cleanup();
}
bool mainWindow{};
bool sizeOutOfDate{};
bool m_usesSRGB = false;
bool hasDefinedSwapchainImage{}; // indicates if the swapchain image is in a defined state
VkPhysicalDevice m_physicalDevice{};
VkDevice m_logicalDevice{};
VkSurfaceKHR surface{};
VkSurfaceFormatKHR m_surfaceFormat{};
VkSwapchainKHR swapchain{};
VkExtent2D swapchainExtent{};
VkFence m_imageAvailableFence{};
uint32 swapchainImageIndex = (uint32)-1;
uint32 m_acquireIndex = 0; // increases with every successful vkAcquireNextImageKHR
VSync m_vsyncState = VSync::Immediate;
// swapchain image ringbuffer (indexed by swapchainImageIndex)
std::vector<VkImage> m_swapchainImages;
std::vector<VkImageView> m_swapchainImageViews;
std::vector<VkFramebuffer> m_swapchainFramebuffers;
std::vector<VkSemaphore> m_swapchainPresentSemaphores;
std::vector<VkSemaphore> m_acquireSemaphores; // indexed by acquireIndex
VkRenderPass m_swapchainRenderPass = nullptr;
private:
Vector2i desiredExtent;
};
@@ -457,6 +457,12 @@ void PipelineCompiler::InitVertexInputState(const LatteContextRegister& latteReg
uint32 bufferStride = (latteRegister.GetRawView()[bufferBaseRegisterIndex + 2] >> 11) & 0xFFFF;
VkVertexInputBindingDescription entry{};
#if BOOST_OS_MACOS
if (bufferStride % 4 != 0) {
forceLog_printf("MoltenVK error: vertex stride was %d, expected multiple of 4", bufferStride);
bufferStride = 0;
}
#endif
entry.stride = bufferStride;
if (!fetchType.has_value() || fetchType == LatteConst::VertexFetchType2::VERTEX_DATA)
entry.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
File diff suppressed because it is too large Load Diff
@@ -1,4 +1,5 @@
#pragma once
#include "Cafe/HW/Latte/Renderer/Renderer.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h"
@@ -6,6 +7,7 @@
#include "Cafe/HW/Latte/Renderer/Vulkan/LatteTextureViewVk.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/CachedFBOVk.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/VKRMemoryManager.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/SwapchainInfoVk.h"
#include "util/math/vector2.h"
#include "util/helpers/Semaphore.h"
#include "util/containers/flat_hash_map.hpp"
@@ -124,6 +126,9 @@ class VulkanRenderer : public Renderer
friend class LatteTextureReadbackInfoVk;
friend class PipelineCompiler;
using VSync = SwapchainInfoVk::VSync;
using QueueFamilyIndices = SwapchainInfoVk::QueueFamilyIndices;
static const inline int UNIFORMVAR_RINGBUFFER_SIZE = 1024 * 1024 * 16; // 16MB
static const inline int INDEX_STREAM_BUFFER_SIZE = 16 * 1024 * 1024; // 16 MB
@@ -132,15 +137,7 @@ class VulkanRenderer : public Renderer
static const inline int OCCLUSION_QUERY_POOL_SIZE = 1024;
public:
enum class VSync
{
// values here must match GeneralSettings2::m_vsync
Immediate = 0,
FIFO = 1,
MAILBOX = 2,
SYNC_AND_LIMIT = 3, // synchronize emulated vsync events to monitor vsync. But skip events if rate higher than virtual vsync period
};
// memory management
VKRMemoryManager* memoryManager{};
VKRMemoryManager* GetMemoryManager() const { return memoryManager; };
@@ -185,18 +182,20 @@ public:
void GetDeviceFeatures();
void DetermineVendor();
void Initialize(const Vector2i& size, bool isMainWindow);
void Initialize(const Vector2i& size, bool mainWindow);
const std::unique_ptr<SwapchainInfoVk>& GetChainInfoPtr(bool mainWindow) const;
SwapchainInfoVk& GetChainInfo(bool mainWindow) const;
void StopUsingPadAndWait();
bool IsPadWindowActive() override;
void HandleScreenshotRequest(LatteTextureView* texView, bool padView) override;
void ResizeSwapchain(const Vector2i& size, bool isMainWindow);
void SetSwapchainTargetSize(const Vector2i& size, bool mainWindow);
void QueryMemoryInfo();
void QueryAvailableFormats();
void EnableVSync(int state) override;
#if BOOST_OS_WINDOWS
static VkSurfaceKHR CreateWinSurface(VkInstance instance, HWND hwindow);
#endif
@@ -212,7 +211,7 @@ public:
void ImguiInit();
VkInstance GetVkInstance() const { return m_instance; }
VkDevice GetLogicalDevice() const { return m_logicalDevice; }
VkPhysicalDevice GetPhysicalDevice() const { return m_physical_device; }
VkPhysicalDevice GetPhysicalDevice() const { return m_physicalDevice; }
VkDescriptorPool GetDescriptorPool() const { return m_descriptorPool; }
@@ -433,85 +432,14 @@ private:
bool drawSequenceSkip; // if true, skip draw_execute()
}m_state;
// swapchain - todo move this to m_swapchainState
struct SwapChainInfo
{
SwapChainInfo(VkDevice device, VkSurfaceKHR surface) : m_device(device), surface(surface) {}
SwapChainInfo(const SwapChainInfo&) = delete;
SwapChainInfo(SwapChainInfo&&) noexcept = default;
~SwapChainInfo()
{
if (m_swapChainRenderPass)
{
vkDestroyRenderPass(m_device, m_swapChainRenderPass, nullptr);
m_swapChainRenderPass = VK_NULL_HANDLE;
}
if (swapChain)
{
vkDestroySwapchainKHR(m_device, swapChain, nullptr);
swapChain = VK_NULL_HANDLE;
}
for (auto& imageView : m_swapchainImageViews)
vkDestroyImageView(m_device, imageView, nullptr);
m_swapchainImageViews.clear();
for (auto& framebuffer : m_swapchainFramebuffers)
vkDestroyFramebuffer(m_device, framebuffer, nullptr);
m_swapchainFramebuffers.clear();
}
VkDevice m_device;
VkSurfaceKHR surface{};
VkSwapchainKHR swapChain{};
VkExtent2D swapchainExtend{};
uint32 swapchainImageIndex = (uint32)-1;
uint32 m_acquireIndex = 0; // increases with every successful vkAcquireNextImageKHR
struct AcquireInfo
{
// move fence here?
VkSemaphore acquireSemaphore;
};
std::vector<AcquireInfo> m_acquireInfo; // indexed by acquireIndex
// swapchain image ringbuffer (indexed by swapchainImageIndex)
std::vector<VkImage> m_swapchainImages;
std::vector<VkImageView> m_swapchainImageViews;
std::vector<VkFramebuffer> m_swapchainFramebuffers;
std::vector<VkSemaphore> m_swapchainPresentSemaphores;
VkFence m_imageAvailableFence = nullptr;
VkRenderPass m_swapChainRenderPass = nullptr;
VkRenderPass m_imguiRenderPass = nullptr;
};
std::unique_ptr<SwapChainInfo> m_mainSwapchainInfo{}, m_padSwapchainInfo{};
std::unique_ptr<SwapchainInfoVk> m_mainSwapchainInfo{}, m_padSwapchainInfo{};
Semaphore m_padCloseReadySemaphore;
bool m_destroyPadSwapchainNextAcquire = false;
bool IsSwapchainInfoValid(bool mainWindow) const;
VkSwapchainKHR CreateSwapChain(SwapChainInfo& swap_chain_info, const Vector2i& size, bool mainwindow);
struct
{
bool resizeRequestedMainWindow{};
Vector2i newExtentMainWindow;
bool resizeRequestedPadWindow{};
Vector2i newExtentPadWindow;
bool tvHasDefinedSwapchainImage{}; // indicates if the swapchain image is in a defined state
bool drcHasDefinedSwapchainImage{};
}m_swapchainState;
VkRenderPass m_imguiRenderPass = nullptr;
VkDescriptorPool m_descriptorPool;
VkSurfaceFormatKHR m_swapchainFormat;
bool m_tvBufferUsesSRGB = false;
bool m_drvBufferUsesSRGB = false;
struct QueueFamilyIndices
{
int32_t graphicsFamily = -1;
int32_t presentFamily = -1;
bool IsComplete() const { return graphicsFamily >= 0 && presentFamily >= 0; }
};
static QueueFamilyIndices FindQueueFamilies(VkSurfaceKHR surface, const VkPhysicalDevice& device);
struct FeatureControl
{
@@ -557,15 +485,8 @@ private:
static bool CheckDeviceExtensionSupport(const VkPhysicalDevice device, FeatureControl& info);
static std::vector<const char*> CheckInstanceExtensionSupport(FeatureControl& info);
void SwapBuffer(bool main_window);
VSync m_vsync_state = VSync::Immediate;
struct SwapChainSupportDetails
{
VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
};
void UpdateVSyncState(bool mainWindow);
void SwapBuffer(bool mainWindow);
VkDescriptorSetLayout m_swapchainDescriptorSetLayout;
@@ -573,14 +494,9 @@ private:
// swapchain
static SwapChainSupportDetails QuerySwapChainSupport(VkSurfaceKHR surface, const VkPhysicalDevice& device);
std::vector<VkDeviceQueueCreateInfo> CreateQueueCreateInfos(const std::set<int>& uniqueQueueFamilies) const;
VkDeviceCreateInfo CreateDeviceCreateInfo(const std::vector<VkDeviceQueueCreateInfo>& queueCreateInfos, const VkPhysicalDeviceFeatures& deviceFeatures, const void* deviceExtensionStructs, std::vector<const char*>& used_extensions) const;
static bool IsDeviceSuitable(VkSurfaceKHR surface, const VkPhysicalDevice& device);
VkSurfaceFormatKHR ChooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& formats, bool mainWindow) const;
VkPresentModeKHR ChooseSwapPresentMode(const std::vector<VkPresentModeKHR>& modes);
VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, const Vector2i& size) const;
VkSwapchainCreateInfoKHR CreateSwapchainCreateInfo(VkSurfaceKHR surface, const SwapChainSupportDetails& swapChainSupport, const VkSurfaceFormatKHR& surfaceFormat, uint32 imageCount, const VkExtent2D& extent);
void CreateCommandPool();
void CreateCommandBuffers();
@@ -642,8 +558,8 @@ private:
void CreatePipelineCache();
VkPipelineShaderStageCreateInfo CreatePipelineShaderStageCreateInfo(VkShaderStageFlagBits stage, VkShaderModule& module, const char* entryName) const;
VkPipeline backbufferBlit_createGraphicsPipeline(VkDescriptorSetLayout descriptorLayout, bool padView, RendererOutputShader* shader);
void AcquireNextSwapchainImage(bool main_window);
void RecreateSwapchain(bool mainwindow);
bool AcquireNextSwapchainImage(bool mainWindow);
void RecreateSwapchain(bool mainWindow, bool skipCreate = false);
// streamout
void streamout_setupXfbBuffer(uint32 bufferIndex, sint32 ringBufferOffset, uint32 rangeAddr, uint32 rangeSize) override;
@@ -666,7 +582,7 @@ private:
std::vector<const char*> m_layerNames;
VkInstance m_instance = VK_NULL_HANDLE;
VkPhysicalDevice m_physical_device = VK_NULL_HANDLE;
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
VkDevice m_logicalDevice = VK_NULL_HANDLE;
VkDebugUtilsMessengerEXT m_debugCallback = nullptr;
volatile bool m_destructionRequested = false;
@@ -1196,30 +1196,15 @@ void VulkanRenderer::draw_setRenderPass()
// update self-dependency flag
if (m_state.descriptorSetsChanged || m_state.activeRenderpassFBO != fboVk)
{
bool hadDep = m_state.hasRenderSelfDependency;
m_state.hasRenderSelfDependency = fboVk->CheckForCollision(m_state.activeVertexDS, m_state.activeGeometryDS, m_state.activePixelDS);
}
auto vkObjRenderPass = fboVk->GetRenderPassObj();
auto vkObjFramebuffer = fboVk->GetFramebufferObj();
if (m_state.hasRenderSelfDependency)
{
bool triggerBarrier = GetConfig().vk_accurate_barriers || m_state.activePipelineInfo->neverSkipAccurateBarrier;
if (triggerBarrier)
{
VkMemoryBarrier memoryBarrier{};
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
vkCmdPipelineBarrier(m_state.currentCommandBuffer, srcStage, dstStage, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
performanceMonitor.vk.numDrawBarriersPerFrame.increment();
}
}
bool overridePassReuse = m_state.hasRenderSelfDependency && (GetConfig().vk_accurate_barriers || m_state.activePipelineInfo->neverSkipAccurateBarrier);
if (m_state.activeRenderpassFBO == fboVk)
if (!overridePassReuse && m_state.activeRenderpassFBO == fboVk)
{
if (m_state.descriptorSetsChanged)
sync_inputTexturesChanged();
+1 -1
View File
@@ -273,7 +273,7 @@ void iosuCrypto_generateDeviceCertificate()
BIGNUM* bn_x = BN_CTX_get(context);
BIGNUM* bn_y = BN_CTX_get(context);
EC_POINT_get_affine_coordinates_GF2m(group, pubkey, bn_x, bn_y, NULL);
EC_POINT_get_affine_coordinates(group, pubkey, bn_x, bn_y, NULL);
uint8 publicKeyOutput[0x3C];
memset(publicKeyOutput, 0, sizeof(publicKeyOutput));
+78 -13
View File
@@ -1,5 +1,7 @@
#include "Cafe/OS/common/OSCommon.h"
#include "input/InputManager.h"
#include "audio/IAudioInputAPI.h"
#include "config/CemuConfig.h"
enum class MIC_RESULT
{
@@ -13,6 +15,7 @@ enum class MIC_RESULT
#define MIC_SAMPLERATE 32000
const int MIC_SAMPLES_PER_3MS_32KHZ = (96); // 32000*3/1000
enum class MIC_STATUS_FLAGS : uint32
{
@@ -22,8 +25,8 @@ enum class MIC_STATUS_FLAGS : uint32
};
DEFINE_ENUM_FLAG_OPERATORS(MIC_STATUS_FLAGS);
#define MIC_HANDLE_DRC0 100
#define MIC_HANDLE_DRC1 101
#define MIC_HANDLE_DRC0 0
#define MIC_HANDLE_DRC1 1
enum class MIC_STATEID
{
@@ -139,6 +142,36 @@ void micExport_MICInit(PPCInterpreter_t* hCPU)
// return status
memory_writeU32(hCPU->gpr[6], 0); // no error
osLib_returnFromFunction(hCPU, (drcIndex==0)?MIC_HANDLE_DRC0:MIC_HANDLE_DRC1); // success
auto& config = GetConfig();
const auto audio_api = IAudioInputAPI::Cubeb; // change this if more input apis get implemented
std::unique_lock lock(g_audioInputMutex);
if (!g_inputAudio)
{
IAudioInputAPI::DeviceDescriptionPtr device_description;
if (IAudioInputAPI::IsAudioInputAPIAvailable(audio_api))
{
auto devices = IAudioInputAPI::GetDevices(audio_api);
const auto it = std::find_if(devices.begin(), devices.end(), [&config](const auto& d) {return d->GetIdentifier() == config.input_device; });
if (it != devices.end())
device_description = *it;
}
if (device_description)
{
try
{
g_inputAudio = IAudioInputAPI::CreateDevice(audio_api, device_description, MIC_SAMPLERATE, 1, MIC_SAMPLES_PER_3MS_32KHZ, 16);
g_inputAudio->SetVolume(config.input_volume);
}
catch (std::runtime_error& ex)
{
forceLog_printf("can't initialize audio input: %s", ex.what());
exit(0);
}
}
}
}
void micExport_MICOpen(PPCInterpreter_t* hCPU)
@@ -172,6 +205,10 @@ void micExport_MICOpen(PPCInterpreter_t* hCPU)
// success
MICStatus.drc[drcIndex].isOpen = true;
osLib_returnFromFunction(hCPU, (uint32)MIC_RESULT::SUCCESS);
std::shared_lock lock(g_audioInputMutex);
if(g_inputAudio)
g_inputAudio->Play();
}
void micExport_MICClose(PPCInterpreter_t* hCPU)
@@ -198,6 +235,10 @@ void micExport_MICClose(PPCInterpreter_t* hCPU)
// success
MICStatus.drc[drcIndex].isOpen = false;
osLib_returnFromFunction(hCPU, (uint32)MIC_RESULT::SUCCESS);
std::shared_lock lock(g_audioInputMutex);
if (g_inputAudio)
g_inputAudio->Stop();
}
void micExport_MICGetStatus(PPCInterpreter_t* hCPU)
@@ -360,6 +401,17 @@ void micExport_MICSetDataConsumed(PPCInterpreter_t* hCPU)
return;
}
void mic_updateDevicePlayState(bool isPlaying)
{
if (g_inputAudio)
{
if (isPlaying)
g_inputAudio->Play();
else
g_inputAudio->Stop();
}
}
void mic_updateOnAXFrame()
{
sint32 drcIndex = 0;
@@ -368,26 +420,39 @@ void mic_updateOnAXFrame()
drcIndex = 1;
if (mic_isActive(1) == false)
{
std::shared_lock lock(g_audioInputMutex);
mic_updateDevicePlayState(false);
return;
}
}
const sint32 micSampleCount = 32000/32;
sint16 micSampleData[micSampleCount];
auto controller = InputManager::instance().get_vpad_controller(drcIndex);
if( controller && controller->is_mic_active() )
std::shared_lock lock(g_audioInputMutex);
mic_updateDevicePlayState(true);
if (g_inputAudio)
{
for(sint32 i=0; i<micSampleCount; i++)
{
micSampleData[i] = (sint16)(sin((float)GetTickCount()*0.1f+sin((float)GetTickCount()*0.0001f)*100.0f)*30000.0f);
}
sint16 micSampleData[MIC_SAMPLES_PER_3MS_32KHZ];
g_inputAudio->ConsumeBlock(micSampleData);
mic_feedSamples(0, micSampleData, MIC_SAMPLES_PER_3MS_32KHZ);
}
else
{
memset(micSampleData, 0x00, sizeof(micSampleData));
const sint32 micSampleCount = 32000 / 32;
sint16 micSampleData[micSampleCount];
auto controller = InputManager::instance().get_vpad_controller(drcIndex);
if( controller && controller->is_mic_active() )
{
for(sint32 i=0; i<micSampleCount; i++)
{
micSampleData[i] = (sint16)(sin((float)GetTickCount()*0.1f+sin((float)GetTickCount()*0.0001f)*100.0f)*30000.0f);
}
}
else
{
memset(micSampleData, 0x00, sizeof(micSampleData));
}
mic_feedSamples(0, micSampleData, micSampleCount);
}
mic_feedSamples(0, micSampleData, micSampleCount);
}
namespace mic
+1 -1
View File
@@ -550,7 +550,7 @@ namespace NCrypto
EC_POINT_mul(group, pubkey, bn_privKey, NULL, NULL, NULL);
BIGNUM* bn_x = BN_new();
BIGNUM* bn_y = BN_new();
EC_POINT_get_affine_coordinates_GF2m(group, pubkey, bn_x, bn_y, NULL);
EC_POINT_get_affine_coordinates(group, pubkey, bn_x, bn_y, NULL);
// store public key
ECCPubKey genPubKey;

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