From aacbc4e675f89617db419df12d556fff2a9209a5 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Fri, 15 Sep 2023 23:13:49 +0300 Subject: [PATCH 01/32] Initial sceVideoOutRegisterBuffers function (added ErrorCodes returns) --- src/Core/PS4/HLE/ErrorCodes.h | 16 ++++++---- src/Core/PS4/HLE/Graphics/video_out.cpp | 42 +++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/Core/PS4/HLE/ErrorCodes.h b/src/Core/PS4/HLE/ErrorCodes.h index 04edb64e..50014a29 100644 --- a/src/Core/PS4/HLE/ErrorCodes.h +++ b/src/Core/PS4/HLE/ErrorCodes.h @@ -9,9 +9,13 @@ constexpr int SCE_KERNEL_ERROR_EAGAIN = 0x80020023; // Memory cannot be a constexpr int SCE_KERNEL_ERROR_ENAMETOOLONG = 0x8002003f; // character strings exceeds valid size // videoOut -constexpr int SCE_VIDEO_OUT_ERROR_INVALID_VALUE = 0x80290001; // invalid argument -constexpr int SCE_VIDEO_OUT_ERROR_RESOURCE_BUSY = 0x80290009; // already opened -constexpr int SCE_VIDEO_OUT_ERROR_INVALID_INDEX = 0x8029000A; // invalid buffer index -constexpr int SCE_VIDEO_OUT_ERROR_INVALID_HANDLE = 0x8029000B; // invalid handle -constexpr int SCE_VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE = 0x8029000C; // Invalid event queue -constexpr int SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL = 0x80290012; // flip queue is full +constexpr int SCE_VIDEO_OUT_ERROR_INVALID_VALUE = 0x80290001; // invalid argument +constexpr int SCE_VIDEO_OUT_ERROR_INVALID_ADDRESS = 0x80290002; // invalid addresses +constexpr int SCE_VIDEO_OUT_ERROR_INVALID_TILING_MODE = 0x80290007; // invalid tiling mode +constexpr int SCE_VIDEO_OUT_ERROR_INVALID_ASPECT_RATIO = 0x80290008; // invalid aspect ration +constexpr int SCE_VIDEO_OUT_ERROR_RESOURCE_BUSY = 0x80290009; // already opened +constexpr int SCE_VIDEO_OUT_ERROR_INVALID_INDEX = 0x8029000A; // invalid buffer index +constexpr int SCE_VIDEO_OUT_ERROR_INVALID_HANDLE = 0x8029000B; // invalid handle +constexpr int SCE_VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE = 0x8029000C; // Invalid event queue +constexpr int SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL = 0x80290012; // flip queue is full +constexpr int SCE_VIDEO_OUT_ERROR_INVALID_OPTION = 0x8029001A; // Invalid buffer attribute option diff --git a/src/Core/PS4/HLE/Graphics/video_out.cpp b/src/Core/PS4/HLE/Graphics/video_out.cpp index a9356b3f..56d006ee 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.cpp +++ b/src/Core/PS4/HLE/Graphics/video_out.cpp @@ -115,8 +115,46 @@ s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(LibKernel::EventQueues::SceKernelEqueue s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* const* addresses, s32 bufferNum, const SceVideoOutBufferAttribute* attribute) { - // BREAKPOINT(); - PRINT_DUMMY_FUNCTION_NAME(); + PRINT_FUNCTION_NAME(); + auto* videoOut = Singleton::Instance(); + auto* ctx = videoOut->getCtx(handle); + + if (handle == 1) { // main port + if (startIndex < 0 || startIndex > 15) { + LOG_TRACE_IF(log_file_videoout, "invalid startIndex = {}\n", startIndex); + return SCE_VIDEO_OUT_ERROR_INVALID_VALUE; + } + if (bufferNum < 1 || bufferNum > 16) { + LOG_TRACE_IF(log_file_videoout, "invalid bufferNum = {}\n", bufferNum); + return SCE_VIDEO_OUT_ERROR_INVALID_VALUE; + } + } + if (addresses == nullptr) { + LOG_TRACE_IF(log_file_videoout, "addresses are null\n"); + return SCE_VIDEO_OUT_ERROR_INVALID_ADDRESS; + } + + if (attribute == nullptr) { + LOG_TRACE_IF(log_file_videoout, "attribute is null\n"); + return SCE_VIDEO_OUT_ERROR_INVALID_OPTION; + } + if (attribute->aspectRatio != 0) { + LOG_TRACE_IF(log_file_videoout, "invalid aspect ratio = {}\n", attribute->aspectRatio); + return SCE_VIDEO_OUT_ERROR_INVALID_ASPECT_RATIO; + } + if (attribute->tilingMode != 0 || attribute->tilingMode != 1) { + LOG_TRACE_IF(log_file_videoout, "invalid tilingMode = {}\n", attribute->tilingMode); + return SCE_VIDEO_OUT_ERROR_INVALID_TILING_MODE; + } + LOG_INFO_IF(log_file_videoout, "startIndex = {}\n", startIndex); + LOG_INFO_IF(log_file_videoout, "bufferNum = {}\n", bufferNum); + LOG_INFO_IF(log_file_videoout, "pixelFormat = {}\n", log_hex_full(attribute->pixelFormat)); + LOG_INFO_IF(log_file_videoout, "tilingMode = {}\n", attribute->tilingMode); + LOG_INFO_IF(log_file_videoout, "aspectRatio = {}\n", attribute->aspectRatio); + LOG_INFO_IF(log_file_videoout, "width = {}\n", attribute->width); + LOG_INFO_IF(log_file_videoout, "height = {}\n", attribute->height); + LOG_INFO_IF(log_file_videoout, "pitchInPixel = {}\n", attribute->pitchInPixel); + LOG_INFO_IF(log_file_videoout, "option = {}\n", attribute->option); return 0; } s32 PS4_SYSV_ABI sceVideoOutSetFlipRate(s32 handle, s32 rate) { From 243c0158c1af99c742d0681b98e8a787e951ada8 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sat, 16 Sep 2023 00:03:11 +0300 Subject: [PATCH 02/32] more to buffers --- src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h | 2 ++ src/Core/PS4/HLE/Graphics/video_out.cpp | 12 +++++++++++- src/emulator.cpp | 8 +++++++- src/emulator.h | 1 + 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h index 1017fbc0..8adf22ef 100644 --- a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h +++ b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h @@ -16,6 +16,8 @@ struct VideoConfigInternal { SceVideoOutVblankStatus m_vblank_status; std::vector m_flip_evtEq; int m_flip_rate = 0; + + int buffers_registration_index = 0; }; class FlipQueue { diff --git a/src/Core/PS4/HLE/Graphics/video_out.cpp b/src/Core/PS4/HLE/Graphics/video_out.cpp index 56d006ee..6074bff0 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.cpp +++ b/src/Core/PS4/HLE/Graphics/video_out.cpp @@ -12,6 +12,7 @@ #include "Objects/video_out_ctx.h" #include "Util/Singleton.h" +#include namespace HLE::Libs::Graphics::VideoOut { @@ -155,7 +156,16 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co LOG_INFO_IF(log_file_videoout, "height = {}\n", attribute->height); LOG_INFO_IF(log_file_videoout, "pitchInPixel = {}\n", attribute->pitchInPixel); LOG_INFO_IF(log_file_videoout, "option = {}\n", attribute->option); - return 0; + + int registration_index = ctx->buffers_registration_index++; + + Emulator::checkAndWaitForGraphicsInit(); + + //try to calculate buffer size + u64 buffer_size = 1280 * 720 * 4; //TODO hardcore value should be redone + u64 buffer_pitch = attribute->pitchInPixel; + + return registration_index; } s32 PS4_SYSV_ABI sceVideoOutSetFlipRate(s32 handle, s32 rate) { PRINT_FUNCTION_NAME(); diff --git a/src/emulator.cpp b/src/emulator.cpp index 0fa5ca5d..98c3dae0 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -14,6 +14,13 @@ void emuInit(u32 width, u32 height) { g_window_ctx->m_graphic_ctx.screen_height = height; } +void checkAndWaitForGraphicsInit() { + Lib::LockMutexGuard lock(g_window_ctx->m_mutex); + + while (!g_window_ctx->m_is_graphic_initialized) { + g_window_ctx->m_graphic_initialized_cond.WaitCondVar(&g_window_ctx->m_mutex); + } +} static void CreateSdlWindow(WindowCtx* ctx) { int width = static_cast(ctx->m_graphic_ctx.screen_width); int height = static_cast(ctx->m_graphic_ctx.screen_height); @@ -34,7 +41,6 @@ static void CreateSdlWindow(WindowCtx* ctx) { } SDL_SetWindowResizable(ctx->m_window, SDL_FALSE); // we don't support resizable atm - SDL_ShowWindow(g_window_ctx->m_window); // TODO should be removed just left it over to make it fancy :D } void emuRun() { g_window_ctx->m_mutex.LockMutex(); diff --git a/src/emulator.h b/src/emulator.h index d86b1ef6..975b5330 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -24,4 +24,5 @@ struct EmuPrivate { }; void emuInit(u32 width, u32 height); void emuRun(); +void checkAndWaitForGraphicsInit(); } // namespace Emulator \ No newline at end of file From 74ac091b23285b43ff1a691905bdb237fc1bc122 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sat, 16 Sep 2023 10:50:10 +0300 Subject: [PATCH 03/32] added vulkan submodule --- .gitmodules | 4 ++++ third-party/vulkan | 1 + 2 files changed, 5 insertions(+) create mode 160000 third-party/vulkan diff --git a/.gitmodules b/.gitmodules index abb8fc02..9f2d7480 100644 --- a/.gitmodules +++ b/.gitmodules @@ -33,3 +33,7 @@ path = third-party/toml11 url = https://github.com/ToruNiina/toml11 branch = master +[submodule "third-party/vulkan"] + path = third-party/vulkan + url = https://github.com/shadps4/vulkan.git + branch = main diff --git a/third-party/vulkan b/third-party/vulkan new file mode 160000 index 00000000..b684e9e8 --- /dev/null +++ b/third-party/vulkan @@ -0,0 +1 @@ +Subproject commit b684e9e87614d64259a4b2c2253078c167377703 From e2b6c70f0a95e01d4f1311c4bf73f9e22ee01601 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sat, 16 Sep 2023 10:51:09 +0300 Subject: [PATCH 04/32] fixed vulkan compile --- CMakeLists.txt | 3 ++- src/Core/PS4/HLE/Graphics/video_out.cpp | 2 +- third-party/vulkan | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82488063..f46f0c79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ include_directories(third-party/fmt/include) include_directories(third-party/magic_enum/include) include_directories(third-party/zydis/include/Zydis) include_directories(third-party/winpthread/include) +include_directories(third-party/vulkan/include) add_subdirectory("third-party") #=================== EXAMPLE =================== include_directories(src) @@ -55,7 +56,7 @@ add_executable(shadps4 "src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h" "src/emulator.cpp" "src/emulator.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h" "src/Core/PS4/HLE/Graphics/graphics_ctx.h") find_package(OpenGL REQUIRED) -target_link_libraries(shadps4 PUBLIC fmt mincore spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY}) +target_link_libraries(shadps4 PUBLIC fmt mincore spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY} vulkan-1 spirv-tools-opt spirv-tools) add_custom_command(TARGET shadps4 POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different diff --git a/src/Core/PS4/HLE/Graphics/video_out.cpp b/src/Core/PS4/HLE/Graphics/video_out.cpp index 6074bff0..cc53b5e2 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.cpp +++ b/src/Core/PS4/HLE/Graphics/video_out.cpp @@ -162,7 +162,7 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co Emulator::checkAndWaitForGraphicsInit(); //try to calculate buffer size - u64 buffer_size = 1280 * 720 * 4; //TODO hardcore value should be redone + u64 buffer_size = 1280 * 720 * 4; //TODO hardcoded value should be redone u64 buffer_pitch = attribute->pitchInPixel; return registration_index; diff --git a/third-party/vulkan b/third-party/vulkan index b684e9e8..8c9feb4f 160000 --- a/third-party/vulkan +++ b/third-party/vulkan @@ -1 +1 @@ -Subproject commit b684e9e87614d64259a4b2c2253078c167377703 +Subproject commit 8c9feb4f480b32f7c7421af546aa6ffb558bdd5e From c081d6c73b095222b7a16160394287cba83d6c27 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sat, 16 Sep 2023 16:56:23 +0300 Subject: [PATCH 05/32] second try to fix vulkan Build --- third-party/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index a3ee0a2f..0b0db59c 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -33,6 +33,8 @@ add_subdirectory(winpthread) add_subdirectory(discord-rpc) #=================== toml11 =================== add_subdirectory(toml11) +#=================== vulkan ================== +add_subdirectory(vulkan) #=================== IMGUI =================== set(IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/imgui) From be4c88a3380e6692eaff8f2dc5a003459ae3a48d Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sat, 16 Sep 2023 23:05:57 +0300 Subject: [PATCH 06/32] fixed tiling mode checking --- src/Core/PS4/HLE/Graphics/video_out.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/PS4/HLE/Graphics/video_out.cpp b/src/Core/PS4/HLE/Graphics/video_out.cpp index cc53b5e2..c470df6f 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.cpp +++ b/src/Core/PS4/HLE/Graphics/video_out.cpp @@ -143,7 +143,7 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co LOG_TRACE_IF(log_file_videoout, "invalid aspect ratio = {}\n", attribute->aspectRatio); return SCE_VIDEO_OUT_ERROR_INVALID_ASPECT_RATIO; } - if (attribute->tilingMode != 0 || attribute->tilingMode != 1) { + if (attribute->tilingMode < 0 || attribute->tilingMode > 1) { LOG_TRACE_IF(log_file_videoout, "invalid tilingMode = {}\n", attribute->tilingMode); return SCE_VIDEO_OUT_ERROR_INVALID_TILING_MODE; } From f6388c367e55c7bf03973e88e6d3937672c52b0f Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sun, 17 Sep 2023 20:01:29 +0300 Subject: [PATCH 07/32] added vulkan extension initialize --- CMakeLists.txt | 2 +- src/emulator.cpp | 2 ++ src/vulkan_util.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++ src/vulkan_util.h | 21 ++++++++++++++++++ 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 src/vulkan_util.cpp create mode 100644 src/vulkan_util.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f46f0c79..ef8319ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,7 @@ add_executable(shadps4 src/Core/PS4/HLE/Kernel/event_queues.h src/Core/PS4/HLE/Kernel/cpu_management.cpp src/Core/PS4/HLE/Kernel/cpu_management.h - "src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h" "src/emulator.cpp" "src/emulator.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h" "src/Core/PS4/HLE/Graphics/graphics_ctx.h") + "src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h" "src/emulator.cpp" "src/emulator.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h" "src/Core/PS4/HLE/Graphics/graphics_ctx.h" "src/vulkan_util.cpp" "src/vulkan_util.h") find_package(OpenGL REQUIRED) target_link_libraries(shadps4 PUBLIC fmt mincore spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY} vulkan-1 spirv-tools-opt spirv-tools) diff --git a/src/emulator.cpp b/src/emulator.cpp index 98c3dae0..d77138e7 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -1,6 +1,7 @@ #include "emulator.h" #include "Core/PS4/HLE/Graphics/video_out.h" +#include namespace Emulator { @@ -47,6 +48,7 @@ void emuRun() { { // init window and wait until init finishes CreateSdlWindow(g_window_ctx); + Graphics::Vulkan::vulkanCreate(g_window_ctx); g_window_ctx->m_is_graphic_initialized = true; g_window_ctx->m_graphic_initialized_cond.SignalCondVar(); } diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp new file mode 100644 index 00000000..677f61b4 --- /dev/null +++ b/src/vulkan_util.cpp @@ -0,0 +1,54 @@ +#include "vulkan_util.h" +#include +#include +#include +#include + +constexpr bool log_file_vulkanutil = true; // disable it to disable logging + +void Graphics::Vulkan::vulkanCreate(Emulator::WindowCtx* ctx) { + VulkanExt ext; + vulkanGetExtensions(&ext); + + VkApplicationInfo app_info{}; + app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + app_info.pNext = nullptr; + app_info.pApplicationName = "shadps4"; + app_info.applicationVersion = 1; + app_info.pEngineName = "shadps4"; + app_info.engineVersion = 1; + app_info.apiVersion = VK_API_VERSION_1_2; +} + +void Graphics::Vulkan::vulkanGetExtensions(VulkanExt* ext) { + u32 required_extensions_count = 0; + u32 available_extensions_count = 0; + u32 available_layers_count = 0; + auto result = SDL_Vulkan_GetInstanceExtensions(&required_extensions_count, nullptr); + + ext->required_extensions = std::vector(required_extensions_count); + + result = SDL_Vulkan_GetInstanceExtensions(&required_extensions_count, ext->required_extensions.data()); + + vkEnumerateInstanceExtensionProperties(nullptr, &available_extensions_count, nullptr); + + ext->available_extensions = std::vector(available_extensions_count); + + vkEnumerateInstanceExtensionProperties(nullptr, &available_extensions_count, ext->available_extensions.data()); + + vkEnumerateInstanceLayerProperties(&available_layers_count, nullptr); + ext->available_layers = std::vector(available_layers_count); + vkEnumerateInstanceLayerProperties(&available_layers_count, ext->available_layers.data()); + + for (const char* ext : ext->required_extensions) { + LOG_INFO_IF(log_file_vulkanutil, "Vulkan required extension = {}\n", ext); + } + + for (const auto& ext : ext->available_extensions) { + LOG_INFO_IF(log_file_vulkanutil, "Vulkan available extension: {}, version = {}\n", ext.extensionName, ext.specVersion); + } + + for (const auto& l : ext->available_layers) { + LOG_INFO_IF(log_file_vulkanutil, "Vulkan available layer: {}, specVersion = {}, implVersion = {}, {}\n", l.layerName, l.specVersion,l.implementationVersion,l.description); + } +} diff --git a/src/vulkan_util.h b/src/vulkan_util.h new file mode 100644 index 00000000..cba04d26 --- /dev/null +++ b/src/vulkan_util.h @@ -0,0 +1,21 @@ +#pragma once +#include "emulator.h" +#include +#include +#include + +namespace Graphics::Vulkan { + +struct VulkanExt { + bool enable_validation_layers = false; + + std::vector required_extensions; + std::vector available_extensions; + std::vector required_layers; + std::vector available_layers; +}; + +void vulkanCreate(Emulator::WindowCtx *ctx); +void vulkanGetExtensions(VulkanExt* ext); + +}; \ No newline at end of file From ef6da6bddb6ff37d3eaa682e67a4e7d713ac325b Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sun, 17 Sep 2023 23:38:16 +0300 Subject: [PATCH 08/32] more vulkan init progress --- src/Core/PS4/HLE/Graphics/graphics_ctx.h | 2 ++ src/emulator.h | 1 + src/vulkan_util.cpp | 24 ++++++++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/src/Core/PS4/HLE/Graphics/graphics_ctx.h b/src/Core/PS4/HLE/Graphics/graphics_ctx.h index 782b66f3..330fad57 100644 --- a/src/Core/PS4/HLE/Graphics/graphics_ctx.h +++ b/src/Core/PS4/HLE/Graphics/graphics_ctx.h @@ -1,9 +1,11 @@ #pragma once #include +#include namespace HLE::Libs::Graphics { struct GraphicCtx { u32 screen_width = 0; u32 screen_height = 0; + VkInstance m_instance = nullptr; }; } // namespace HLE::Libs::Graphics \ No newline at end of file diff --git a/src/emulator.h b/src/emulator.h index 975b5330..143eb18f 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -11,6 +11,7 @@ struct WindowCtx { Lib::ConditionVariable m_graphic_initialized_cond; SDL_Window* m_window = nullptr; bool is_window_hidden = true; + VkSurfaceKHR m_surface = nullptr; }; struct EmuPrivate { diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index 677f61b4..28cb185f 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -18,6 +18,30 @@ void Graphics::Vulkan::vulkanCreate(Emulator::WindowCtx* ctx) { app_info.pEngineName = "shadps4"; app_info.engineVersion = 1; app_info.apiVersion = VK_API_VERSION_1_2; + + VkInstanceCreateInfo inst_info{}; + inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + inst_info.pNext = nullptr; + inst_info.flags = 0; + inst_info.pApplicationInfo = &app_info; + inst_info.enabledExtensionCount = ext.required_extensions.size(); + inst_info.ppEnabledExtensionNames = ext.required_extensions.data(); + inst_info.enabledLayerCount = 0; + inst_info.ppEnabledLayerNames = nullptr; + + VkResult result = vkCreateInstance(&inst_info, nullptr, &ctx->m_graphic_ctx.m_instance); + if (result == VK_ERROR_INCOMPATIBLE_DRIVER) { + LOG_CRITICAL_IF(log_file_vulkanutil, "Can't find an compatiblie vulkan driver\n"); + std::exit(0); + } else if (result != VK_SUCCESS) { + LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create an vulkan instance\n"); + std::exit(0); + } + + if (SDL_Vulkan_CreateSurface(ctx->m_window, ctx->m_graphic_ctx.m_instance, &ctx->m_surface) == SDL_FALSE) { + LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create an vulkan surface\n"); + std::exit(0); + } } void Graphics::Vulkan::vulkanGetExtensions(VulkanExt* ext) { From 78bafe88face6f245afbbf0673e8a7310034b271 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Mon, 18 Sep 2023 14:52:16 +0300 Subject: [PATCH 09/32] even more vulkan init --- src/Core/PS4/HLE/Graphics/graphics_ctx.h | 1 + src/emulator.h | 17 +++++++++++ src/vulkan_util.cpp | 39 +++++++++++++++++++++--- src/vulkan_util.h | 24 ++++++--------- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/src/Core/PS4/HLE/Graphics/graphics_ctx.h b/src/Core/PS4/HLE/Graphics/graphics_ctx.h index 330fad57..39f553b7 100644 --- a/src/Core/PS4/HLE/Graphics/graphics_ctx.h +++ b/src/Core/PS4/HLE/Graphics/graphics_ctx.h @@ -7,5 +7,6 @@ struct GraphicCtx { u32 screen_width = 0; u32 screen_height = 0; VkInstance m_instance = nullptr; + VkPhysicalDevice physical_device = nullptr; }; } // namespace HLE::Libs::Graphics \ No newline at end of file diff --git a/src/emulator.h b/src/emulator.h index 143eb18f..bcb9e775 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -2,8 +2,24 @@ #include #include #include +#include + namespace Emulator { + +struct VulkanExt { + bool enable_validation_layers = false; + + std::vector required_extensions; + std::vector available_extensions; + std::vector required_layers; + std::vector available_layers; +}; + +struct VulkanSurfaceCapabilities {}; + +struct VulkanQueues {}; + struct WindowCtx { HLE::Libs::Graphics::GraphicCtx m_graphic_ctx; Lib::Mutex m_mutex; @@ -12,6 +28,7 @@ struct WindowCtx { SDL_Window* m_window = nullptr; bool is_window_hidden = true; VkSurfaceKHR m_surface = nullptr; + VulkanSurfaceCapabilities* m_surface_capabilities = nullptr; }; struct EmuPrivate { diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index 28cb185f..6c191496 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -1,14 +1,15 @@ #include "vulkan_util.h" + +#include #include #include -#include #include constexpr bool log_file_vulkanutil = true; // disable it to disable logging void Graphics::Vulkan::vulkanCreate(Emulator::WindowCtx* ctx) { - VulkanExt ext; - vulkanGetExtensions(&ext); + Emulator::VulkanExt ext; + vulkanGetInstanceExtensions(&ext); VkApplicationInfo app_info{}; app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; @@ -42,9 +43,19 @@ void Graphics::Vulkan::vulkanCreate(Emulator::WindowCtx* ctx) { LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create an vulkan surface\n"); std::exit(0); } + + // TODO i am not sure if it's that it is neccesary or if it needs more + std::vector device_extensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME, + VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME, "VK_KHR_maintenance1"}; + + ctx->m_surface_capabilities = new Emulator::VulkanSurfaceCapabilities{}; + Emulator::VulkanQueues queues; + + vulkanFindCompatiblePhysicalDevice(ctx->m_graphic_ctx.m_instance, ctx->m_surface, device_extensions, ctx->m_surface_capabilities, + &ctx->m_graphic_ctx.physical_device, &queues); } -void Graphics::Vulkan::vulkanGetExtensions(VulkanExt* ext) { +void Graphics::Vulkan::vulkanGetInstanceExtensions(Emulator::VulkanExt* ext) { u32 required_extensions_count = 0; u32 available_extensions_count = 0; u32 available_layers_count = 0; @@ -73,6 +84,24 @@ void Graphics::Vulkan::vulkanGetExtensions(VulkanExt* ext) { } for (const auto& l : ext->available_layers) { - LOG_INFO_IF(log_file_vulkanutil, "Vulkan available layer: {}, specVersion = {}, implVersion = {}, {}\n", l.layerName, l.specVersion,l.implementationVersion,l.description); + LOG_INFO_IF(log_file_vulkanutil, "Vulkan available layer: {}, specVersion = {}, implVersion = {}, {}\n", l.layerName, l.specVersion, + l.implementationVersion, l.description); + } +} + +void Graphics::Vulkan::vulkanFindCompatiblePhysicalDevice(VkInstance instance, VkSurfaceKHR surface, + const std::vector& device_extensions, + Emulator::VulkanSurfaceCapabilities* out_capabilities, VkPhysicalDevice* out_device, + Emulator::VulkanQueues* out_queues) { + u32 count_devices = 0; + vkEnumeratePhysicalDevices(instance, &count_devices, nullptr); + + std::vector devices(count_devices); + vkEnumeratePhysicalDevices(instance, &count_devices, devices.data()); + + VkPhysicalDevice found_best_device = nullptr; + Emulator::VulkanQueues found_best_queues; + + for (const auto& device : devices) { } } diff --git a/src/vulkan_util.h b/src/vulkan_util.h index cba04d26..a7299118 100644 --- a/src/vulkan_util.h +++ b/src/vulkan_util.h @@ -1,21 +1,15 @@ #pragma once -#include "emulator.h" #include -#include #include +#include + +#include "emulator.h" + namespace Graphics::Vulkan { -struct VulkanExt { - bool enable_validation_layers = false; - - std::vector required_extensions; - std::vector available_extensions; - std::vector required_layers; - std::vector available_layers; -}; - -void vulkanCreate(Emulator::WindowCtx *ctx); -void vulkanGetExtensions(VulkanExt* ext); - -}; \ No newline at end of file +void vulkanCreate(Emulator::WindowCtx* ctx); +void vulkanGetInstanceExtensions(Emulator::VulkanExt* ext); +void vulkanFindCompatiblePhysicalDevice(VkInstance instance, VkSurfaceKHR surface, const std::vector& device_extensions, + Emulator::VulkanSurfaceCapabilities* out_capabilities, VkPhysicalDevice* out_device, Emulator::VulkanQueues* out_queues); +}; // namespace Graphics::Vulkan \ No newline at end of file From faf9a03437232878923d2211b596ac9069be48c4 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 19 Sep 2023 09:15:59 +0300 Subject: [PATCH 10/32] some vulkan queue work --- src/emulator.h | 6 ++++-- src/vulkan_util.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/vulkan_util.h | 1 + 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/emulator.h b/src/emulator.h index bcb9e775..8d34ef67 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -2,8 +2,8 @@ #include #include #include -#include +#include namespace Emulator { @@ -18,7 +18,9 @@ struct VulkanExt { struct VulkanSurfaceCapabilities {}; -struct VulkanQueues {}; +struct VulkanQueues { + u32 family_count = 0; +}; struct WindowCtx { HLE::Libs::Graphics::GraphicCtx m_graphic_ctx; diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index 6c191496..9552332d 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -4,6 +4,7 @@ #include #include #include +#include constexpr bool log_file_vulkanutil = true; // disable it to disable logging @@ -103,5 +104,41 @@ void Graphics::Vulkan::vulkanFindCompatiblePhysicalDevice(VkInstance instance, V Emulator::VulkanQueues found_best_queues; for (const auto& device : devices) { + + VkPhysicalDeviceProperties device_properties{}; + VkPhysicalDeviceFeatures2 device_features2{}; + + vkGetPhysicalDeviceProperties(device, &device_properties); + vkGetPhysicalDeviceFeatures2(device, &device_features2); + if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) { + continue; // we don't want integrated gpu for now .Later we will check the requirements and see what we can support (TODO fix me) + } + LOG_INFO_IF(log_file_vulkanutil,"Vulkan device: {}\n", device_properties.deviceName); + + auto qs = vulkanFindQueues(device, surface); } } + +Emulator::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface) { + Emulator::VulkanQueues qs; + + u32 queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, nullptr); + std::vector queue_families(queue_family_count); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families.data()); + + qs.family_count = queue_family_count; + + u32 family = 0; + for (auto& f : queue_families) { + VkBool32 presentation_supported = VK_FALSE; + vkGetPhysicalDeviceSurfaceSupportKHR(device, family, surface, &presentation_supported); + + LOG_INFO_IF(log_file_vulkanutil, "queue family: {}, count = {}, present = {}\n", string_VkQueueFlags(f.queueFlags).c_str(), f.queueCount, + (presentation_supported == VK_TRUE ? "true" : "false")); + + family++; + } + + return qs; +} diff --git a/src/vulkan_util.h b/src/vulkan_util.h index a7299118..995edefc 100644 --- a/src/vulkan_util.h +++ b/src/vulkan_util.h @@ -12,4 +12,5 @@ void vulkanCreate(Emulator::WindowCtx* ctx); void vulkanGetInstanceExtensions(Emulator::VulkanExt* ext); void vulkanFindCompatiblePhysicalDevice(VkInstance instance, VkSurfaceKHR surface, const std::vector& device_extensions, Emulator::VulkanSurfaceCapabilities* out_capabilities, VkPhysicalDevice* out_device, Emulator::VulkanQueues* out_queues); +Emulator::VulkanQueues vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface); }; // namespace Graphics::Vulkan \ No newline at end of file From b68f018fad6f53abfb9e7b7153c9c701e175c239 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 19 Sep 2023 14:02:40 +0300 Subject: [PATCH 11/32] Added vulkanGetSurfaceCapabilities --- src/emulator.h | 8 +++++++- src/vulkan_util.cpp | 30 ++++++++++++++++++++++++++++++ src/vulkan_util.h | 2 ++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/emulator.h b/src/emulator.h index 8d34ef67..2f3be030 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -16,7 +16,13 @@ struct VulkanExt { std::vector available_layers; }; -struct VulkanSurfaceCapabilities {}; +struct VulkanSurfaceCapabilities { + VkSurfaceCapabilitiesKHR capabilities{}; + std::vector formats; + std::vector present_modes; + bool is_format_srgb_bgra32 = false; + bool is_format_unorm_bgra32 = false; +}; struct VulkanQueues { u32 family_count = 0; diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index 9552332d..f37d0848 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -116,6 +116,8 @@ void Graphics::Vulkan::vulkanFindCompatiblePhysicalDevice(VkInstance instance, V LOG_INFO_IF(log_file_vulkanutil,"Vulkan device: {}\n", device_properties.deviceName); auto qs = vulkanFindQueues(device, surface); + + vulkanGetSurfaceCapabilities(device, surface, out_capabilities); } } @@ -142,3 +144,31 @@ Emulator::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice devic return qs; } + +void Graphics::Vulkan::vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, Emulator::VulkanSurfaceCapabilities* surfaceCap) { + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &surfaceCap->capabilities); + + uint32_t formats_count = 0; + vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &formats_count, nullptr); + + surfaceCap->formats = std::vector(formats_count); + vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &formats_count, surfaceCap->formats.data()); + + uint32_t present_modes_count = 0; + vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_modes_count, nullptr); + + + surfaceCap->present_modes = std::vector(present_modes_count); + vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_modes_count, surfaceCap->present_modes.data()); + + for (const auto& f : surfaceCap->formats) { + if (f.format == VK_FORMAT_B8G8R8A8_SRGB && f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + surfaceCap->is_format_srgb_bgra32 = true; + break; + } + if (f.format == VK_FORMAT_B8G8R8A8_UNORM && f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + surfaceCap->is_format_unorm_bgra32 = true; + break; + } + } +} \ No newline at end of file diff --git a/src/vulkan_util.h b/src/vulkan_util.h index 995edefc..0afabddf 100644 --- a/src/vulkan_util.h +++ b/src/vulkan_util.h @@ -13,4 +13,6 @@ void vulkanGetInstanceExtensions(Emulator::VulkanExt* ext); void vulkanFindCompatiblePhysicalDevice(VkInstance instance, VkSurfaceKHR surface, const std::vector& device_extensions, Emulator::VulkanSurfaceCapabilities* out_capabilities, VkPhysicalDevice* out_device, Emulator::VulkanQueues* out_queues); Emulator::VulkanQueues vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface); +void vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, + Emulator::VulkanSurfaceCapabilities* surfaceCap); }; // namespace Graphics::Vulkan \ No newline at end of file From 48ae687191c601aed99a5eb54b5a90ee6b4dfc3d Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 19 Sep 2023 17:13:37 +0300 Subject: [PATCH 12/32] misc --- src/vulkan_util.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index f37d0848..cb7db66e 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -118,7 +118,12 @@ void Graphics::Vulkan::vulkanFindCompatiblePhysicalDevice(VkInstance instance, V auto qs = vulkanFindQueues(device, surface); vulkanGetSurfaceCapabilities(device, surface, out_capabilities); + + found_best_device = device; + found_best_queues = qs; } + *out_device = found_best_device; + *out_queues = found_best_queues; } Emulator::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface) { From 3768dfabfc3a36f806c20c38fb80850f12101270 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 20 Sep 2023 14:19:20 +0300 Subject: [PATCH 13/32] more work on vulkan queues --- src/emulator.h | 13 +++++++++++++ src/vulkan_util.cpp | 30 +++++++++++++++++++++--------- src/vulkan_util.h | 12 +++++++++--- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/emulator.h b/src/emulator.h index 2f3be030..e1519ab3 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -24,10 +24,23 @@ struct VulkanSurfaceCapabilities { bool is_format_unorm_bgra32 = false; }; +struct VulkanQueueInfo { + u32 family = 0; + u32 index = 0; + bool is_graphics = false; + bool is_compute = false; + bool is_transfer = false; + bool is_present = false; +}; + struct VulkanQueues { u32 family_count = 0; + std::vector available; + std::vector graphics; + std::vector family_used; }; + struct WindowCtx { HLE::Libs::Graphics::GraphicCtx m_graphic_ctx; Lib::Mutex m_mutex; diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index cb7db66e..18ef6b4e 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -3,8 +3,8 @@ #include #include #include -#include #include +#include constexpr bool log_file_vulkanutil = true; // disable it to disable logging @@ -104,7 +104,6 @@ void Graphics::Vulkan::vulkanFindCompatiblePhysicalDevice(VkInstance instance, V Emulator::VulkanQueues found_best_queues; for (const auto& device : devices) { - VkPhysicalDeviceProperties device_properties{}; VkPhysicalDeviceFeatures2 device_features2{}; @@ -113,7 +112,7 @@ void Graphics::Vulkan::vulkanFindCompatiblePhysicalDevice(VkInstance instance, V if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) { continue; // we don't want integrated gpu for now .Later we will check the requirements and see what we can support (TODO fix me) } - LOG_INFO_IF(log_file_vulkanutil,"Vulkan device: {}\n", device_properties.deviceName); + LOG_INFO_IF(log_file_vulkanutil, "Vulkan device: {}\n", device_properties.deviceName); auto qs = vulkanFindQueues(device, surface); @@ -126,8 +125,8 @@ void Graphics::Vulkan::vulkanFindCompatiblePhysicalDevice(VkInstance instance, V *out_queues = found_best_queues; } -Emulator::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface) { - Emulator::VulkanQueues qs; +Emulator::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface) { + Emulator::VulkanQueues qs; u32 queue_family_count = 0; vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, nullptr); @@ -142,15 +141,29 @@ Emulator::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice devic vkGetPhysicalDeviceSurfaceSupportKHR(device, family, surface, &presentation_supported); LOG_INFO_IF(log_file_vulkanutil, "queue family: {}, count = {}, present = {}\n", string_VkQueueFlags(f.queueFlags).c_str(), f.queueCount, - (presentation_supported == VK_TRUE ? "true" : "false")); + (presentation_supported == VK_TRUE ? "true" : "false")); + for (uint32_t i = 0; i < f.queueCount; i++) { + Emulator::VulkanQueueInfo info; + info.family = family; + info.index = i; + info.is_graphics = (f.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0; + info.is_compute = (f.queueFlags & VK_QUEUE_COMPUTE_BIT) != 0; + info.is_transfer = (f.queueFlags & VK_QUEUE_TRANSFER_BIT) != 0; + info.is_present = (presentation_supported == VK_TRUE); + + qs.available.push_back(info); + } + + qs.family_used.push_back(0); family++; } - + // TODO finish it return qs; } -void Graphics::Vulkan::vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, Emulator::VulkanSurfaceCapabilities* surfaceCap) { +void Graphics::Vulkan::vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, + Emulator::VulkanSurfaceCapabilities* surfaceCap) { vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &surfaceCap->capabilities); uint32_t formats_count = 0; @@ -162,7 +175,6 @@ void Graphics::Vulkan::vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_de uint32_t present_modes_count = 0; vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_modes_count, nullptr); - surfaceCap->present_modes = std::vector(present_modes_count); vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_modes_count, surfaceCap->present_modes.data()); diff --git a/src/vulkan_util.h b/src/vulkan_util.h index 0afabddf..25e8e05d 100644 --- a/src/vulkan_util.h +++ b/src/vulkan_util.h @@ -8,11 +8,17 @@ namespace Graphics::Vulkan { +constexpr int VULKAN_QUEUES_NUM = 11; // Total of the above +constexpr int VULKAN_QUEUE_GRAPHICS_NUM = 1; +constexpr int VULKAN_QUEUE_TRANSFER_NUM = 1; +constexpr int VULKAN_QUEUE_PRESENT_NUM = 1; +constexpr int VULKAN_QUEUE_COMPUTE_NUM = 8; + void vulkanCreate(Emulator::WindowCtx* ctx); void vulkanGetInstanceExtensions(Emulator::VulkanExt* ext); void vulkanFindCompatiblePhysicalDevice(VkInstance instance, VkSurfaceKHR surface, const std::vector& device_extensions, - Emulator::VulkanSurfaceCapabilities* out_capabilities, VkPhysicalDevice* out_device, Emulator::VulkanQueues* out_queues); + Emulator::VulkanSurfaceCapabilities* out_capabilities, VkPhysicalDevice* out_device, + Emulator::VulkanQueues* out_queues); Emulator::VulkanQueues vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface); -void vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, - Emulator::VulkanSurfaceCapabilities* surfaceCap); +void vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, Emulator::VulkanSurfaceCapabilities* surfaceCap); }; // namespace Graphics::Vulkan \ No newline at end of file From 90dc454440bf628b20c1e2097087d695f09ad43f Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 21 Sep 2023 12:41:51 +0300 Subject: [PATCH 14/32] Finished vulkanFindQueues --- src/emulator.h | 3 +++ src/vulkan_util.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/emulator.h b/src/emulator.h index e1519ab3..6dadc684 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -37,6 +37,9 @@ struct VulkanQueues { u32 family_count = 0; std::vector available; std::vector graphics; + std::vector compute; + std::vector transfer; + std::vector present; std::vector family_used; }; diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index 18ef6b4e..dcfac166 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -158,7 +158,56 @@ Emulator::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice devic family++; } - // TODO finish it + u32 index = 0; + for (u32 i = 0; i < VULKAN_QUEUE_GRAPHICS_NUM; i++) { + + for (const auto& idx : qs.available) { + if (idx.is_graphics) + { + qs.family_used[qs.available.at(index).family]++; + qs.graphics.push_back(qs.available.at(index)); + qs.available.erase(qs.available.begin()+index); + break; + } + index++; + } + } + index = 0; + for (u32 i = 0; i < VULKAN_QUEUE_COMPUTE_NUM; i++) { + for (const auto& idx : qs.available) { + if (idx.is_graphics) { + qs.family_used[qs.available.at(index).family]++; + qs.compute.push_back(qs.available.at(index)); + qs.available.erase(qs.available.begin() + index); + break; + } + index++; + } + } + index = 0; + for (uint32_t i = 0; i < VULKAN_QUEUE_TRANSFER_NUM; i++) { + for (const auto& idx : qs.available) { + if (idx.is_graphics) { + qs.family_used[qs.available.at(index).family]++; + qs.transfer.push_back(qs.available.at(index)); + qs.available.erase(qs.available.begin() + index); + break; + } + index++; + } + } + index = 0; + for (uint32_t i = 0; i < VULKAN_QUEUE_PRESENT_NUM; i++) { + for (const auto& idx : qs.available) { + if (idx.is_graphics) { + qs.family_used[qs.available.at(index).family]++; + qs.present.push_back(qs.available.at(index)); + qs.available.erase(qs.available.begin() + index); + break; + } + index++; + } + } return qs; } From b1d812bb32c69a6a064f1fc5716b3b88e271f80a Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 21 Sep 2023 12:59:48 +0300 Subject: [PATCH 15/32] vulkan : createDevice --- src/Core/PS4/HLE/Graphics/graphics_ctx.h | 3 +- src/vulkan_util.cpp | 69 ++++++++++++++++++++++-- src/vulkan_util.h | 2 + 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/Core/PS4/HLE/Graphics/graphics_ctx.h b/src/Core/PS4/HLE/Graphics/graphics_ctx.h index 39f553b7..82ca6b05 100644 --- a/src/Core/PS4/HLE/Graphics/graphics_ctx.h +++ b/src/Core/PS4/HLE/Graphics/graphics_ctx.h @@ -7,6 +7,7 @@ struct GraphicCtx { u32 screen_width = 0; u32 screen_height = 0; VkInstance m_instance = nullptr; - VkPhysicalDevice physical_device = nullptr; + VkPhysicalDevice m_physical_device = nullptr; + VkDevice m_device = nullptr; }; } // namespace HLE::Libs::Graphics \ No newline at end of file diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index dcfac166..e648759b 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -53,9 +53,70 @@ void Graphics::Vulkan::vulkanCreate(Emulator::WindowCtx* ctx) { Emulator::VulkanQueues queues; vulkanFindCompatiblePhysicalDevice(ctx->m_graphic_ctx.m_instance, ctx->m_surface, device_extensions, ctx->m_surface_capabilities, - &ctx->m_graphic_ctx.physical_device, &queues); + &ctx->m_graphic_ctx.m_physical_device, &queues); + + if (ctx->m_graphic_ctx.m_physical_device == nullptr) { + LOG_CRITICAL_IF(log_file_vulkanutil, "Can't find compatible vulkan device\n"); + std::exit(0); + } + + VkPhysicalDeviceProperties device_properties{}; + vkGetPhysicalDeviceProperties(ctx->m_graphic_ctx.m_physical_device, &device_properties); + + LOG_INFO_IF(log_file_vulkanutil, "GFX device to be used : {}\n", device_properties.deviceName); + + ctx->m_graphic_ctx.m_device = vulkanCreateDevice(ctx->m_graphic_ctx.m_physical_device, ctx->m_surface, &ext, queues, device_extensions); + if (ctx->m_graphic_ctx.m_device == nullptr) { + LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create vulkan device\n"); + std::exit(0); + } } +VkDevice Graphics::Vulkan::vulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const Emulator::VulkanExt* r, + const Emulator::VulkanQueues& queues, const std::vector& device_extensions) { + + std::vector queue_create_info(queues.family_count); + std::vector> queue_priority(queues.family_count); + uint32_t queue_create_info_num = 0; + + for (uint32_t i = 0; i < queues.family_count; i++) { + if (queues.family_used[i] != 0) { + for (uint32_t pi = 0; pi < queues.family_used[i]; pi++) { + queue_priority[queue_create_info_num].push_back(1.0f); + } + + queue_create_info[queue_create_info_num].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_info[queue_create_info_num].pNext = nullptr; + queue_create_info[queue_create_info_num].flags = 0; + queue_create_info[queue_create_info_num].queueFamilyIndex = i; + queue_create_info[queue_create_info_num].queueCount = queues.family_used[i]; + queue_create_info[queue_create_info_num].pQueuePriorities = queue_priority[queue_create_info_num].data(); + + queue_create_info_num++; + } + } + + VkPhysicalDeviceFeatures device_features{}; + //TODO add neccesary device features + + VkDeviceCreateInfo create_info{}; + create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.pQueueCreateInfos = queue_create_info.data(); + create_info.queueCreateInfoCount = queue_create_info_num; + create_info.enabledLayerCount = 0; + create_info.ppEnabledLayerNames = nullptr; + create_info.enabledExtensionCount = device_extensions.size(); + create_info.ppEnabledExtensionNames = device_extensions.data(); + create_info.pEnabledFeatures = &device_features; + + VkDevice device = nullptr; + + vkCreateDevice(physical_device, &create_info, nullptr, &device); + + return device; +} void Graphics::Vulkan::vulkanGetInstanceExtensions(Emulator::VulkanExt* ext) { u32 required_extensions_count = 0; u32 available_extensions_count = 0; @@ -160,13 +221,11 @@ Emulator::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice devic } u32 index = 0; for (u32 i = 0; i < VULKAN_QUEUE_GRAPHICS_NUM; i++) { - for (const auto& idx : qs.available) { - if (idx.is_graphics) - { + if (idx.is_graphics) { qs.family_used[qs.available.at(index).family]++; qs.graphics.push_back(qs.available.at(index)); - qs.available.erase(qs.available.begin()+index); + qs.available.erase(qs.available.begin() + index); break; } index++; diff --git a/src/vulkan_util.h b/src/vulkan_util.h index 25e8e05d..f653fae1 100644 --- a/src/vulkan_util.h +++ b/src/vulkan_util.h @@ -19,6 +19,8 @@ void vulkanGetInstanceExtensions(Emulator::VulkanExt* ext); void vulkanFindCompatiblePhysicalDevice(VkInstance instance, VkSurfaceKHR surface, const std::vector& device_extensions, Emulator::VulkanSurfaceCapabilities* out_capabilities, VkPhysicalDevice* out_device, Emulator::VulkanQueues* out_queues); +VkDevice vulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const Emulator::VulkanExt* r, + const Emulator::VulkanQueues& queues, const std::vector& device_extensions); Emulator::VulkanQueues vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface); void vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, Emulator::VulkanSurfaceCapabilities* surfaceCap); }; // namespace Graphics::Vulkan \ No newline at end of file From 3c4716ba5f3b5476b648938a85f4e162a187a440 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 21 Sep 2023 18:20:13 +0300 Subject: [PATCH 16/32] vulkanCreateQueues --- src/Core/PS4/HLE/Graphics/graphics_ctx.h | 11 +++++++++++ src/vulkan_util.cpp | 24 ++++++++++++++++++++++++ src/vulkan_util.h | 7 +++++++ 3 files changed, 42 insertions(+) diff --git a/src/Core/PS4/HLE/Graphics/graphics_ctx.h b/src/Core/PS4/HLE/Graphics/graphics_ctx.h index 82ca6b05..074e8626 100644 --- a/src/Core/PS4/HLE/Graphics/graphics_ctx.h +++ b/src/Core/PS4/HLE/Graphics/graphics_ctx.h @@ -1,13 +1,24 @@ #pragma once #include #include +#include +#include "Lib/Threads.h" namespace HLE::Libs::Graphics { + +struct VulkanQueueInfo { + Lib::Mutex* mutex = nullptr; + u32 family = static_cast(-1); + u32 index = static_cast(-1); + VkQueue vk_queue = nullptr; +}; + struct GraphicCtx { u32 screen_width = 0; u32 screen_height = 0; VkInstance m_instance = nullptr; VkPhysicalDevice m_physical_device = nullptr; VkDevice m_device = nullptr; + VulkanQueueInfo queues[11]; //VULKAN_QUEUES_NUM }; } // namespace HLE::Libs::Graphics \ No newline at end of file diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index e648759b..9512e5e9 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -70,6 +70,30 @@ void Graphics::Vulkan::vulkanCreate(Emulator::WindowCtx* ctx) { LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create vulkan device\n"); std::exit(0); } + + vulkanCreateQueues(&ctx->m_graphic_ctx, queues); + +} + +void Graphics::Vulkan::vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emulator::VulkanQueues& queues) { + + auto get_queue = [ctx](int id, const Emulator::VulkanQueueInfo& info, bool with_mutex = false) { + ctx->queues[id].family = info.family; + ctx->queues[id].index = info.index; + vkGetDeviceQueue(ctx->m_device, ctx->queues[id].family, ctx->queues[id].index, &ctx->queues[id].vk_queue); + if (with_mutex) { + ctx->queues[id].mutex = new Lib::Mutex; + } + }; + + get_queue(VULKAN_QUEUE_GFX, queues.graphics.at(0)); + get_queue(VULKAN_QUEUE_UTIL, queues.transfer.at(0)); + get_queue(VULKAN_QUEUE_PRESENT, queues.present.at(0)); + + for (int id = 0; id < VULKAN_QUEUE_COMPUTE_NUM; id++) { + bool with_mutex = (VULKAN_QUEUE_COMPUTE_NUM == queues.compute.size()); + get_queue(id, queues.compute.at(id % queues.compute.size()), with_mutex); + } } VkDevice Graphics::Vulkan::vulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const Emulator::VulkanExt* r, diff --git a/src/vulkan_util.h b/src/vulkan_util.h index f653fae1..8b70b2c4 100644 --- a/src/vulkan_util.h +++ b/src/vulkan_util.h @@ -14,6 +14,11 @@ constexpr int VULKAN_QUEUE_TRANSFER_NUM = 1; constexpr int VULKAN_QUEUE_PRESENT_NUM = 1; constexpr int VULKAN_QUEUE_COMPUTE_NUM = 8; +constexpr int VULKAN_QUEUE_GFX = 8; +constexpr int VULKAN_QUEUE_UTIL = 9; +constexpr int VULKAN_QUEUE_PRESENT = 10; + + void vulkanCreate(Emulator::WindowCtx* ctx); void vulkanGetInstanceExtensions(Emulator::VulkanExt* ext); void vulkanFindCompatiblePhysicalDevice(VkInstance instance, VkSurfaceKHR surface, const std::vector& device_extensions, @@ -23,4 +28,6 @@ VkDevice vulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surfa const Emulator::VulkanQueues& queues, const std::vector& device_extensions); Emulator::VulkanQueues vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface); void vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, Emulator::VulkanSurfaceCapabilities* surfaceCap); +void vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emulator::VulkanQueues& queues); + }; // namespace Graphics::Vulkan \ No newline at end of file From 085996488854d0373c43c38ebb980c745117d9af Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 21 Sep 2023 23:48:16 +0300 Subject: [PATCH 17/32] almost finished vulkan init --- src/emulator.cpp | 28 ++++--- src/emulator.h | 12 +++ src/vulkan_util.cpp | 191 ++++++++++++++++++++++++++++++++++---------- src/vulkan_util.h | 2 +- 4 files changed, 176 insertions(+), 57 deletions(-) diff --git a/src/emulator.cpp b/src/emulator.cpp index d77138e7..91d7b055 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -2,24 +2,25 @@ #include "Core/PS4/HLE/Graphics/video_out.h" #include +#include namespace Emulator { -static WindowCtx* g_window_ctx = nullptr; bool m_emu_needs_exit = false; void emuInit(u32 width, u32 height) { - g_window_ctx = new WindowCtx; + auto* window_ctx = Singleton::Instance(); - g_window_ctx->m_graphic_ctx.screen_width = width; - g_window_ctx->m_graphic_ctx.screen_height = height; + window_ctx->m_graphic_ctx.screen_width = width; + window_ctx->m_graphic_ctx.screen_height = height; } void checkAndWaitForGraphicsInit() { - Lib::LockMutexGuard lock(g_window_ctx->m_mutex); + auto* window_ctx = Singleton::Instance(); + Lib::LockMutexGuard lock(window_ctx->m_mutex); - while (!g_window_ctx->m_is_graphic_initialized) { - g_window_ctx->m_graphic_initialized_cond.WaitCondVar(&g_window_ctx->m_mutex); + while (!window_ctx->m_is_graphic_initialized) { + window_ctx->m_graphic_initialized_cond.WaitCondVar(&window_ctx->m_mutex); } } static void CreateSdlWindow(WindowCtx* ctx) { @@ -44,15 +45,16 @@ static void CreateSdlWindow(WindowCtx* ctx) { SDL_SetWindowResizable(ctx->m_window, SDL_FALSE); // we don't support resizable atm } void emuRun() { - g_window_ctx->m_mutex.LockMutex(); + auto* window_ctx = Singleton::Instance(); + window_ctx->m_mutex.LockMutex(); { // init window and wait until init finishes - CreateSdlWindow(g_window_ctx); - Graphics::Vulkan::vulkanCreate(g_window_ctx); - g_window_ctx->m_is_graphic_initialized = true; - g_window_ctx->m_graphic_initialized_cond.SignalCondVar(); + CreateSdlWindow(window_ctx); + Graphics::Vulkan::vulkanCreate(window_ctx); + window_ctx->m_is_graphic_initialized = true; + window_ctx->m_graphic_initialized_cond.SignalCondVar(); } - g_window_ctx->m_mutex.UnlockMutex(); + window_ctx->m_mutex.UnlockMutex(); bool exit_loop = false; diff --git a/src/emulator.h b/src/emulator.h index 6dadc684..39e960e6 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -43,6 +43,17 @@ struct VulkanQueues { std::vector family_used; }; +struct VulkanSwapchain { + VkSwapchainKHR swapchain = nullptr; + VkFormat swapchain_format = VK_FORMAT_UNDEFINED; + VkExtent2D swapchain_extent = {}; + VkImage* swapchain_images = nullptr; + VkImageView* swapchain_image_views = nullptr; + u32 swapchain_images_count = 0; + VkSemaphore present_complete_semaphore = nullptr; + VkFence present_complete_fence = nullptr; + u32 current_index = 0; +}; struct WindowCtx { HLE::Libs::Graphics::GraphicCtx m_graphic_ctx; @@ -53,6 +64,7 @@ struct WindowCtx { bool is_window_hidden = true; VkSurfaceKHR m_surface = nullptr; VulkanSurfaceCapabilities* m_surface_capabilities = nullptr; + VulkanSwapchain* swapchain = nullptr; }; struct EmuPrivate { diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index 9512e5e9..88c85edc 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -1,10 +1,11 @@ #include "vulkan_util.h" - +#include #include #include #include #include #include +#include constexpr bool log_file_vulkanutil = true; // disable it to disable logging @@ -63,47 +64,151 @@ void Graphics::Vulkan::vulkanCreate(Emulator::WindowCtx* ctx) { VkPhysicalDeviceProperties device_properties{}; vkGetPhysicalDeviceProperties(ctx->m_graphic_ctx.m_physical_device, &device_properties); - LOG_INFO_IF(log_file_vulkanutil, "GFX device to be used : {}\n", device_properties.deviceName); + LOG_INFO_IF(log_file_vulkanutil, "GFX device to be used : {}\n", device_properties.deviceName); - ctx->m_graphic_ctx.m_device = vulkanCreateDevice(ctx->m_graphic_ctx.m_physical_device, ctx->m_surface, &ext, queues, device_extensions); - if (ctx->m_graphic_ctx.m_device == nullptr) { + ctx->m_graphic_ctx.m_device = vulkanCreateDevice(ctx->m_graphic_ctx.m_physical_device, ctx->m_surface, &ext, queues, device_extensions); + if (ctx->m_graphic_ctx.m_device == nullptr) { LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create vulkan device\n"); std::exit(0); - } - - vulkanCreateQueues(&ctx->m_graphic_ctx, queues); + } + vulkanCreateQueues(&ctx->m_graphic_ctx, queues); + ctx->swapchain = vulkanCreateSwapchain(&ctx->m_graphic_ctx, 2); } +Emulator::VulkanSwapchain* vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count) { + auto* window_ctx = Singleton::Instance(); + Lib::LockMutexGuard lock(window_ctx->m_mutex); + + auto* s = new Emulator::VulkanSwapchain; + + VkExtent2D extent{}; + extent.width = std::clamp(ctx->screen_width, window_ctx->m_surface_capabilities->capabilities.minImageExtent.width, + window_ctx->m_surface_capabilities->capabilities.maxImageExtent.width); + extent.height = std::clamp(ctx->screen_height, window_ctx->m_surface_capabilities->capabilities.minImageExtent.height, + window_ctx->m_surface_capabilities->capabilities.maxImageExtent.height); + + image_count = std::clamp(image_count, window_ctx->m_surface_capabilities->capabilities.minImageCount, + window_ctx->m_surface_capabilities->capabilities.maxImageCount); + + VkSwapchainCreateInfoKHR create_info{}; + create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.surface = window_ctx->m_surface; + create_info.minImageCount = image_count; + + if (window_ctx->m_surface_capabilities->is_format_unorm_bgra32) { + create_info.imageFormat = VK_FORMAT_B8G8R8A8_UNORM; + create_info.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; + } else if (window_ctx->m_surface_capabilities->is_format_srgb_bgra32) { + create_info.imageFormat = VK_FORMAT_B8G8R8A8_SRGB; + create_info.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; + } else { + create_info.imageFormat = window_ctx->m_surface_capabilities->formats.at(0).format; + create_info.imageColorSpace = window_ctx->m_surface_capabilities->formats.at(0).colorSpace; + } + + create_info.imageExtent = extent; + create_info.imageArrayLayers = 1; + create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + create_info.queueFamilyIndexCount = 0; + create_info.pQueueFamilyIndices = nullptr; + create_info.preTransform = window_ctx->m_surface_capabilities->capabilities.currentTransform; + create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR; + create_info.clipped = VK_TRUE; + create_info.oldSwapchain = nullptr; + + s->swapchain_format = create_info.imageFormat; + s->swapchain_extent = extent; + + VkSwapchainKHR swapchain = nullptr; + + vkCreateSwapchainKHR(ctx->m_device, &create_info, nullptr, &swapchain); + + vkGetSwapchainImagesKHR(ctx->m_device, swapchain, &s->swapchain_images_count, nullptr); + + s->swapchain_images = new VkImage[s->swapchain_images_count]; + vkGetSwapchainImagesKHR(ctx->m_device, swapchain, &s->swapchain_images_count, s->swapchain_images); + + s->swapchain_image_views = new VkImageView[s->swapchain_images_count]; + for (uint32_t i = 0; i < s->swapchain_images_count; i++) { + VkImageViewCreateInfo create_info{}; + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.image = (s->swapchain_images)[i]; + create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + create_info.format = s->swapchain_format; + create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + create_info.subresourceRange.baseArrayLayer = 0; + create_info.subresourceRange.baseMipLevel = 0; + create_info.subresourceRange.layerCount = 1; + create_info.subresourceRange.levelCount = 1; + + vkCreateImageView(ctx->m_device, &create_info, nullptr, &((s->swapchain_image_views)[i])); + } + if (s->swapchain == nullptr) { + LOG_CRITICAL_IF(log_file_vulkanutil, "Could not create swapchain\n"); + std::exit(0); + } + + s->current_index = static_cast(-1); + + VkSemaphoreCreateInfo present_complete_info{}; + present_complete_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + present_complete_info.pNext = nullptr; + present_complete_info.flags = 0; + + auto result = vkCreateSemaphore(ctx->m_device, &present_complete_info, nullptr, &s->present_complete_semaphore); + + VkFenceCreateInfo fence_info{}; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_info.pNext = nullptr; + fence_info.flags = 0; + + result = vkCreateFence(ctx->m_device, &fence_info, nullptr, &s->present_complete_fence); + if (result != VK_SUCCESS) { + LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create vulkan fence\n"); + std::exit(0); + } + + return s; + +} void Graphics::Vulkan::vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emulator::VulkanQueues& queues) { + auto get_queue = [ctx](int id, const Emulator::VulkanQueueInfo& info, bool with_mutex = false) { + ctx->queues[id].family = info.family; + ctx->queues[id].index = info.index; + vkGetDeviceQueue(ctx->m_device, ctx->queues[id].family, ctx->queues[id].index, &ctx->queues[id].vk_queue); + if (with_mutex) { + ctx->queues[id].mutex = new Lib::Mutex; + } + }; - auto get_queue = [ctx](int id, const Emulator::VulkanQueueInfo& info, bool with_mutex = false) { - ctx->queues[id].family = info.family; - ctx->queues[id].index = info.index; - vkGetDeviceQueue(ctx->m_device, ctx->queues[id].family, ctx->queues[id].index, &ctx->queues[id].vk_queue); - if (with_mutex) { - ctx->queues[id].mutex = new Lib::Mutex; - } - }; + get_queue(VULKAN_QUEUE_GFX, queues.graphics.at(0)); + get_queue(VULKAN_QUEUE_UTIL, queues.transfer.at(0)); + get_queue(VULKAN_QUEUE_PRESENT, queues.present.at(0)); - get_queue(VULKAN_QUEUE_GFX, queues.graphics.at(0)); - get_queue(VULKAN_QUEUE_UTIL, queues.transfer.at(0)); - get_queue(VULKAN_QUEUE_PRESENT, queues.present.at(0)); - - for (int id = 0; id < VULKAN_QUEUE_COMPUTE_NUM; id++) { + for (int id = 0; id < VULKAN_QUEUE_COMPUTE_NUM; id++) { bool with_mutex = (VULKAN_QUEUE_COMPUTE_NUM == queues.compute.size()); get_queue(id, queues.compute.at(id % queues.compute.size()), with_mutex); - } + } } VkDevice Graphics::Vulkan::vulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const Emulator::VulkanExt* r, const Emulator::VulkanQueues& queues, const std::vector& device_extensions) { + std::vector queue_create_info(queues.family_count); + std::vector> queue_priority(queues.family_count); + uint32_t queue_create_info_num = 0; - std::vector queue_create_info(queues.family_count); - std::vector> queue_priority(queues.family_count); - uint32_t queue_create_info_num = 0; - - for (uint32_t i = 0; i < queues.family_count; i++) { + for (uint32_t i = 0; i < queues.family_count; i++) { if (queues.family_used[i] != 0) { for (uint32_t pi = 0; pi < queues.family_used[i]; pi++) { queue_priority[queue_create_info_num].push_back(1.0f); @@ -118,28 +223,28 @@ VkDevice Graphics::Vulkan::vulkanCreateDevice(VkPhysicalDevice physical_device, queue_create_info_num++; } - } + } - VkPhysicalDeviceFeatures device_features{}; - //TODO add neccesary device features + VkPhysicalDeviceFeatures device_features{}; + // TODO add neccesary device features - VkDeviceCreateInfo create_info{}; - create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - create_info.pNext = nullptr; - create_info.flags = 0; - create_info.pQueueCreateInfos = queue_create_info.data(); - create_info.queueCreateInfoCount = queue_create_info_num; - create_info.enabledLayerCount = 0; - create_info.ppEnabledLayerNames = nullptr; - create_info.enabledExtensionCount = device_extensions.size(); - create_info.ppEnabledExtensionNames = device_extensions.data(); - create_info.pEnabledFeatures = &device_features; + VkDeviceCreateInfo create_info{}; + create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.pQueueCreateInfos = queue_create_info.data(); + create_info.queueCreateInfoCount = queue_create_info_num; + create_info.enabledLayerCount = 0; + create_info.ppEnabledLayerNames = nullptr; + create_info.enabledExtensionCount = device_extensions.size(); + create_info.ppEnabledExtensionNames = device_extensions.data(); + create_info.pEnabledFeatures = &device_features; - VkDevice device = nullptr; + VkDevice device = nullptr; - vkCreateDevice(physical_device, &create_info, nullptr, &device); + vkCreateDevice(physical_device, &create_info, nullptr, &device); - return device; + return device; } void Graphics::Vulkan::vulkanGetInstanceExtensions(Emulator::VulkanExt* ext) { u32 required_extensions_count = 0; diff --git a/src/vulkan_util.h b/src/vulkan_util.h index 8b70b2c4..5fcaf651 100644 --- a/src/vulkan_util.h +++ b/src/vulkan_util.h @@ -29,5 +29,5 @@ VkDevice vulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surfa Emulator::VulkanQueues vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface); void vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, Emulator::VulkanSurfaceCapabilities* surfaceCap); void vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emulator::VulkanQueues& queues); - +Emulator::VulkanSwapchain* vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count); }; // namespace Graphics::Vulkan \ No newline at end of file From 12382ddac42c16bdd7c50017407c6152235e69fd Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Fri, 22 Sep 2023 00:05:00 +0300 Subject: [PATCH 18/32] fixed some silly issues --- src/vulkan_util.cpp | 29 ++++++++++++++--------------- src/vulkan_util.h | 6 ++++++ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index 88c85edc..bf3b84b0 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -1,11 +1,13 @@ #include "vulkan_util.h" -#include + #include +#include #include #include #include #include -#include + +#include constexpr bool log_file_vulkanutil = true; // disable it to disable logging @@ -76,20 +78,20 @@ void Graphics::Vulkan::vulkanCreate(Emulator::WindowCtx* ctx) { ctx->swapchain = vulkanCreateSwapchain(&ctx->m_graphic_ctx, 2); } -Emulator::VulkanSwapchain* vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count) { +Emulator::VulkanSwapchain* Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count) { auto* window_ctx = Singleton::Instance(); Lib::LockMutexGuard lock(window_ctx->m_mutex); auto* s = new Emulator::VulkanSwapchain; VkExtent2D extent{}; - extent.width = std::clamp(ctx->screen_width, window_ctx->m_surface_capabilities->capabilities.minImageExtent.width, - window_ctx->m_surface_capabilities->capabilities.maxImageExtent.width); - extent.height = std::clamp(ctx->screen_height, window_ctx->m_surface_capabilities->capabilities.minImageExtent.height, - window_ctx->m_surface_capabilities->capabilities.maxImageExtent.height); + extent.width = clamp(ctx->screen_width, window_ctx->m_surface_capabilities->capabilities.minImageExtent.width, + window_ctx->m_surface_capabilities->capabilities.maxImageExtent.width); + extent.height = clamp(ctx->screen_height, window_ctx->m_surface_capabilities->capabilities.minImageExtent.height, + window_ctx->m_surface_capabilities->capabilities.maxImageExtent.height); - image_count = std::clamp(image_count, window_ctx->m_surface_capabilities->capabilities.minImageCount, - window_ctx->m_surface_capabilities->capabilities.maxImageCount); + image_count = clamp(image_count, window_ctx->m_surface_capabilities->capabilities.minImageCount, + window_ctx->m_surface_capabilities->capabilities.maxImageCount); VkSwapchainCreateInfoKHR create_info{}; create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; @@ -124,14 +126,12 @@ Emulator::VulkanSwapchain* vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx s->swapchain_format = create_info.imageFormat; s->swapchain_extent = extent; - VkSwapchainKHR swapchain = nullptr; + vkCreateSwapchainKHR(ctx->m_device, &create_info, nullptr, &s->swapchain); - vkCreateSwapchainKHR(ctx->m_device, &create_info, nullptr, &swapchain); - - vkGetSwapchainImagesKHR(ctx->m_device, swapchain, &s->swapchain_images_count, nullptr); + vkGetSwapchainImagesKHR(ctx->m_device, s->swapchain, &s->swapchain_images_count, nullptr); s->swapchain_images = new VkImage[s->swapchain_images_count]; - vkGetSwapchainImagesKHR(ctx->m_device, swapchain, &s->swapchain_images_count, s->swapchain_images); + vkGetSwapchainImagesKHR(ctx->m_device, s->swapchain, &s->swapchain_images_count, s->swapchain_images); s->swapchain_image_views = new VkImageView[s->swapchain_images_count]; for (uint32_t i = 0; i < s->swapchain_images_count; i++) { @@ -180,7 +180,6 @@ Emulator::VulkanSwapchain* vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx } return s; - } void Graphics::Vulkan::vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emulator::VulkanQueues& queues) { auto get_queue = [ctx](int id, const Emulator::VulkanQueueInfo& info, bool with_mutex = false) { diff --git a/src/vulkan_util.h b/src/vulkan_util.h index 5fcaf651..d082c196 100644 --- a/src/vulkan_util.h +++ b/src/vulkan_util.h @@ -18,6 +18,12 @@ constexpr int VULKAN_QUEUE_GFX = 8; constexpr int VULKAN_QUEUE_UTIL = 9; constexpr int VULKAN_QUEUE_PRESENT = 10; +template +const T& clamp(const T& x, const T& min, const T& max) { + if (x < min) return min; + if (x > max) return max; + return x; +} void vulkanCreate(Emulator::WindowCtx* ctx); void vulkanGetInstanceExtensions(Emulator::VulkanExt* ext); From f469296b788f7f0a32f82c9b47e82337b874263a Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Fri, 22 Sep 2023 10:38:21 +0300 Subject: [PATCH 19/32] some video buffer work --- CMakeLists.txt | 2 +- src/Core/PS4/GPU/gpu_memory.h | 4 ++-- src/Core/PS4/GPU/video_out_buffer.cpp | 0 src/Core/PS4/GPU/video_out_buffer.h | 12 ++++++++++++ src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h | 1 + src/Core/PS4/HLE/Graphics/video_out.cpp | 11 +++++++++++ src/Core/PS4/HLE/Graphics/video_out.h | 7 +++++++ 7 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 src/Core/PS4/GPU/video_out_buffer.cpp create mode 100644 src/Core/PS4/GPU/video_out_buffer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ef8319ce..d720ec92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,7 @@ add_executable(shadps4 src/Core/PS4/HLE/Kernel/event_queues.h src/Core/PS4/HLE/Kernel/cpu_management.cpp src/Core/PS4/HLE/Kernel/cpu_management.h - "src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h" "src/emulator.cpp" "src/emulator.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h" "src/Core/PS4/HLE/Graphics/graphics_ctx.h" "src/vulkan_util.cpp" "src/vulkan_util.h") + "src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h" "src/emulator.cpp" "src/emulator.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h" "src/Core/PS4/HLE/Graphics/graphics_ctx.h" "src/vulkan_util.cpp" "src/vulkan_util.h" "src/Core/PS4/GPU/video_out_buffer.cpp" "src/Core/PS4/GPU/video_out_buffer.h") find_package(OpenGL REQUIRED) target_link_libraries(shadps4 PUBLIC fmt mincore spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY} vulkan-1 spirv-tools-opt spirv-tools) diff --git a/src/Core/PS4/GPU/gpu_memory.h b/src/Core/PS4/GPU/gpu_memory.h index 3f667bbf..14084de9 100644 --- a/src/Core/PS4/GPU/gpu_memory.h +++ b/src/Core/PS4/GPU/gpu_memory.h @@ -4,6 +4,6 @@ namespace GPU { enum class MemoryMode : u32 { NoAccess = 0, Read = 1, Write = 2, ReadWrite = 3 }; - +enum class MemoryObjectType : u64 { InvalidObj, VideoOutBufferObj }; void MemorySetAllocArea(u64 virtual_addr, u64 size); -} \ No newline at end of file +} // namespace GPU \ No newline at end of file diff --git a/src/Core/PS4/GPU/video_out_buffer.cpp b/src/Core/PS4/GPU/video_out_buffer.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/Core/PS4/GPU/video_out_buffer.h b/src/Core/PS4/GPU/video_out_buffer.h new file mode 100644 index 00000000..d3be8090 --- /dev/null +++ b/src/Core/PS4/GPU/video_out_buffer.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace GPU { + +enum class VideoOutBufferFormat : u64 { + Unknown, + R8G8B8A8Srgb, + B8G8R8A8Srgb, +}; +} diff --git a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h index 8adf22ef..238697f9 100644 --- a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h +++ b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h @@ -17,6 +17,7 @@ struct VideoConfigInternal { std::vector m_flip_evtEq; int m_flip_rate = 0; + std::vector buffers_sets; int buffers_registration_index = 0; }; diff --git a/src/Core/PS4/HLE/Graphics/video_out.cpp b/src/Core/PS4/HLE/Graphics/video_out.cpp index c470df6f..f5ddeb19 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.cpp +++ b/src/Core/PS4/HLE/Graphics/video_out.cpp @@ -165,6 +165,17 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co u64 buffer_size = 1280 * 720 * 4; //TODO hardcoded value should be redone u64 buffer_pitch = attribute->pitchInPixel; + VideoOutBufferSetInternal buf{}; + + buf.start_index = startIndex; + buf.num = bufferNum; + buf.set_id = registration_index; + buf.attr = *attribute; + + ctx->buffers_sets.push_back(buf); + + + return registration_index; } s32 PS4_SYSV_ABI sceVideoOutSetFlipRate(s32 handle, s32 rate) { diff --git a/src/Core/PS4/HLE/Graphics/video_out.h b/src/Core/PS4/HLE/Graphics/video_out.h index 3ea6fb54..c3250891 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.h +++ b/src/Core/PS4/HLE/Graphics/video_out.h @@ -87,6 +87,13 @@ struct SceVideoOutVblankStatus { u08 pad1[7] = {}; }; +struct VideoOutBufferSetInternal { + SceVideoOutBufferAttribute attr; + int start_index = 0; + int num = 0; + int set_id = 0; +}; + void videoOutInit(u32 width, u32 height); std::string getPixelFormatString(s32 format); void videoOutRegisterLib(SymbolsResolver* sym); From 59efa477ce37e9cf47571223383c9885e3be05c7 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Mon, 25 Sep 2023 00:06:04 +0300 Subject: [PATCH 20/32] even more work on video buffers --- src/Core/PS4/GPU/video_out_buffer.h | 6 +++ src/Core/PS4/HLE/ErrorCodes.h | 1 + .../PS4/HLE/Graphics/Objects/video_out_ctx.h | 11 +++++- src/Core/PS4/HLE/Graphics/graphics_ctx.h | 39 +++++++++++++++++-- src/Core/PS4/HLE/Graphics/video_out.cpp | 31 +++++++++++++-- 5 files changed, 80 insertions(+), 8 deletions(-) diff --git a/src/Core/PS4/GPU/video_out_buffer.h b/src/Core/PS4/GPU/video_out_buffer.h index d3be8090..e3624178 100644 --- a/src/Core/PS4/GPU/video_out_buffer.h +++ b/src/Core/PS4/GPU/video_out_buffer.h @@ -9,4 +9,10 @@ enum class VideoOutBufferFormat : u64 { R8G8B8A8Srgb, B8G8R8A8Srgb, }; + +class VideoOutBufferObj { + public: + explicit VideoOutBufferObj(VideoOutBufferFormat pixel_format, u32 width, u32 height, bool is_tiled, bool is_neo, u32 pitch) { + } +}; } diff --git a/src/Core/PS4/HLE/ErrorCodes.h b/src/Core/PS4/HLE/ErrorCodes.h index 50014a29..06c3014d 100644 --- a/src/Core/PS4/HLE/ErrorCodes.h +++ b/src/Core/PS4/HLE/ErrorCodes.h @@ -17,5 +17,6 @@ constexpr int SCE_VIDEO_OUT_ERROR_RESOURCE_BUSY = 0x80290009; // already constexpr int SCE_VIDEO_OUT_ERROR_INVALID_INDEX = 0x8029000A; // invalid buffer index constexpr int SCE_VIDEO_OUT_ERROR_INVALID_HANDLE = 0x8029000B; // invalid handle constexpr int SCE_VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE = 0x8029000C; // Invalid event queue +constexpr int SCE_VIDEO_OUT_ERROR_SLOT_OCCUPIED = 0x80290010; // slot already used constexpr int SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL = 0x80290012; // flip queue is full constexpr int SCE_VIDEO_OUT_ERROR_INVALID_OPTION = 0x8029001A; // Invalid buffer attribute option diff --git a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h index 238697f9..c586063c 100644 --- a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h +++ b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h @@ -1,12 +1,19 @@ #pragma once #include #include +#include using namespace HLE::Libs::Graphics::VideoOut; namespace HLE::Graphics::Objects { -//class FlipQueue; +struct VideoOutBufferInfo { + const void* buffer = nullptr; + HLE::Libs::Graphics::VideoOutVulkanImage* buffer_render = nullptr; + u64 buffer_size = 0; + u64 buffer_pitch = 0; + int set_id = 0; +}; struct VideoConfigInternal { Lib::Mutex m_mutex; @@ -16,7 +23,7 @@ struct VideoConfigInternal { SceVideoOutVblankStatus m_vblank_status; std::vector m_flip_evtEq; int m_flip_rate = 0; - + VideoOutBufferInfo buffers[16]; std::vector buffers_sets; int buffers_registration_index = 0; }; diff --git a/src/Core/PS4/HLE/Graphics/graphics_ctx.h b/src/Core/PS4/HLE/Graphics/graphics_ctx.h index 074e8626..48972da7 100644 --- a/src/Core/PS4/HLE/Graphics/graphics_ctx.h +++ b/src/Core/PS4/HLE/Graphics/graphics_ctx.h @@ -1,7 +1,7 @@ #pragma once + #include -#include -#include +#include #include "Lib/Threads.h" namespace HLE::Libs::Graphics { @@ -19,6 +19,39 @@ struct GraphicCtx { VkInstance m_instance = nullptr; VkPhysicalDevice m_physical_device = nullptr; VkDevice m_device = nullptr; - VulkanQueueInfo queues[11]; //VULKAN_QUEUES_NUM + VulkanQueueInfo queues[11]; // VULKAN_QUEUES_NUM }; + +enum class VulkanImageType { Unknown, VideoOut}; + +struct VulkanMemory { + VkMemoryRequirements requirements = {}; + VkMemoryPropertyFlags property = 0; + VkDeviceMemory memory = nullptr; + VkDeviceSize offset = 0; + u32 type = 0; + u64 unique_id = 0; +}; + +struct VulkanImage { + static constexpr int VIEW_MAX = 4; + static constexpr int VIEW_DEFAULT = 0; + static constexpr int VIEW_BGRA = 1; + static constexpr int VIEW_DEPTH_TEXTURE = 2; + + explicit VulkanImage(VulkanImageType type) : type(type) {} + + VulkanImageType type = VulkanImageType::Unknown; + VkFormat format = VK_FORMAT_UNDEFINED; + VkExtent2D extent = {}; + VkImage image = nullptr; + VkImageView image_view[VIEW_MAX] = {}; + VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED; + VulkanMemory memory; +}; + +struct VideoOutVulkanImage : public VulkanImage { + VideoOutVulkanImage() : VulkanImage(VulkanImageType::VideoOut) {} +}; + } // namespace HLE::Libs::Graphics \ No newline at end of file diff --git a/src/Core/PS4/HLE/Graphics/video_out.cpp b/src/Core/PS4/HLE/Graphics/video_out.cpp index f5ddeb19..ac0749d1 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.cpp +++ b/src/Core/PS4/HLE/Graphics/video_out.cpp @@ -1,8 +1,10 @@ #include "video_out.h" +#include #include #include #include +#include #include #include #include @@ -12,7 +14,7 @@ #include "Objects/video_out_ctx.h" #include "Util/Singleton.h" -#include +#include "emulator.h" namespace HLE::Libs::Graphics::VideoOut { @@ -160,9 +162,10 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co int registration_index = ctx->buffers_registration_index++; Emulator::checkAndWaitForGraphicsInit(); + // TODO Graphics::RenderCreateCxt(); - //try to calculate buffer size - u64 buffer_size = 1280 * 720 * 4; //TODO hardcoded value should be redone + // try to calculate buffer size + u64 buffer_size = 1280 * 720 * 4; // TODO hardcoded value should be redone u64 buffer_pitch = attribute->pitchInPixel; VideoOutBufferSetInternal buf{}; @@ -174,7 +177,29 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co ctx->buffers_sets.push_back(buf); + GPU::VideoOutBufferFormat format = GPU::VideoOutBufferFormat::Unknown; + if (attribute->pixelFormat == 0x80000000) { + format = GPU::VideoOutBufferFormat::B8G8R8A8Srgb; + } else if (attribute->pixelFormat == 0x80002200) { + format = GPU::VideoOutBufferFormat::R8G8B8A8Srgb; + } + + GPU::VideoOutBufferObj buffer_info(format, attribute->width, attribute->height, attribute->tilingMode == 0, Config::isNeoMode(), buffer_pitch); + + for (int i = 0; i < bufferNum; i++) { + if (ctx->buffers[i + startIndex].buffer != nullptr) { + LOG_TRACE_IF(log_file_videoout, "buffer slot {} is occupied!\n", i + startIndex); + return SCE_VIDEO_OUT_ERROR_SLOT_OCCUPIED; + } + + ctx->buffers[i + startIndex].set_id = registration_index; + ctx->buffers[i + startIndex].buffer = addresses[i]; + ctx->buffers[i + startIndex].buffer_size = buffer_size; + ctx->buffers[i + startIndex].buffer_pitch = buffer_pitch; + // ctx->buffers[i + startIndex].buffer_vulkan = TODO!!! + LOG_INFO_IF(log_file_videoout, "buffers[{}] = {}\n", i + startIndex, reinterpret_cast(addresses[i])); + } return registration_index; } From 1f0beb0ec3afff81ebb0d69a6bfacff76b6b45e2 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Mon, 25 Sep 2023 12:04:40 +0300 Subject: [PATCH 21/32] gpumemory works --- src/Core/PS4/GPU/gpu_memory.cpp | 3 +++ src/Core/PS4/GPU/gpu_memory.h | 11 +++++++++++ src/Core/PS4/GPU/video_out_buffer.h | 3 ++- src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h | 11 +++++++++++ src/Core/PS4/HLE/Graphics/video_out.cpp | 8 ++++++-- src/emulator.cpp | 13 +++++++++++-- src/emulator.h | 1 + 7 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/Core/PS4/GPU/gpu_memory.cpp b/src/Core/PS4/GPU/gpu_memory.cpp index 873f43b5..6b51f022 100644 --- a/src/Core/PS4/GPU/gpu_memory.cpp +++ b/src/Core/PS4/GPU/gpu_memory.cpp @@ -2,4 +2,7 @@ namespace GPU { void MemorySetAllocArea(u64 virtual_addr, u64 size) {} +void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, void* todo, u64 virtual_addr, u64 size, const GPUObject& info) { + return nullptr; +} } // namespace GPU \ No newline at end of file diff --git a/src/Core/PS4/GPU/gpu_memory.h b/src/Core/PS4/GPU/gpu_memory.h index 14084de9..043c075d 100644 --- a/src/Core/PS4/GPU/gpu_memory.h +++ b/src/Core/PS4/GPU/gpu_memory.h @@ -1,9 +1,20 @@ #pragma once #include +#include namespace GPU { enum class MemoryMode : u32 { NoAccess = 0, Read = 1, Write = 2, ReadWrite = 3 }; enum class MemoryObjectType : u64 { InvalidObj, VideoOutBufferObj }; void MemorySetAllocArea(u64 virtual_addr, u64 size); + +class GPUObject { + public: + GPUObject() = default; + virtual ~GPUObject() = default; +}; + +void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/void* todo, u64 virtual_addr, u64 size, + const GPUObject& info); + } // namespace GPU \ No newline at end of file diff --git a/src/Core/PS4/GPU/video_out_buffer.h b/src/Core/PS4/GPU/video_out_buffer.h index e3624178..e07496c9 100644 --- a/src/Core/PS4/GPU/video_out_buffer.h +++ b/src/Core/PS4/GPU/video_out_buffer.h @@ -1,6 +1,7 @@ #pragma once #include +#include "gpu_memory.h" namespace GPU { @@ -10,7 +11,7 @@ enum class VideoOutBufferFormat : u64 { B8G8R8A8Srgb, }; -class VideoOutBufferObj { +class VideoOutBufferObj : public GPUObject { public: explicit VideoOutBufferObj(VideoOutBufferFormat pixel_format, u32 width, u32 height, bool is_tiled, bool is_neo, u32 pitch) { } diff --git a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h index c586063c..6ce3c755 100644 --- a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h +++ b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h @@ -2,6 +2,7 @@ #include #include #include +#include using namespace HLE::Libs::Graphics::VideoOut; @@ -59,9 +60,19 @@ class VideoOutCtx { int Open(); VideoConfigInternal* getCtx(int handle); FlipQueue& getFlipQueue() { return m_flip_queue; } + HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() { + Lib::LockMutexGuard lock(m_mutex); + + if (m_graphic_ctx == nullptr) { + m_graphic_ctx = Emulator::getGraphicCtx(); + } + + return m_graphic_ctx; + } private: Lib::Mutex m_mutex; VideoConfigInternal m_video_out_ctx; FlipQueue m_flip_queue; + HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr; }; }; // namespace HLE::Graphics::Objects \ No newline at end of file diff --git a/src/Core/PS4/HLE/Graphics/video_out.cpp b/src/Core/PS4/HLE/Graphics/video_out.cpp index ac0749d1..52b1e034 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.cpp +++ b/src/Core/PS4/HLE/Graphics/video_out.cpp @@ -15,6 +15,7 @@ #include "Objects/video_out_ctx.h" #include "Util/Singleton.h" #include "emulator.h" +#include namespace HLE::Libs::Graphics::VideoOut { @@ -162,7 +163,7 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co int registration_index = ctx->buffers_registration_index++; Emulator::checkAndWaitForGraphicsInit(); - // TODO Graphics::RenderCreateCxt(); + // TODO Graphics::RenderCreateCtx(); // try to calculate buffer size u64 buffer_size = 1280 * 720 * 4; // TODO hardcoded value should be redone @@ -197,7 +198,10 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co ctx->buffers[i + startIndex].buffer = addresses[i]; ctx->buffers[i + startIndex].buffer_size = buffer_size; ctx->buffers[i + startIndex].buffer_pitch = buffer_pitch; - // ctx->buffers[i + startIndex].buffer_vulkan = TODO!!! + ctx->buffers[i + startIndex].buffer_render = static_cast( + GPU::memoryCreateObj( + 0, videoOut->getGraphicCtx(), nullptr, reinterpret_cast(addresses[i]), buffer_size, buffer_info)); + LOG_INFO_IF(log_file_videoout, "buffers[{}] = {}\n", i + startIndex, reinterpret_cast(addresses[i])); } diff --git a/src/emulator.cpp b/src/emulator.cpp index 91d7b055..dc02102a 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -1,8 +1,9 @@ #include "emulator.h" -#include "Core/PS4/HLE/Graphics/video_out.h" -#include #include +#include + +#include "Core/PS4/HLE/Graphics/video_out.h" namespace Emulator { @@ -91,4 +92,12 @@ void emuRun() { } std::exit(0); } + +HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() { + auto* window_ctx = Singleton::Instance(); + Lib::LockMutexGuard lock(window_ctx->m_mutex); + + return &window_ctx->m_graphic_ctx; +} + } // namespace Emulator \ No newline at end of file diff --git a/src/emulator.h b/src/emulator.h index 39e960e6..ff17a31f 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -79,4 +79,5 @@ struct EmuPrivate { void emuInit(u32 width, u32 height); void emuRun(); void checkAndWaitForGraphicsInit(); +HLE::Libs::Graphics::GraphicCtx* getGraphicCtx(); } // namespace Emulator \ No newline at end of file From 627c0d1b61a7d8b218d0aa589442bf5a336e8555 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Mon, 25 Sep 2023 15:08:36 +0300 Subject: [PATCH 22/32] more gpu memory work --- CMakeLists.txt | 2 +- src/Core/PS4/GPU/gpu_memory.cpp | 42 +++++++++++++++++-- src/Core/PS4/GPU/gpu_memory.h | 20 +++++++-- src/Core/PS4/HLE/Graphics/graphics_render.cpp | 9 ++++ src/Core/PS4/HLE/Graphics/graphics_render.h | 24 +++++++++++ src/Core/PS4/HLE/Graphics/video_out.cpp | 3 +- src/Core/PS4/HLE/Kernel/memory_management.cpp | 2 +- 7 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 src/Core/PS4/HLE/Graphics/graphics_render.cpp create mode 100644 src/Core/PS4/HLE/Graphics/graphics_render.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d720ec92..5d751971 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,7 @@ add_executable(shadps4 src/Core/PS4/HLE/Kernel/event_queues.h src/Core/PS4/HLE/Kernel/cpu_management.cpp src/Core/PS4/HLE/Kernel/cpu_management.h - "src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h" "src/emulator.cpp" "src/emulator.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h" "src/Core/PS4/HLE/Graphics/graphics_ctx.h" "src/vulkan_util.cpp" "src/vulkan_util.h" "src/Core/PS4/GPU/video_out_buffer.cpp" "src/Core/PS4/GPU/video_out_buffer.h") + "src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h" "src/emulator.cpp" "src/emulator.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h" "src/Core/PS4/HLE/Graphics/graphics_ctx.h" "src/vulkan_util.cpp" "src/vulkan_util.h" "src/Core/PS4/GPU/video_out_buffer.cpp" "src/Core/PS4/GPU/video_out_buffer.h" "src/Core/PS4/HLE/Graphics/graphics_render.cpp" "src/Core/PS4/HLE/Graphics/graphics_render.h") find_package(OpenGL REQUIRED) target_link_libraries(shadps4 PUBLIC fmt mincore spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY} vulkan-1 spirv-tools-opt spirv-tools) diff --git a/src/Core/PS4/GPU/gpu_memory.cpp b/src/Core/PS4/GPU/gpu_memory.cpp index 6b51f022..25b7f8c6 100644 --- a/src/Core/PS4/GPU/gpu_memory.cpp +++ b/src/Core/PS4/GPU/gpu_memory.cpp @@ -1,8 +1,42 @@ #include "gpu_memory.h" -namespace GPU { -void MemorySetAllocArea(u64 virtual_addr, u64 size) {} -void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, void* todo, u64 virtual_addr, u64 size, const GPUObject& info) { +#include "Util/Singleton.h" + +void GPU::memorySetAllocArea(u64 virtual_addr, u64 size) { + auto* gpumemory = Singleton::Instance(); + + Lib::LockMutexGuard lock(gpumemory->m_mutex); + + MemoryHeap h; + h.allocated_virtual_addr = virtual_addr; + h.allocated_size = size; + + gpumemory->m_heaps.push_back(h); +} +void* GPU::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, void* todo, u64 virtual_addr, u64 size, const GPUObject& info) { + auto* gpumemory = Singleton::Instance(); + + Lib::LockMutexGuard lock(gpumemory->m_mutex); + + int heap_id = gpumemory->getHeapId(virtual_addr, size); + + if (heap_id < 0) + { + return nullptr; + } return nullptr; } -} // namespace GPU \ No newline at end of file + + +int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) { + int index = 0; + for (const auto& heap : m_heaps) { + if ((virtual_addr >= heap.allocated_virtual_addr && virtual_addr < heap.allocated_virtual_addr + heap.allocated_size) || + ((virtual_addr + size - 1) >= heap.allocated_virtual_addr && + (virtual_addr + size - 1) < heap.allocated_virtual_addr + heap.allocated_size)) { + return index; + } + index++; + } + return -1; +} diff --git a/src/Core/PS4/GPU/gpu_memory.h b/src/Core/PS4/GPU/gpu_memory.h index 043c075d..0a655b62 100644 --- a/src/Core/PS4/GPU/gpu_memory.h +++ b/src/Core/PS4/GPU/gpu_memory.h @@ -1,20 +1,34 @@ #pragma once -#include #include +#include +#include namespace GPU { enum class MemoryMode : u32 { NoAccess = 0, Read = 1, Write = 2, ReadWrite = 3 }; enum class MemoryObjectType : u64 { InvalidObj, VideoOutBufferObj }; -void MemorySetAllocArea(u64 virtual_addr, u64 size); +struct MemoryHeap { + u64 allocated_virtual_addr = 0; + u64 allocated_size = 0; +}; + +class GPUMemory { + public: + GPUMemory() {} + virtual ~GPUMemory() {} + int getHeapId(u64 vaddr, u64 size); + Lib::Mutex m_mutex; + std::vector m_heaps; +}; class GPUObject { public: GPUObject() = default; virtual ~GPUObject() = default; }; -void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/void* todo, u64 virtual_addr, u64 size, +void memorySetAllocArea(u64 virtual_addr, u64 size); +void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, u64 virtual_addr, u64 size, const GPUObject& info); } // namespace GPU \ No newline at end of file diff --git a/src/Core/PS4/HLE/Graphics/graphics_render.cpp b/src/Core/PS4/HLE/Graphics/graphics_render.cpp new file mode 100644 index 00000000..43d9e8ab --- /dev/null +++ b/src/Core/PS4/HLE/Graphics/graphics_render.cpp @@ -0,0 +1,9 @@ +#include "graphics_render.h" +#include "Util/Singleton.h" +#include "emulator.h" + +void GPU::renderCreateCtx() { + auto* render_ctx = Singleton::Instance(); + + render_ctx->setGraphicCtx(Emulator::getGraphicCtx()); +} diff --git a/src/Core/PS4/HLE/Graphics/graphics_render.h b/src/Core/PS4/HLE/Graphics/graphics_render.h new file mode 100644 index 00000000..9b019711 --- /dev/null +++ b/src/Core/PS4/HLE/Graphics/graphics_render.h @@ -0,0 +1,24 @@ +#pragma once +#include "graphics_ctx.h" + +namespace GPU { + +class Framebuffer { + public: + Framebuffer() {} + virtual ~Framebuffer() {} +}; +class RenderCtx { + public: + RenderCtx() : m_framebuffer(new Framebuffer) {} + + virtual ~RenderCtx() {} + void setGraphicCtx(HLE::Libs::Graphics::GraphicCtx* ctx) { m_graphic_ctx = ctx; } + private: + Framebuffer* m_framebuffer = nullptr; + HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr; +}; + + +void renderCreateCtx(); +}; // namespace GPU \ No newline at end of file diff --git a/src/Core/PS4/HLE/Graphics/video_out.cpp b/src/Core/PS4/HLE/Graphics/video_out.cpp index 52b1e034..7db6b895 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.cpp +++ b/src/Core/PS4/HLE/Graphics/video_out.cpp @@ -16,6 +16,7 @@ #include "Util/Singleton.h" #include "emulator.h" #include +#include "graphics_render.h" namespace HLE::Libs::Graphics::VideoOut { @@ -163,7 +164,7 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co int registration_index = ctx->buffers_registration_index++; Emulator::checkAndWaitForGraphicsInit(); - // TODO Graphics::RenderCreateCtx(); + GPU::renderCreateCtx(); // try to calculate buffer size u64 buffer_size = 1280 * 720 * 4; // TODO hardcoded value should be redone diff --git a/src/Core/PS4/HLE/Kernel/memory_management.cpp b/src/Core/PS4/HLE/Kernel/memory_management.cpp index 4897ad38..220e81be 100644 --- a/src/Core/PS4/HLE/Kernel/memory_management.cpp +++ b/src/Core/PS4/HLE/Kernel/memory_management.cpp @@ -120,7 +120,7 @@ int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int fl } if (gpu_mode != GPU::MemoryMode::NoAccess) { - GPU::MemorySetAllocArea(out_addr, len); + GPU::memorySetAllocArea(out_addr, len); } return SCE_OK; } From 7570576aa274e1116d9b1c36fc06bc5dc686dc89 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 26 Sep 2023 03:46:25 +0300 Subject: [PATCH 23/32] more abstract memoryCreateObj --- src/Core/PS4/GPU/gpu_memory.cpp | 35 ++++++++++++++++++++------------- src/Core/PS4/GPU/gpu_memory.h | 5 +++++ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/Core/PS4/GPU/gpu_memory.cpp b/src/Core/PS4/GPU/gpu_memory.cpp index 25b7f8c6..fd5c0ca0 100644 --- a/src/Core/PS4/GPU/gpu_memory.cpp +++ b/src/Core/PS4/GPU/gpu_memory.cpp @@ -2,6 +2,12 @@ #include "Util/Singleton.h" +void* GPU::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, void* todo /*CommandBuffer?*/, u64 virtual_addr, u64 size, const GPUObject& info) { + auto* gpumemory = Singleton::Instance(); + + return gpumemory->memoryCreateObj(submit_id, ctx, nullptr, &virtual_addr, &size, 1, info); +} + void GPU::memorySetAllocArea(u64 virtual_addr, u64 size) { auto* gpumemory = Singleton::Instance(); @@ -13,20 +19,6 @@ void GPU::memorySetAllocArea(u64 virtual_addr, u64 size) { gpumemory->m_heaps.push_back(h); } -void* GPU::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, void* todo, u64 virtual_addr, u64 size, const GPUObject& info) { - auto* gpumemory = Singleton::Instance(); - - Lib::LockMutexGuard lock(gpumemory->m_mutex); - - int heap_id = gpumemory->getHeapId(virtual_addr, size); - - if (heap_id < 0) - { - return nullptr; - } - return nullptr; -} - int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) { int index = 0; @@ -40,3 +32,18 @@ int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) { } return -1; } + +void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, void* todo, const u64* virtual_addr, const u64* size, + int virtual_addr_num, const GPUObject& info) { + auto* gpumemory = Singleton::Instance(); + + Lib::LockMutexGuard lock(gpumemory->m_mutex); + + int heap_id = gpumemory->getHeapId(virtual_addr[0], size[0]); + + if (heap_id < 0) { + return nullptr; + } + // TODO not finished! + return nullptr; +} diff --git a/src/Core/PS4/GPU/gpu_memory.h b/src/Core/PS4/GPU/gpu_memory.h index 0a655b62..2f2fa4c2 100644 --- a/src/Core/PS4/GPU/gpu_memory.h +++ b/src/Core/PS4/GPU/gpu_memory.h @@ -5,6 +5,9 @@ #include namespace GPU { + +class GPUObject; + enum class MemoryMode : u32 { NoAccess = 0, Read = 1, Write = 2, ReadWrite = 3 }; enum class MemoryObjectType : u64 { InvalidObj, VideoOutBufferObj }; @@ -20,6 +23,8 @@ class GPUMemory { int getHeapId(u64 vaddr, u64 size); Lib::Mutex m_mutex; std::vector m_heaps; + void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr, + const u64* size, int virtual_addr_num, const GPUObject& info); }; class GPUObject { public: From 1a5dd6cdfe594cf3f1d3dd6b101f7750c3037f77 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 26 Sep 2023 16:00:13 +0300 Subject: [PATCH 24/32] added XXH3_64bits and calculate memory obj hashes --- .gitmodules | 4 ++++ CMakeLists.txt | 1 + src/Core/PS4/GPU/gpu_memory.cpp | 24 ++++++++++++++++++++++-- src/Core/PS4/GPU/gpu_memory.h | 10 +++++++++- src/Core/PS4/GPU/video_out_buffer.h | 18 +++++++++++++++++- third-party/xxHash | 1 + 6 files changed, 54 insertions(+), 4 deletions(-) create mode 160000 third-party/xxHash diff --git a/.gitmodules b/.gitmodules index 9f2d7480..9cfbedd0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,3 +37,7 @@ path = third-party/vulkan url = https://github.com/shadps4/vulkan.git branch = main +[submodule "third-party/xxHash"] + path = third-party/xxHash + url = https://github.com/Cyan4973/xxHash.git + branch = dev diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d751971..a5a0fe28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ include_directories(third-party/magic_enum/include) include_directories(third-party/zydis/include/Zydis) include_directories(third-party/winpthread/include) include_directories(third-party/vulkan/include) +include_directories(third-party/xxhash/include) add_subdirectory("third-party") #=================== EXAMPLE =================== include_directories(src) diff --git a/src/Core/PS4/GPU/gpu_memory.cpp b/src/Core/PS4/GPU/gpu_memory.cpp index fd5c0ca0..41a73896 100644 --- a/src/Core/PS4/GPU/gpu_memory.cpp +++ b/src/Core/PS4/GPU/gpu_memory.cpp @@ -1,8 +1,11 @@ #include "gpu_memory.h" +#include + #include "Util/Singleton.h" -void* GPU::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, void* todo /*CommandBuffer?*/, u64 virtual_addr, u64 size, const GPUObject& info) { +void* GPU::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, void* todo /*CommandBuffer?*/, u64 virtual_addr, u64 size, + const GPUObject& info) { auto* gpumemory = Singleton::Instance(); return gpumemory->memoryCreateObj(submit_id, ctx, nullptr, &virtual_addr, &size, 1, info); @@ -20,6 +23,8 @@ void GPU::memorySetAllocArea(u64 virtual_addr, u64 size) { gpumemory->m_heaps.push_back(h); } +u64 GPU::calculate_hash(const u08* buf, u64 size) { return (size > 0 && buf != nullptr ? XXH3_64bits(buf, size) : 0); } + int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) { int index = 0; for (const auto& heap : m_heaps) { @@ -44,6 +49,21 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi if (heap_id < 0) { return nullptr; } - // TODO not finished! + + ObjInfo obj = {}; + + // copy parameters from info to obj + for (int i = 0; i < 8; i++) { + obj.obj_params[i] = info.obj_params[i]; + } + u64 hash[3] = {}; // assuming virtual_addr_num shouldn't be more that 3 + + for (int h = 0; h < virtual_addr_num; h++) { + if (info.hasHash) { + hash[h] = GPU::calculate_hash(reinterpret_cast(virtual_addr[h]), size[h]); + } else { + hash[h] = 0; + } + } return nullptr; } diff --git a/src/Core/PS4/GPU/gpu_memory.h b/src/Core/PS4/GPU/gpu_memory.h index 2f2fa4c2..a13697f8 100644 --- a/src/Core/PS4/GPU/gpu_memory.h +++ b/src/Core/PS4/GPU/gpu_memory.h @@ -16,6 +16,9 @@ struct MemoryHeap { u64 allocated_size = 0; }; +struct ObjInfo { + u64 obj_params[8] = {}; +}; class GPUMemory { public: GPUMemory() {} @@ -30,10 +33,15 @@ class GPUObject { public: GPUObject() = default; virtual ~GPUObject() = default; + u64 obj_params[8] = {}; + bool hasHash = false; + bool isReadOnly = false; + MemoryObjectType objectType = MemoryObjectType::InvalidObj; + }; void memorySetAllocArea(u64 virtual_addr, u64 size); void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, u64 virtual_addr, u64 size, const GPUObject& info); - +u64 calculate_hash(const u08* buf, u64 size); } // namespace GPU \ No newline at end of file diff --git a/src/Core/PS4/GPU/video_out_buffer.h b/src/Core/PS4/GPU/video_out_buffer.h index e07496c9..7d9478b9 100644 --- a/src/Core/PS4/GPU/video_out_buffer.h +++ b/src/Core/PS4/GPU/video_out_buffer.h @@ -1,6 +1,7 @@ #pragma once #include + #include "gpu_memory.h" namespace GPU { @@ -13,7 +14,22 @@ enum class VideoOutBufferFormat : u64 { class VideoOutBufferObj : public GPUObject { public: + static constexpr int PIXEL_FORMAT_PARAM = 0; + static constexpr int WIDTH_PARAM = 1; + static constexpr int HEIGHT_PARAM = 2; + static constexpr int IS_TILE_PARAM = 3; + static constexpr int IS_NEO_PARAM = 4; + static constexpr int PITCH_PARAM = 5; + explicit VideoOutBufferObj(VideoOutBufferFormat pixel_format, u32 width, u32 height, bool is_tiled, bool is_neo, u32 pitch) { + obj_params[PIXEL_FORMAT_PARAM] = static_cast(pixel_format); + obj_params[WIDTH_PARAM] = width; + obj_params[HEIGHT_PARAM] = height; + obj_params[IS_TILE_PARAM] = is_tiled ? 1 : 0; + obj_params[IS_NEO_PARAM] = is_neo ? 1 : 0; + obj_params[PITCH_PARAM] = pitch; + hasHash = true; + objectType = GPU::MemoryObjectType::VideoOutBufferObj; } }; -} +} // namespace GPU diff --git a/third-party/xxHash b/third-party/xxHash new file mode 160000 index 00000000..058e54b1 --- /dev/null +++ b/third-party/xxHash @@ -0,0 +1 @@ +Subproject commit 058e54b10b10c658fd50862e6f65f55522afa182 From b14e50904b4a808099668306e09fa9a44284af1e Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 26 Sep 2023 18:56:08 +0300 Subject: [PATCH 25/32] more work on creating videoOutBuffer object --- src/Core/PS4/GPU/gpu_memory.cpp | 20 ++++++++++++++------ src/Core/PS4/GPU/gpu_memory.h | 18 +++++++++++++++++- src/Core/PS4/GPU/video_out_buffer.cpp | 8 ++++++++ src/Core/PS4/GPU/video_out_buffer.h | 4 +++- 4 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/Core/PS4/GPU/gpu_memory.cpp b/src/Core/PS4/GPU/gpu_memory.cpp index 41a73896..4e92e1fa 100644 --- a/src/Core/PS4/GPU/gpu_memory.cpp +++ b/src/Core/PS4/GPU/gpu_memory.cpp @@ -50,20 +50,28 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi return nullptr; } - ObjInfo obj = {}; + ObjInfo objInfo = {}; // copy parameters from info to obj for (int i = 0; i < 8; i++) { - obj.obj_params[i] = info.obj_params[i]; + objInfo.obj_params[i] = info.obj_params[i]; } - u64 hash[3] = {}; // assuming virtual_addr_num shouldn't be more that 3 + + objInfo.gpu_object.objectType = info.objectType; + objInfo.gpu_object.obj = nullptr; for (int h = 0; h < virtual_addr_num; h++) { - if (info.hasHash) { - hash[h] = GPU::calculate_hash(reinterpret_cast(virtual_addr[h]), size[h]); + if (info.check_hash) { + objInfo.hash[h] = GPU::calculate_hash(reinterpret_cast(virtual_addr[h]), size[h]); } else { - hash[h] = 0; + objInfo.hash[h] = 0; } } + objInfo.submit_id = submit_id; + objInfo.check_hash = info.check_hash; + + objInfo.gpu_object.obj = info.getCreateFunc()(ctx, objInfo.obj_params, virtual_addr, size, virtual_addr_num, &objInfo.mem); + + // TODO we need more ... return nullptr; } diff --git a/src/Core/PS4/GPU/gpu_memory.h b/src/Core/PS4/GPU/gpu_memory.h index a13697f8..05ef74e7 100644 --- a/src/Core/PS4/GPU/gpu_memory.h +++ b/src/Core/PS4/GPU/gpu_memory.h @@ -16,9 +16,21 @@ struct MemoryHeap { u64 allocated_size = 0; }; +struct GpuMemoryObject { + MemoryObjectType objectType = MemoryObjectType::InvalidObj; + void* obj = nullptr; +}; + struct ObjInfo { u64 obj_params[8] = {}; + GpuMemoryObject gpu_object; + u64 hash[3] = {}; + u64 submit_id = 0; + bool check_hash = false; + HLE::Libs::Graphics::VulkanMemory mem; }; + + class GPUMemory { public: GPUMemory() {} @@ -34,10 +46,14 @@ class GPUObject { GPUObject() = default; virtual ~GPUObject() = default; u64 obj_params[8] = {}; - bool hasHash = false; + bool check_hash = false; bool isReadOnly = false; MemoryObjectType objectType = MemoryObjectType::InvalidObj; + using create_func_t = void* (*)(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* vaddr, const u64* size, int vaddr_num, + HLE::Libs::Graphics::VulkanMemory* mem); + + virtual create_func_t getCreateFunc() const = 0; }; void memorySetAllocArea(u64 virtual_addr, u64 size); diff --git a/src/Core/PS4/GPU/video_out_buffer.cpp b/src/Core/PS4/GPU/video_out_buffer.cpp index e69de29b..1f4c8fe3 100644 --- a/src/Core/PS4/GPU/video_out_buffer.cpp +++ b/src/Core/PS4/GPU/video_out_buffer.cpp @@ -0,0 +1,8 @@ +#include "video_out_buffer.h" + +static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* vaddr, const u64* size, int vaddr_num, + HLE::Libs::Graphics::VulkanMemory* mem) { + return nullptr;//TODO +} + +GPU::GPUObject::create_func_t GPU::VideoOutBufferObj::getCreateFunc() const { return create_func; } \ No newline at end of file diff --git a/src/Core/PS4/GPU/video_out_buffer.h b/src/Core/PS4/GPU/video_out_buffer.h index 7d9478b9..65da864b 100644 --- a/src/Core/PS4/GPU/video_out_buffer.h +++ b/src/Core/PS4/GPU/video_out_buffer.h @@ -28,8 +28,10 @@ class VideoOutBufferObj : public GPUObject { obj_params[IS_TILE_PARAM] = is_tiled ? 1 : 0; obj_params[IS_NEO_PARAM] = is_neo ? 1 : 0; obj_params[PITCH_PARAM] = pitch; - hasHash = true; + check_hash = true; objectType = GPU::MemoryObjectType::VideoOutBufferObj; } + + create_func_t getCreateFunc() const override; }; } // namespace GPU From 512309c8a03cb2d5b86fc75ab074b746a49326cb Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 26 Sep 2023 20:08:03 +0300 Subject: [PATCH 26/32] even more work on videoOutbuffer --- src/Core/PS4/GPU/gpu_memory.cpp | 33 ++++++++ src/Core/PS4/GPU/gpu_memory.h | 6 +- src/Core/PS4/GPU/video_out_buffer.cpp | 113 +++++++++++++++++++++++++- src/Core/PS4/GPU/video_out_buffer.h | 1 + 4 files changed, 149 insertions(+), 4 deletions(-) diff --git a/src/Core/PS4/GPU/gpu_memory.cpp b/src/Core/PS4/GPU/gpu_memory.cpp index 4e92e1fa..c96183ff 100644 --- a/src/Core/PS4/GPU/gpu_memory.cpp +++ b/src/Core/PS4/GPU/gpu_memory.cpp @@ -25,6 +25,39 @@ void GPU::memorySetAllocArea(u64 virtual_addr, u64 size) { u64 GPU::calculate_hash(const u08* buf, u64 size) { return (size > 0 && buf != nullptr ? XXH3_64bits(buf, size) : 0); } +bool GPU::vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanMemory* mem) { + static std::atomic_uint64_t unique_id = 0; + + VkPhysicalDeviceMemoryProperties memory_properties{}; + vkGetPhysicalDeviceMemoryProperties(ctx->m_physical_device, &memory_properties); + + u32 index = 0; + for (; index < memory_properties.memoryTypeCount; index++) { + if ((mem->requirements.memoryTypeBits & (static_cast(1) << index)) != 0 && + (memory_properties.memoryTypes[index].propertyFlags & mem->property) == mem->property) { + break; + } + } + + mem->type = index; + mem->offset = 0; + + VkMemoryAllocateInfo alloc_info{}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.pNext = nullptr; + alloc_info.allocationSize = mem->requirements.size; + alloc_info.memoryTypeIndex = index; + + mem->unique_id = ++unique_id; + + auto result = vkAllocateMemory(ctx->m_device, &alloc_info, nullptr, &mem->memory); + + if (result == VK_SUCCESS) { + return true; + } + return false; +} + int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) { int index = 0; for (const auto& heap : m_heaps) { diff --git a/src/Core/PS4/GPU/gpu_memory.h b/src/Core/PS4/GPU/gpu_memory.h index 05ef74e7..eb234b44 100644 --- a/src/Core/PS4/GPU/gpu_memory.h +++ b/src/Core/PS4/GPU/gpu_memory.h @@ -50,14 +50,18 @@ class GPUObject { bool isReadOnly = false; MemoryObjectType objectType = MemoryObjectType::InvalidObj; - using create_func_t = void* (*)(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* vaddr, const u64* size, int vaddr_num, + using create_func_t = void* (*)(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* virtual_addr, const u64* size, int virtual_addr_num, HLE::Libs::Graphics::VulkanMemory* mem); + using update_func_t = void (*)(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, void* obj, const u64* virtual_addr, const u64* size, + int virtual_addr_num); virtual create_func_t getCreateFunc() const = 0; + virtual update_func_t getUpdateFunc() const = 0; }; void memorySetAllocArea(u64 virtual_addr, u64 size); void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, u64 virtual_addr, u64 size, const GPUObject& info); u64 calculate_hash(const u08* buf, u64 size); +bool vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanMemory* mem); } // namespace GPU \ No newline at end of file diff --git a/src/Core/PS4/GPU/video_out_buffer.cpp b/src/Core/PS4/GPU/video_out_buffer.cpp index 1f4c8fe3..00455b5c 100644 --- a/src/Core/PS4/GPU/video_out_buffer.cpp +++ b/src/Core/PS4/GPU/video_out_buffer.cpp @@ -1,8 +1,115 @@ #include "video_out_buffer.h" -static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* vaddr, const u64* size, int vaddr_num, +#include + +#include "debug.h" + +constexpr bool log_file_videoOutBuffer = true; // disable it to disable logging + +static void update_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, void* obj, const u64* virtual_addr, const u64* size, + int virtual_addr_num) {} + +static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* virtual_addr, const u64* size, int virtual_addr_num, HLE::Libs::Graphics::VulkanMemory* mem) { - return nullptr;//TODO + auto pixel_format = params[GPU::VideoOutBufferObj::PIXEL_FORMAT_PARAM]; + auto width = params[GPU::VideoOutBufferObj::WIDTH_PARAM]; + auto height = params[GPU::VideoOutBufferObj::HEIGHT_PARAM]; + + auto* vk_obj = new HLE::Libs::Graphics::VideoOutVulkanImage; + + VkFormat vk_format = VK_FORMAT_UNDEFINED; + + switch (pixel_format) { + case static_cast(GPU::VideoOutBufferFormat::R8G8B8A8Srgb): vk_format = VK_FORMAT_R8G8B8A8_SRGB; break; + case static_cast(GPU::VideoOutBufferFormat::B8G8R8A8Srgb): vk_format = VK_FORMAT_B8G8R8A8_SRGB; break; + default: LOG_CRITICAL_IF(log_file_videoOutBuffer, "unknown pixelFormat = {}\n", pixel_format); std::exit(0); + } + + vk_obj->extent.width = width; + vk_obj->extent.height = height; + vk_obj->format = vk_format; + vk_obj->image = nullptr; + vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED; + + for (auto& view : vk_obj->image_view) { + view = nullptr; + } + + VkImageCreateInfo image_info{}; + image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_info.pNext = nullptr; + image_info.flags = 0; + image_info.imageType = VK_IMAGE_TYPE_2D; + image_info.extent.width = vk_obj->extent.width; + image_info.extent.height = vk_obj->extent.height; + image_info.extent.depth = 1; + image_info.mipLevels = 1; + image_info.arrayLayers = 1; + image_info.format = vk_obj->format; + image_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_info.initialLayout = vk_obj->layout; + image_info.usage = + static_cast(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT) | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; + + vkCreateImage(ctx->m_device, &image_info, nullptr, &vk_obj->image); + + if (vk_obj->image == nullptr) { + LOG_CRITICAL_IF(log_file_videoOutBuffer, "vk_obj->image is null\n"); + std::exit(0); + } + + vkGetImageMemoryRequirements(ctx->m_device, vk_obj->image, &mem->requirements); + + mem->property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + + bool allocated = GPU::vulkanAllocateMemory(ctx, mem); + + if (!allocated) { + LOG_CRITICAL_IF(log_file_videoOutBuffer, "can't allocate vulkan memory\n"); + std::exit(0); + } + + vkBindImageMemory(ctx->m_device, vk_obj->image, mem->memory, mem->offset); + + vk_obj->memory = *mem; + + LOG_INFO_IF(log_file_videoOutBuffer, "videoOutBuffer create object\n"); + LOG_INFO_IF(log_file_videoOutBuffer, "mem requirements.size = {}\n", mem->requirements.size); + LOG_INFO_IF(log_file_videoOutBuffer, "width = {}\n", width); + LOG_INFO_IF(log_file_videoOutBuffer, "height = {}\n", height); + LOG_INFO_IF(log_file_videoOutBuffer, "size = {}\n", *size); + + update_func(ctx, params, vk_obj, virtual_addr, size, virtual_addr_num); + + VkImageViewCreateInfo create_info{}; + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.image = vk_obj->image; + create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + create_info.format = vk_obj->format; + create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + create_info.subresourceRange.baseArrayLayer = 0; + create_info.subresourceRange.baseMipLevel = 0; + create_info.subresourceRange.layerCount = 1; + create_info.subresourceRange.levelCount = 1; + + vkCreateImageView(ctx->m_device, &create_info, nullptr, &vk_obj->image_view[HLE::Libs::Graphics::VulkanImage::VIEW_DEFAULT]); + + if (vk_obj->image_view[HLE::Libs::Graphics::VulkanImage::VIEW_DEFAULT] == nullptr) { + LOG_CRITICAL_IF(log_file_videoOutBuffer, "vk_obj->image_view is null\n"); + std::exit(0); + } + + return vk_obj; } -GPU::GPUObject::create_func_t GPU::VideoOutBufferObj::getCreateFunc() const { return create_func; } \ No newline at end of file +GPU::GPUObject::create_func_t GPU::VideoOutBufferObj::getCreateFunc() const { return create_func; } + +GPU::GPUObject::update_func_t GPU::VideoOutBufferObj::getUpdateFunc() const { return update_func; } diff --git a/src/Core/PS4/GPU/video_out_buffer.h b/src/Core/PS4/GPU/video_out_buffer.h index 65da864b..ed459efe 100644 --- a/src/Core/PS4/GPU/video_out_buffer.h +++ b/src/Core/PS4/GPU/video_out_buffer.h @@ -33,5 +33,6 @@ class VideoOutBufferObj : public GPUObject { } create_func_t getCreateFunc() const override; + update_func_t getUpdateFunc() const override; }; } // namespace GPU From c6633a511ae3ba2c5b215ee5e37706b641125a71 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 26 Sep 2023 20:40:02 +0300 Subject: [PATCH 27/32] small adjustments --- src/Core/PS4/HLE/Graphics/video_out.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/PS4/HLE/Graphics/video_out.cpp b/src/Core/PS4/HLE/Graphics/video_out.cpp index 7db6b895..95b2957c 100644 --- a/src/Core/PS4/HLE/Graphics/video_out.cpp +++ b/src/Core/PS4/HLE/Graphics/video_out.cpp @@ -167,7 +167,7 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co GPU::renderCreateCtx(); // try to calculate buffer size - u64 buffer_size = 1280 * 720 * 4; // TODO hardcoded value should be redone + u64 buffer_size = 1280 * 768 * 4; // TODO hardcoded value should be redone u64 buffer_pitch = attribute->pitchInPixel; VideoOutBufferSetInternal buf{}; @@ -203,7 +203,7 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co GPU::memoryCreateObj( 0, videoOut->getGraphicCtx(), nullptr, reinterpret_cast(addresses[i]), buffer_size, buffer_info)); - LOG_INFO_IF(log_file_videoout, "buffers[{}] = {}\n", i + startIndex, reinterpret_cast(addresses[i])); + LOG_INFO_IF(log_file_videoout, "buffers[{}] = {}\n", i + startIndex, log_hex_full(reinterpret_cast(addresses[i]))); } return registration_index; From 21120ac0ae1880a4a9840a2d04a7333960530021 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 27 Sep 2023 07:45:05 +0300 Subject: [PATCH 28/32] finished gpu buffer creation --- src/Core/PS4/GPU/gpu_memory.cpp | 24 ++++++++++++++++++++++-- src/Core/PS4/GPU/gpu_memory.h | 23 +++++++++++++++++++---- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/Core/PS4/GPU/gpu_memory.cpp b/src/Core/PS4/GPU/gpu_memory.cpp index c96183ff..a17e0469 100644 --- a/src/Core/PS4/GPU/gpu_memory.cpp +++ b/src/Core/PS4/GPU/gpu_memory.cpp @@ -82,6 +82,7 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi if (heap_id < 0) { return nullptr; } + auto& heap = m_heaps[heap_id]; ObjInfo objInfo = {}; @@ -105,6 +106,25 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi objInfo.gpu_object.obj = info.getCreateFunc()(ctx, objInfo.obj_params, virtual_addr, size, virtual_addr_num, &objInfo.mem); - // TODO we need more ... - return nullptr; + int index = static_cast(heap.objects.size()); + + HeapObject hobj{}; + hobj.block = createHeapBlock(virtual_addr, size, virtual_addr_num, heap_id, index); + hobj.info = objInfo; + hobj.free = false; + heap.objects.push_back(hobj); + + return objInfo.gpu_object.obj; +} + +GPU::HeapBlock GPU::GPUMemory::createHeapBlock(const u64* virtual_addr, const u64* size, int virtual_addr_num, int heap_id, int obj_id) { + auto& heap = m_heaps[heap_id]; + + GPU::HeapBlock heapBlock{}; + heapBlock.virtual_addr_num = virtual_addr_num; + for (int vi = 0; vi < virtual_addr_num; vi++) { + heapBlock.virtual_addr[vi] = virtual_addr[vi]; + heapBlock.size[vi] = size[vi]; + } + return heapBlock; } diff --git a/src/Core/PS4/GPU/gpu_memory.h b/src/Core/PS4/GPU/gpu_memory.h index eb234b44..7690cd06 100644 --- a/src/Core/PS4/GPU/gpu_memory.h +++ b/src/Core/PS4/GPU/gpu_memory.h @@ -11,10 +11,7 @@ class GPUObject; enum class MemoryMode : u32 { NoAccess = 0, Read = 1, Write = 2, ReadWrite = 3 }; enum class MemoryObjectType : u64 { InvalidObj, VideoOutBufferObj }; -struct MemoryHeap { - u64 allocated_virtual_addr = 0; - u64 allocated_size = 0; -}; + struct GpuMemoryObject { MemoryObjectType objectType = MemoryObjectType::InvalidObj; @@ -30,6 +27,23 @@ struct ObjInfo { HLE::Libs::Graphics::VulkanMemory mem; }; +struct HeapBlock { + u64 virtual_addr[3] = {}; + u64 size[3] = {}; + int virtual_addr_num = 0; +}; + +struct HeapObject { + HeapBlock block; + ObjInfo info; + bool free = true; +}; + +struct MemoryHeap { + u64 allocated_virtual_addr = 0; + u64 allocated_size = 0; + std::vector objects; +}; class GPUMemory { public: @@ -40,6 +54,7 @@ class GPUMemory { std::vector m_heaps; void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr, const u64* size, int virtual_addr_num, const GPUObject& info); + HeapBlock createHeapBlock(const u64* virtual_addr, const u64* size, int virtual_addr_num, int heap_id, int obj_id); }; class GPUObject { public: From 98ccbe7f302ff7d2113cc93d6859da47fcf779cf Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 27 Sep 2023 08:34:02 +0300 Subject: [PATCH 29/32] update gpu memory function --- src/Core/PS4/GPU/gpu_memory.cpp | 58 +++++++++++++++++++++++ src/Core/PS4/GPU/gpu_memory.h | 70 ++++++++++++++-------------- src/Core/PS4/HLE/LibSceGnmDriver.cpp | 5 +- 3 files changed, 98 insertions(+), 35 deletions(-) diff --git a/src/Core/PS4/GPU/gpu_memory.cpp b/src/Core/PS4/GPU/gpu_memory.cpp index a17e0469..39591892 100644 --- a/src/Core/PS4/GPU/gpu_memory.cpp +++ b/src/Core/PS4/GPU/gpu_memory.cpp @@ -58,6 +58,11 @@ bool GPU::vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs:: return false; } +void GPU::flushGarlic(HLE::Libs::Graphics::GraphicCtx* ctx) { + auto* gpumemory = Singleton::Instance(); + gpumemory->flushAllHeaps(ctx); +} + int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) { int index = 0; for (const auto& heap : m_heaps) { @@ -106,6 +111,7 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi objInfo.gpu_object.obj = info.getCreateFunc()(ctx, objInfo.obj_params, virtual_addr, size, virtual_addr_num, &objInfo.mem); + objInfo.update_func = info.getUpdateFunc(); int index = static_cast(heap.objects.size()); HeapObject hobj{}; @@ -128,3 +134,55 @@ GPU::HeapBlock GPU::GPUMemory::createHeapBlock(const u64* virtual_addr, const u6 } return heapBlock; } + +void GPU::GPUMemory::update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, int heap_id, int obj_id) { + auto& heap = m_heaps[heap_id]; + + auto& heapObj = heap.objects[obj_id]; + auto& objInfo = heapObj.info; + bool need_update = false; + + if (submit_id > objInfo.submit_id) { + uint64_t hash[3] = {}; + + for (int i = 0; i < heapObj.block.virtual_addr_num; i++) { + if (objInfo.check_hash) { + hash[i] = GPU::calculate_hash(reinterpret_cast(heapObj.block.virtual_addr[i]), heapObj.block.size[i]); + } else { + hash[i] = 0; + } + } + + for (int i = 0; i < heapObj.block.virtual_addr_num; i++) { + if (objInfo.hash[i] != hash[i]) { + need_update = true; + objInfo.hash[i] = hash[i]; + } + } + + if (submit_id != UINT64_MAX) { + objInfo.submit_id = submit_id; + } + } + + if (need_update) { + objInfo.update_func(ctx, objInfo.obj_params, objInfo.gpu_object.obj, heapObj.block.virtual_addr, heapObj.block.size, + heapObj.block.virtual_addr_num); + } +} + +void GPU::GPUMemory::flushAllHeaps(HLE::Libs::Graphics::GraphicCtx* ctx) { + Lib::LockMutexGuard lock(m_mutex); + + int heap_id = 0; + for (auto& heap : m_heaps) { + int index = 0; + for (auto& heapObj : heap.objects) { + if (!heapObj.free) { + update(UINT64_MAX, ctx, heap_id, index); + } + index++; + } + heap_id++; + } +} diff --git a/src/Core/PS4/GPU/gpu_memory.h b/src/Core/PS4/GPU/gpu_memory.h index 7690cd06..f7612649 100644 --- a/src/Core/PS4/GPU/gpu_memory.h +++ b/src/Core/PS4/GPU/gpu_memory.h @@ -11,51 +11,17 @@ class GPUObject; enum class MemoryMode : u32 { NoAccess = 0, Read = 1, Write = 2, ReadWrite = 3 }; enum class MemoryObjectType : u64 { InvalidObj, VideoOutBufferObj }; - - struct GpuMemoryObject { MemoryObjectType objectType = MemoryObjectType::InvalidObj; void* obj = nullptr; }; -struct ObjInfo { - u64 obj_params[8] = {}; - GpuMemoryObject gpu_object; - u64 hash[3] = {}; - u64 submit_id = 0; - bool check_hash = false; - HLE::Libs::Graphics::VulkanMemory mem; -}; - struct HeapBlock { u64 virtual_addr[3] = {}; u64 size[3] = {}; int virtual_addr_num = 0; }; -struct HeapObject { - HeapBlock block; - ObjInfo info; - bool free = true; -}; - -struct MemoryHeap { - u64 allocated_virtual_addr = 0; - u64 allocated_size = 0; - std::vector objects; -}; - -class GPUMemory { - public: - GPUMemory() {} - virtual ~GPUMemory() {} - int getHeapId(u64 vaddr, u64 size); - Lib::Mutex m_mutex; - std::vector m_heaps; - void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr, - const u64* size, int virtual_addr_num, const GPUObject& info); - HeapBlock createHeapBlock(const u64* virtual_addr, const u64* size, int virtual_addr_num, int heap_id, int obj_id); -}; class GPUObject { public: GPUObject() = default; @@ -74,9 +40,45 @@ class GPUObject { virtual update_func_t getUpdateFunc() const = 0; }; +struct ObjInfo { + u64 obj_params[8] = {}; + GpuMemoryObject gpu_object; + u64 hash[3] = {}; + u64 submit_id = 0; + bool check_hash = false; + HLE::Libs::Graphics::VulkanMemory mem; + GPU::GPUObject::update_func_t update_func = nullptr; +}; + +struct HeapObject { + HeapBlock block; + ObjInfo info; + bool free = true; +}; +struct MemoryHeap { + u64 allocated_virtual_addr = 0; + u64 allocated_size = 0; + std::vector objects; +}; + +class GPUMemory { + public: + GPUMemory() {} + virtual ~GPUMemory() {} + int getHeapId(u64 vaddr, u64 size); + Lib::Mutex m_mutex; + std::vector m_heaps; + void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr, + const u64* size, int virtual_addr_num, const GPUObject& info); + HeapBlock createHeapBlock(const u64* virtual_addr, const u64* size, int virtual_addr_num, int heap_id, int obj_id); + void update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, int heap_id, int obj_id); + void flushAllHeaps(HLE::Libs::Graphics::GraphicCtx* ctx); +}; + void memorySetAllocArea(u64 virtual_addr, u64 size); void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, u64 virtual_addr, u64 size, const GPUObject& info); u64 calculate_hash(const u08* buf, u64 size); bool vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanMemory* mem); +void flushGarlic(HLE::Libs::Graphics::GraphicCtx* ctx); } // namespace GPU \ No newline at end of file diff --git a/src/Core/PS4/HLE/LibSceGnmDriver.cpp b/src/Core/PS4/HLE/LibSceGnmDriver.cpp index cc48ba45..9744b23f 100644 --- a/src/Core/PS4/HLE/LibSceGnmDriver.cpp +++ b/src/Core/PS4/HLE/LibSceGnmDriver.cpp @@ -3,6 +3,8 @@ #include "../Loader/Elf.h" #include #include +#include +#include namespace HLE::Libs::LibSceGnmDriver { @@ -88,7 +90,8 @@ namespace HLE::Libs::LibSceGnmDriver { void sceGnmDriverTraceInProgress(){} void sceGnmDriverTriggerCapture(){} void sceGnmEndWorkload(){} - void sceGnmFlushGarlic() { PRINT_DUMMY_FUNCTION_NAME(); + void sceGnmFlushGarlic() { PRINT_FUNCTION_NAME(); + GPU::flushGarlic(Emulator::getGraphicCtx()); } void sceGnmGetEqEventType(){} void sceGnmGetEqTimeStamp(){} From 3b853413c7550604efedc724bcec95851ff3d6f1 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 27 Sep 2023 09:26:50 +0300 Subject: [PATCH 30/32] preparing for drawing --- src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp | 6 ++++++ src/emulator.cpp | 2 ++ src/emulator.h | 1 + 3 files changed, 9 insertions(+) diff --git a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp index afc6426f..aa77713d 100644 --- a/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp +++ b/src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp @@ -76,6 +76,12 @@ bool FlipQueue::flip(u32 micros) { auto request = m_requests.at(0); // proceed first request m_mutex.UnlockMutex(); + auto* buffer = request.cfg->buffers[request.index].buffer_render; + + Emulator::DrawBuffer(buffer); + + m_mutex.LockMutex(); + request.cfg->m_mutex.LockMutex(); for (auto& flip_eq : request.cfg->m_flip_evtEq) { if (flip_eq != nullptr) { diff --git a/src/emulator.cpp b/src/emulator.cpp index dc02102a..e9b1539d 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -100,4 +100,6 @@ HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() { return &window_ctx->m_graphic_ctx; } +void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image) {} + } // namespace Emulator \ No newline at end of file diff --git a/src/emulator.h b/src/emulator.h index ff17a31f..b3d2c0e3 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -80,4 +80,5 @@ void emuInit(u32 width, u32 height); void emuRun(); void checkAndWaitForGraphicsInit(); HLE::Libs::Graphics::GraphicCtx* getGraphicCtx(); +void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image); } // namespace Emulator \ No newline at end of file From abe6d392956dbe085e8eb5ae11ef2ddede425359 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 27 Sep 2023 15:15:18 +0300 Subject: [PATCH 31/32] more on buffer rendering, added vulkan command pool --- src/Core/PS4/HLE/Graphics/graphics_ctx.h | 10 + src/Core/PS4/HLE/Graphics/graphics_render.cpp | 189 ++++++++++++++++++ src/Core/PS4/HLE/Graphics/graphics_render.h | 40 +++- src/emulator.cpp | 97 ++++++++- 4 files changed, 334 insertions(+), 2 deletions(-) diff --git a/src/Core/PS4/HLE/Graphics/graphics_ctx.h b/src/Core/PS4/HLE/Graphics/graphics_ctx.h index 48972da7..01103466 100644 --- a/src/Core/PS4/HLE/Graphics/graphics_ctx.h +++ b/src/Core/PS4/HLE/Graphics/graphics_ctx.h @@ -6,6 +6,16 @@ namespace HLE::Libs::Graphics { +struct VulkanCommandPool { + Lib::Mutex mutex; + VkCommandPool pool = nullptr; + VkCommandBuffer* buffers = nullptr; + VkFence* fences = nullptr; + VkSemaphore* semaphores = nullptr; + bool* busy = nullptr; + u32 buffers_count = 0; +}; + struct VulkanQueueInfo { Lib::Mutex* mutex = nullptr; u32 family = static_cast(-1); diff --git a/src/Core/PS4/HLE/Graphics/graphics_render.cpp b/src/Core/PS4/HLE/Graphics/graphics_render.cpp index 43d9e8ab..b5db11cf 100644 --- a/src/Core/PS4/HLE/Graphics/graphics_render.cpp +++ b/src/Core/PS4/HLE/Graphics/graphics_render.cpp @@ -1,9 +1,198 @@ #include "graphics_render.h" + #include "Util/Singleton.h" #include "emulator.h" +static thread_local GPU::CommandPool g_command_pool; + void GPU::renderCreateCtx() { auto* render_ctx = Singleton::Instance(); render_ctx->setGraphicCtx(Emulator::getGraphicCtx()); } + +void GPU::CommandBuffer::allocateBuffer() { + m_pool = g_command_pool.getPool(m_queue); + + Lib::LockMutexGuard lock(m_pool->mutex); + + for (uint32_t i = 0; i < m_pool->buffers_count; i++) { + if (!m_pool->busy[i]) { + m_pool->busy[i] = true; + vkResetCommandBuffer(m_pool->buffers[i], VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); + m_index = i; + break; + } + } +} + +void GPU::CommandBuffer::freeBuffer() { + Lib::LockMutexGuard lock(m_pool->mutex); + + waitForFence(); + + m_pool->busy[m_index] = false; + vkResetCommandBuffer(m_pool->buffers[m_index], VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); + m_index = static_cast(-1); +} + +void GPU::CommandBuffer::waitForFence() { + auto* render_ctx = Singleton::Instance(); + + if (m_execute) { + auto* device = render_ctx->getGraphicCtx()->m_device; + + vkWaitForFences(device, 1, &m_pool->fences[m_index], VK_TRUE, UINT64_MAX); + vkResetFences(device, 1, &m_pool->fences[m_index]); + + m_execute = false; + } +} +void GPU::CommandBuffer::begin() const { + auto* buffer = m_pool->buffers[m_index]; + + VkCommandBufferBeginInfo begin_info{}; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.pNext = nullptr; + begin_info.flags = 0; + begin_info.pInheritanceInfo = nullptr; + + auto result = vkBeginCommandBuffer(buffer, &begin_info); + + if (result != VK_SUCCESS) { + printf("vkBeginCommandBuffer failed\n"); + std::exit(0); + } +} +void GPU::CommandBuffer::end() const { + auto* buffer = m_pool->buffers[m_index]; + + auto result = vkEndCommandBuffer(buffer); + + if (result != VK_SUCCESS) { + printf("vkEndCommandBuffer failed\n"); + std::exit(0); + } +} +void GPU::CommandBuffer::executeWithSemaphore() { + auto* buffer = m_pool->buffers[m_index]; + auto* fence = m_pool->fences[m_index]; + + VkSubmitInfo submit_info{}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 0; + submit_info.pWaitSemaphores = nullptr; + submit_info.pWaitDstStageMask = nullptr; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &buffer; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &m_pool->semaphores[m_index]; + + auto* render_ctx = Singleton::Instance(); + const auto& queue = render_ctx->getGraphicCtx()->queues[m_queue]; + + if (queue.mutex != nullptr) { + queue.mutex->LockMutex(); + } + + auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence); + + if (queue.mutex != nullptr) { + queue.mutex->LockMutex(); + } + + m_execute = true; + + if (result != VK_SUCCESS) { + printf("vkQueueSubmit failed\n"); + std::exit(0); + } +} +void GPU::CommandPool::createPool(int id) { + auto* render_ctx = Singleton::Instance(); + auto* ctx = render_ctx->getGraphicCtx(); + + m_pool[id] = new HLE::Libs::Graphics::VulkanCommandPool; + + VkCommandPoolCreateInfo pool_info{}; + pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + pool_info.pNext = nullptr; + pool_info.queueFamilyIndex = ctx->queues[id].family; + pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + + vkCreateCommandPool(ctx->m_device, &pool_info, nullptr, &m_pool[id]->pool); + + if (m_pool[id]->pool == nullptr) { + printf("pool is nullptr"); + std::exit(0); + } + + m_pool[id]->buffers_count = 4; + m_pool[id]->buffers = new VkCommandBuffer[m_pool[id]->buffers_count]; + m_pool[id]->fences = new VkFence[m_pool[id]->buffers_count]; + m_pool[id]->semaphores = new VkSemaphore[m_pool[id]->buffers_count]; + m_pool[id]->busy = new bool[m_pool[id]->buffers_count]; + + VkCommandBufferAllocateInfo alloc_info{}; + alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + alloc_info.commandPool = m_pool[id]->pool; + alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + alloc_info.commandBufferCount = m_pool[id]->buffers_count; + + if (vkAllocateCommandBuffers(ctx->m_device, &alloc_info, m_pool[id]->buffers) != VK_SUCCESS) { + printf("Can't allocate command buffers\n"); + std::exit(0); + } + + for (uint32_t i = 0; i < m_pool[id]->buffers_count; i++) { + m_pool[id]->busy[i] = false; + + VkFenceCreateInfo fence_info{}; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_info.pNext = nullptr; + fence_info.flags = 0; + + if (vkCreateFence(ctx->m_device, &fence_info, nullptr, &m_pool[id]->fences[i]) != VK_SUCCESS) { + printf("Can't create fence\n"); + std::exit(0); + } + + VkSemaphoreCreateInfo semaphore_info{}; + semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + semaphore_info.pNext = nullptr; + semaphore_info.flags = 0; + + if (vkCreateSemaphore(ctx->m_device, &semaphore_info, nullptr, &m_pool[id]->semaphores[i]) != VK_SUCCESS) { + printf("Can't create semas\n"); + std::exit(0); + } + } +} + +void GPU::CommandPool::deleteAllPool() { + auto* render_ctx = Singleton::Instance(); + auto* ctx = render_ctx->getGraphicCtx(); + + for (auto& pool : m_pool) { + if (pool != nullptr) { + for (uint32_t i = 0; i < pool->buffers_count; i++) { + vkDestroySemaphore(ctx->m_device, pool->semaphores[i], nullptr); + vkDestroyFence(ctx->m_device, pool->fences[i], nullptr); + } + + vkFreeCommandBuffers(ctx->m_device, pool->pool, pool->buffers_count, pool->buffers); + + vkDestroyCommandPool(ctx->m_device, pool->pool, nullptr); + + delete[] pool->semaphores; + delete[] pool->fences; + delete[] pool->buffers; + delete[] pool->busy; + + delete pool; + pool = nullptr; + } + } +} + diff --git a/src/Core/PS4/HLE/Graphics/graphics_render.h b/src/Core/PS4/HLE/Graphics/graphics_render.h index 9b019711..aa3bbd6a 100644 --- a/src/Core/PS4/HLE/Graphics/graphics_render.h +++ b/src/Core/PS4/HLE/Graphics/graphics_render.h @@ -3,6 +3,43 @@ namespace GPU { +class CommandPool { + public: + CommandPool() = default; + ~CommandPool() {} + + HLE::Libs::Graphics::VulkanCommandPool* getPool(int id) { + if (m_pool[id] == nullptr) { + createPool(id); + } + return m_pool[id]; + } + + private: + void createPool(int id); + void deleteAllPool(); + + HLE::Libs::Graphics::VulkanCommandPool* m_pool[11] = {}; +}; +class CommandBuffer { + public: + explicit CommandBuffer(int queue) : m_queue(queue) { allocateBuffer(); } + virtual ~CommandBuffer() { freeBuffer(); } + void allocateBuffer(); + void freeBuffer(); + void waitForFence(); + void begin() const; + void end() const; + void executeWithSemaphore(); + u32 getIndex() const { return m_index; } + HLE::Libs::Graphics::VulkanCommandPool* getPool() { return m_pool; } + private: + int m_queue = -1; + u32 m_index = static_cast(-1); + HLE::Libs::Graphics::VulkanCommandPool* m_pool = nullptr; + bool m_execute = false; +}; + class Framebuffer { public: Framebuffer() {} @@ -14,11 +51,12 @@ class RenderCtx { virtual ~RenderCtx() {} void setGraphicCtx(HLE::Libs::Graphics::GraphicCtx* ctx) { m_graphic_ctx = ctx; } + HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() { return m_graphic_ctx; } + private: Framebuffer* m_framebuffer = nullptr; HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr; }; - void renderCreateCtx(); }; // namespace GPU \ No newline at end of file diff --git a/src/emulator.cpp b/src/emulator.cpp index e9b1539d..29b31e9f 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -1,5 +1,6 @@ #include "emulator.h" +#include #include #include @@ -100,6 +101,100 @@ HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() { return &window_ctx->m_graphic_ctx; } -void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image) {} +void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image) { + auto* window_ctx = Singleton::Instance(); + if (window_ctx->is_window_hidden) { + SDL_ShowWindow(window_ctx->m_window); + window_ctx->is_window_hidden = false; + } + + window_ctx->swapchain->current_index = static_cast(-1); + + auto result = vkAcquireNextImageKHR(window_ctx->m_graphic_ctx.m_device, window_ctx->swapchain->swapchain, UINT64_MAX, nullptr, + window_ctx->swapchain->present_complete_fence, &window_ctx->swapchain->current_index); + + if (result != VK_SUCCESS) { + printf("Can't aquireNextImage\n"); + std::exit(0); + } + if (window_ctx->swapchain->current_index == static_cast(-1)) { + printf("Unsupported:swapchain current index is -1\n"); + std::exit(0); + } + + do { + result = vkWaitForFences(window_ctx->m_graphic_ctx.m_device, 1, &window_ctx->swapchain->present_complete_fence, VK_TRUE, 100000000); + } while (result == VK_TIMEOUT); + if (result != VK_SUCCESS) { + printf("vkWaitForFences is not success\n"); + std::exit(0); + } + + vkResetFences(window_ctx->m_graphic_ctx.m_device, 1, &window_ctx->swapchain->present_complete_fence); + + auto* blt_src_image = image; + auto* blt_dst_image = window_ctx->swapchain; + + if (blt_src_image == nullptr) { + printf("blt_src_image is null\n"); + std::exit(0); + } + if (blt_dst_image == nullptr) { + printf("blt_dst_image is null\n"); + std::exit(0); + } + + GPU::CommandBuffer buffer(10); + + auto* vk_buffer = buffer.getPool()->buffers[buffer.getIndex()]; + + buffer.begin(); + + //UtilBlitImage(&buffer, blt_src_image, blt_dst_image); + + VkImageMemoryBarrier pre_present_barrier{}; + pre_present_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + pre_present_barrier.pNext = nullptr; + pre_present_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + pre_present_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + pre_present_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + pre_present_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + pre_present_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + pre_present_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + pre_present_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + pre_present_barrier.subresourceRange.baseMipLevel = 0; + pre_present_barrier.subresourceRange.levelCount = 1; + pre_present_barrier.subresourceRange.baseArrayLayer = 0; + pre_present_barrier.subresourceRange.layerCount = 1; + pre_present_barrier.image = window_ctx->swapchain->swapchain_images[window_ctx->swapchain->current_index]; + vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, + &pre_present_barrier); + + buffer.end(); + buffer.executeWithSemaphore(); + + VkPresentInfoKHR present{}; + present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + present.pNext = nullptr; + present.swapchainCount = 1; + present.pSwapchains = &window_ctx->swapchain->swapchain; + present.pImageIndices = &window_ctx->swapchain->current_index; + present.pWaitSemaphores = &buffer.getPool()->semaphores[buffer.getIndex()]; + present.waitSemaphoreCount = 1; + present.pResults = nullptr; + + const auto& queue = window_ctx->m_graphic_ctx.queues[10]; + + if (queue.mutex != nullptr) { + printf("queue.mutexe is null\n"); + std::exit(0); + } + + result = vkQueuePresentKHR(queue.vk_queue, &present); + if (result != VK_SUCCESS) { + printf("vkQueuePresentKHR failed\n"); + std::exit(0); + } +} } // namespace Emulator \ No newline at end of file From 05fdea61fc72b7a942bd4796db33fd66606044f1 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 27 Sep 2023 22:47:53 +0300 Subject: [PATCH 32/32] more work on graphics . tiles are not yet supported --- src/Core/PS4/GPU/video_out_buffer.cpp | 13 +- src/Core/PS4/HLE/Graphics/graphics_ctx.h | 8 +- src/Core/PS4/HLE/Graphics/graphics_render.cpp | 36 +++- src/Core/PS4/HLE/Graphics/graphics_render.h | 1 + src/emulator.cpp | 2 +- src/vulkan_util.cpp | 179 +++++++++++++++++- src/vulkan_util.h | 8 + 7 files changed, 242 insertions(+), 5 deletions(-) diff --git a/src/Core/PS4/GPU/video_out_buffer.cpp b/src/Core/PS4/GPU/video_out_buffer.cpp index 00455b5c..73483a91 100644 --- a/src/Core/PS4/GPU/video_out_buffer.cpp +++ b/src/Core/PS4/GPU/video_out_buffer.cpp @@ -3,11 +3,22 @@ #include #include "debug.h" +#include constexpr bool log_file_videoOutBuffer = true; // disable it to disable logging static void update_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, void* obj, const u64* virtual_addr, const u64* size, - int virtual_addr_num) {} + int virtual_addr_num) { + + auto pitch = params[GPU::VideoOutBufferObj::PITCH_PARAM]; + + auto* vk_obj = static_cast(obj); + + vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED; + + Graphics::Vulkan::vulkanFillImage(ctx, vk_obj, reinterpret_cast(*virtual_addr), *size, pitch, + static_cast(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); +} static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* virtual_addr, const u64* size, int virtual_addr_num, HLE::Libs::Graphics::VulkanMemory* mem) { diff --git a/src/Core/PS4/HLE/Graphics/graphics_ctx.h b/src/Core/PS4/HLE/Graphics/graphics_ctx.h index 01103466..5b7eb493 100644 --- a/src/Core/PS4/HLE/Graphics/graphics_ctx.h +++ b/src/Core/PS4/HLE/Graphics/graphics_ctx.h @@ -2,6 +2,7 @@ #include #include + #include "Lib/Threads.h" namespace HLE::Libs::Graphics { @@ -32,7 +33,7 @@ struct GraphicCtx { VulkanQueueInfo queues[11]; // VULKAN_QUEUES_NUM }; -enum class VulkanImageType { Unknown, VideoOut}; +enum class VulkanImageType { Unknown, VideoOut }; struct VulkanMemory { VkMemoryRequirements requirements = {}; @@ -43,6 +44,11 @@ struct VulkanMemory { u64 unique_id = 0; }; +struct VulkanBuffer { + VkBuffer buffer = nullptr; + VulkanMemory memory; + VkBufferUsageFlags usage = 0; +}; struct VulkanImage { static constexpr int VIEW_MAX = 4; static constexpr int VIEW_DEFAULT = 0; diff --git a/src/Core/PS4/HLE/Graphics/graphics_render.cpp b/src/Core/PS4/HLE/Graphics/graphics_render.cpp index b5db11cf..e02bdf7b 100644 --- a/src/Core/PS4/HLE/Graphics/graphics_render.cpp +++ b/src/Core/PS4/HLE/Graphics/graphics_render.cpp @@ -109,6 +109,41 @@ void GPU::CommandBuffer::executeWithSemaphore() { std::exit(0); } } +void GPU::CommandBuffer::execute() { + auto* buffer = m_pool->buffers[m_index]; + auto* fence = m_pool->fences[m_index]; + + VkSubmitInfo submit_info{}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 0; + submit_info.pWaitSemaphores = nullptr; + submit_info.pWaitDstStageMask = nullptr; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &buffer; + submit_info.signalSemaphoreCount = 0; + submit_info.pSignalSemaphores = nullptr; + + auto* render_ctx = Singleton::Instance(); + const auto& queue = render_ctx->getGraphicCtx()->queues[m_queue]; + + if (queue.mutex != nullptr) { + queue.mutex->LockMutex(); + } + + auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence); + + if (queue.mutex != nullptr) { + queue.mutex->UnlockMutex(); + } + + m_execute = true; + + if (result != VK_SUCCESS) { + printf("vkQueueSubmit failed\n"); + std::exit(0); + } +} void GPU::CommandPool::createPool(int id) { auto* render_ctx = Singleton::Instance(); auto* ctx = render_ctx->getGraphicCtx(); @@ -195,4 +230,3 @@ void GPU::CommandPool::deleteAllPool() { } } } - diff --git a/src/Core/PS4/HLE/Graphics/graphics_render.h b/src/Core/PS4/HLE/Graphics/graphics_render.h index aa3bbd6a..b98197de 100644 --- a/src/Core/PS4/HLE/Graphics/graphics_render.h +++ b/src/Core/PS4/HLE/Graphics/graphics_render.h @@ -31,6 +31,7 @@ class CommandBuffer { void begin() const; void end() const; void executeWithSemaphore(); + void execute(); u32 getIndex() const { return m_index; } HLE::Libs::Graphics::VulkanCommandPool* getPool() { return m_pool; } private: diff --git a/src/emulator.cpp b/src/emulator.cpp index 29b31e9f..74bd15ff 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -150,7 +150,7 @@ void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image) { buffer.begin(); - //UtilBlitImage(&buffer, blt_src_image, blt_dst_image); + Graphics::Vulkan::vulkanBlitImage(&buffer, blt_src_image, blt_dst_image); VkImageMemoryBarrier pre_present_barrier{}; pre_present_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index bf3b84b0..42bf21eb 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -1,5 +1,6 @@ #include "vulkan_util.h" +#include #include #include #include @@ -181,6 +182,7 @@ Emulator::VulkanSwapchain* Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Gr return s; } + void Graphics::Vulkan::vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emulator::VulkanQueues& queues) { auto get_queue = [ctx](int id, const Emulator::VulkanQueueInfo& info, bool with_mutex = false) { ctx->queues[id].family = info.family; @@ -424,4 +426,179 @@ void Graphics::Vulkan::vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_de break; } } -} \ No newline at end of file +} + +static void set_image_layout(VkCommandBuffer buffer, HLE::Libs::Graphics::VulkanImage* dst_image, uint32_t base_level, uint32_t levels, + VkImageAspectFlags aspect_mask, VkImageLayout old_image_layout, VkImageLayout new_image_layout) { + VkImageMemoryBarrier imageMemoryBarrier{}; + imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageMemoryBarrier.pNext = nullptr; + imageMemoryBarrier.srcAccessMask = 0; + imageMemoryBarrier.dstAccessMask = 0; + imageMemoryBarrier.oldLayout = old_image_layout; + imageMemoryBarrier.newLayout = new_image_layout; + imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageMemoryBarrier.image = dst_image->image; + imageMemoryBarrier.subresourceRange.aspectMask = aspect_mask; + imageMemoryBarrier.subresourceRange.baseMipLevel = base_level; + imageMemoryBarrier.subresourceRange.levelCount = levels; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.subresourceRange.layerCount = 1; + + if (old_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { + imageMemoryBarrier.srcAccessMask = 0; + } + + if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + imageMemoryBarrier.dstAccessMask = 0; + } + + if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) { + imageMemoryBarrier.dstAccessMask = 0; + } + + if (old_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + imageMemoryBarrier.srcAccessMask = 0; + } + + if (old_image_layout == VK_IMAGE_LAYOUT_PREINITIALIZED) { + imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; + } + + if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + imageMemoryBarrier.srcAccessMask = 0; + imageMemoryBarrier.dstAccessMask = 0; + } + + if (new_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { + imageMemoryBarrier.dstAccessMask = 0; + } + + if (new_image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + imageMemoryBarrier.dstAccessMask = 0; + } + + VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + + vkCmdPipelineBarrier(buffer, src_stages, dest_stages, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); + + dst_image->layout = new_image_layout; +} + +void Graphics::Vulkan::vulkanBlitImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanImage* src_image, + Emulator::VulkanSwapchain* dst_swapchain) { + auto* vk_buffer = buffer->getPool()->buffers[buffer->getIndex()]; + + HLE::Libs::Graphics::VulkanImage swapchain_image(HLE::Libs::Graphics::VulkanImageType::Unknown); + + swapchain_image.image = dst_swapchain->swapchain_images[dst_swapchain->current_index]; + swapchain_image.layout = VK_IMAGE_LAYOUT_UNDEFINED; + + set_image_layout(vk_buffer, src_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + set_image_layout(vk_buffer, &swapchain_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + VkImageBlit region{}; + region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.srcSubresource.mipLevel = 0; + region.srcSubresource.baseArrayLayer = 0; + region.srcSubresource.layerCount = 1; + region.srcOffsets[0].x = 0; + region.srcOffsets[0].y = 0; + region.srcOffsets[0].z = 0; + region.srcOffsets[1].x = static_cast(src_image->extent.width); + region.srcOffsets[1].y = static_cast(src_image->extent.height); + region.srcOffsets[1].z = 1; + region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.dstSubresource.mipLevel = 0; + region.dstSubresource.baseArrayLayer = 0; + region.dstSubresource.layerCount = 1; + region.dstOffsets[0].x = 0; + region.dstOffsets[0].y = 0; + region.dstOffsets[0].z = 0; + region.dstOffsets[1].x = static_cast(dst_swapchain->swapchain_extent.width); + region.dstOffsets[1].y = static_cast(dst_swapchain->swapchain_extent.height); + region.dstOffsets[1].z = 1; + + vkCmdBlitImage(vk_buffer, src_image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapchain_image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, + ®ion, VK_FILTER_LINEAR); + + set_image_layout(vk_buffer, src_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); +} + +void Graphics::Vulkan::vulkanFillImage(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanImage* dst_image, const void* src_data, + u64 size, u32 src_pitch, u64 dst_layout) { + HLE::Libs::Graphics::VulkanBuffer staging_buffer{}; + staging_buffer.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + staging_buffer.memory.property = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + vulkanCreateBuffer(ctx, size, &staging_buffer); + + void* data = nullptr; + vkMapMemory(ctx->m_device, staging_buffer.memory.memory, staging_buffer.memory.offset, staging_buffer.memory.requirements.size, 0, &data); + std::memcpy(data, src_data, size); + vkUnmapMemory(ctx->m_device, staging_buffer.memory.memory); + + GPU::CommandBuffer buffer(9); + + buffer.begin(); + vulkanBufferToImage(&buffer, &staging_buffer, src_pitch, dst_image, dst_layout); + buffer.end(); + buffer.execute(); + buffer.waitForFence(); + + vulkanDeleteBuffer(ctx, &staging_buffer); +} + +void Graphics::Vulkan::vulkanBufferToImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanBuffer* src_buffer, u32 src_pitch, + HLE::Libs::Graphics::VulkanImage* dst_image, u64 dst_layout) { + auto* vk_buffer = buffer->getPool()->buffers[buffer->getIndex()]; + + set_image_layout(vk_buffer, dst_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + VkBufferImageCopy region{}; + region.bufferOffset = 0; + region.bufferRowLength = (src_pitch != dst_image->extent.width ? src_pitch : 0); + region.bufferImageHeight = 0; + + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + + region.imageOffset = {0, 0, 0}; + region.imageExtent = {dst_image->extent.width, dst_image->extent.height, 1}; + + vkCmdCopyBufferToImage(vk_buffer, src_buffer->buffer, dst_image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + set_image_layout(vk_buffer, dst_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + static_cast(dst_layout)); +} + +void Graphics::Vulkan::vulkanCreateBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, u64 size, HLE::Libs::Graphics::VulkanBuffer* buffer) { + VkBufferCreateInfo buffer_info{}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = size; + buffer_info.usage = buffer->usage; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + vkCreateBuffer(ctx->m_device, &buffer_info, nullptr, &buffer->buffer); + + vkGetBufferMemoryRequirements(ctx->m_device, buffer->buffer, &buffer->memory.requirements); + + bool allocated = GPU::vulkanAllocateMemory(ctx, &buffer->memory); + if (!allocated) { + printf("Can't allocate vulkan\n"); + std::exit(0); + } + vkBindBufferMemory(ctx->m_device, buffer->buffer, buffer->memory.memory, buffer->memory.offset); +} + +void Graphics::Vulkan::vulkanDeleteBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanBuffer* buffer) { + vkDestroyBuffer(ctx->m_device, buffer->buffer, nullptr); + vkFreeMemory(ctx->m_device, buffer->memory.memory, nullptr); + buffer->memory.memory = nullptr; + buffer->buffer = nullptr; +} diff --git a/src/vulkan_util.h b/src/vulkan_util.h index d082c196..e25d9880 100644 --- a/src/vulkan_util.h +++ b/src/vulkan_util.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include @@ -36,4 +37,11 @@ Emulator::VulkanQueues vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR su void vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, Emulator::VulkanSurfaceCapabilities* surfaceCap); void vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emulator::VulkanQueues& queues); Emulator::VulkanSwapchain* vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count); +void vulkanBlitImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanImage* src_image, Emulator::VulkanSwapchain* dst_swapchain); +void vulkanFillImage(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanImage* dst_image, const void* src_data, u64 size, u32 src_pitch, + u64 dst_layout); +void vulkanBufferToImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanBuffer* src_buffer, u32 src_pitch, + HLE::Libs::Graphics::VulkanImage* dst_image, u64 dst_layout); +void vulkanCreateBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, u64 size, HLE::Libs::Graphics::VulkanBuffer* buffer); +void vulkanDeleteBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanBuffer* buffer); }; // namespace Graphics::Vulkan \ No newline at end of file