mirror of
https://github.com/SysRay/psOff_public.git
synced 2024-10-07 11:53:25 +00:00
+ imgui
This commit is contained in:
parent
812b20f966
commit
bbf3d661df
@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.24)
|
||||
include(ExternalProject)
|
||||
|
||||
set(PSOFF_LIB_VERSION v.0.0)
|
||||
set(PSOFF_LIB_VERSION v.0.2)
|
||||
set(PSOFF_RENDER_VERSION v.0.5-nightly_29.04.24-fix)
|
||||
|
||||
set(ProjectName psOff_${CMAKE_BUILD_TYPE})
|
||||
|
@ -47,6 +47,7 @@ target_link_libraries(core PRIVATE
|
||||
IPHLPAPI.lib
|
||||
Ws2_32.lib
|
||||
ntdll.dll
|
||||
imgui
|
||||
VulkanMemoryAllocator
|
||||
${Vulkan_LIBRARIES}
|
||||
)
|
||||
|
@ -1,12 +1,16 @@
|
||||
add_library(videoout OBJECT
|
||||
videoout.cpp
|
||||
imageHandler.cpp
|
||||
|
||||
vulkan/vulkanSetup.cpp
|
||||
vulkan/vulkanHelper.cpp
|
||||
imageHandler.cpp
|
||||
|
||||
overlay/overlay.cpp
|
||||
)
|
||||
|
||||
add_dependencies(videoout third_party psOff_utility gamereport initParams config_emu psoff_render)
|
||||
|
||||
target_include_directories(videoout PRIVATE
|
||||
${Vulkan_INCLUDE_DIRS}
|
||||
)
|
||||
${CMAKE_BINARY_DIR}/third_party/src/third_party/include
|
||||
)
|
@ -32,7 +32,8 @@ class ImageHandler: public IImageHandler {
|
||||
|
||||
uint32_t m_countImages = 0;
|
||||
|
||||
std::vector<VkImage> m_scImages;
|
||||
std::vector<VkImage> m_srcImages;
|
||||
std::vector<VkImageView> m_srcImageViews;
|
||||
// - vulkan
|
||||
|
||||
boost::mutex m_mutexInt;
|
||||
@ -96,9 +97,9 @@ void ImageHandler::recreate() {
|
||||
|
||||
uint32_t numImages = 0;
|
||||
vkGetSwapchainImagesKHR(m_deviceInfo->device, m_swapchain, &numImages, nullptr);
|
||||
m_scImages.resize(numImages);
|
||||
m_srcImages.resize(numImages);
|
||||
|
||||
vkGetSwapchainImagesKHR(m_deviceInfo->device, m_swapchain, &numImages, m_scImages.data());
|
||||
vkGetSwapchainImagesKHR(m_deviceInfo->device, m_swapchain, &numImages, m_srcImages.data());
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,7 +156,8 @@ std::optional<ImageData> ImageHandler::getImage_blocking() {
|
||||
m_nextIndex = (++m_nextIndex) % m_maxImages;
|
||||
++m_countImages;
|
||||
|
||||
imageData.swapchainImage = m_scImages[imageData.index];
|
||||
imageData.swapchainImage = m_srcImages[imageData.index];
|
||||
imageData.imageView = m_srcImageViews[imageData.index];
|
||||
|
||||
imageData.extent = m_extentWindow;
|
||||
|
||||
@ -261,9 +263,32 @@ void ImageHandler::init(vulkan::VulkanObj* obj, VkSurfaceKHR surface) {
|
||||
{ // swapchain images
|
||||
uint32_t numImages = 0;
|
||||
vkGetSwapchainImagesKHR(m_deviceInfo->device, m_swapchain, &numImages, nullptr);
|
||||
m_scImages.resize(numImages);
|
||||
m_srcImages.resize(numImages);
|
||||
m_srcImageViews.resize(numImages);
|
||||
|
||||
vkGetSwapchainImagesKHR(m_deviceInfo->device, m_swapchain, &numImages, m_scImages.data());
|
||||
vkGetSwapchainImagesKHR(m_deviceInfo->device, m_swapchain, &numImages, m_srcImages.data());
|
||||
|
||||
for (size_t n = 0; n < numImages; ++n) {
|
||||
VkImageViewCreateInfo createInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.image = m_srcImages[n],
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = m_imageFormat, // todo swizzle?
|
||||
.components = {},
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1u,
|
||||
},
|
||||
};
|
||||
|
||||
vkCreateImageView(m_deviceInfo->device, &createInfo, nullptr, &m_srcImageViews[n]);
|
||||
}
|
||||
}
|
||||
|
||||
{ // Command buffer
|
||||
@ -304,8 +329,12 @@ void ImageHandler::deinit() {
|
||||
for (auto& fence: m_fenceSubmit) {
|
||||
vkDestroyFence(m_deviceInfo->device, fence, nullptr);
|
||||
}
|
||||
for (auto& view: m_srcImageViews) {
|
||||
vkDestroyImageView(m_deviceInfo->device, view, nullptr);
|
||||
}
|
||||
|
||||
if (m_commandPool != nullptr) vkDestroyCommandPool(m_deviceInfo->device, m_commandPool, nullptr);
|
||||
|
||||
if (m_swapchain != nullptr) vkDestroySwapchainKHR(m_deviceInfo->device, m_swapchain, nullptr);
|
||||
|
||||
printf("deinit ImageHandler| done\n");
|
||||
|
@ -6,7 +6,9 @@
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
struct ImageData {
|
||||
VkImage swapchainImage = nullptr;
|
||||
VkImage swapchainImage = nullptr;
|
||||
VkImageView imageView = nullptr;
|
||||
|
||||
VkSemaphore semImageReady = nullptr; /// image is ready for operation
|
||||
VkSemaphore semImageCopied = nullptr; /// Image has been copied, ready to swap
|
||||
VkCommandBuffer cmdBuffer = nullptr; /// Commandbuffer to be used for transer etc. Already called begin!
|
||||
|
165
core/videoout/overlay/overlay.cpp
Normal file
165
core/videoout/overlay/overlay.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
#include "overlay.h"
|
||||
|
||||
#include "../imageHandler.h"
|
||||
#include "logging.h"
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui/imgui_impl_sdl2.h>
|
||||
#include <imgui/imgui_impl_vulkan.h>
|
||||
#include <vulkan/vk_enum_string_helper.h>
|
||||
|
||||
LOG_DEFINE_MODULE(Overlay);
|
||||
|
||||
class OverlayHandler: public IOverlayHandler {
|
||||
std::shared_ptr<vulkan::DeviceInfo> m_deviceInfo;
|
||||
|
||||
VkDescriptorPool m_descriptorPool;
|
||||
|
||||
bool m_isInit = false, m_isStop = false;
|
||||
|
||||
void init(SDL_Window* window, vulkan::QueueInfo* queue, VkFormat displayFormat);
|
||||
void draw();
|
||||
|
||||
public:
|
||||
OverlayHandler(std::shared_ptr<vulkan::DeviceInfo>& deviceInfo, SDL_Window* window, vulkan::QueueInfo* queue, VkFormat displayFormat)
|
||||
: m_deviceInfo(deviceInfo) {
|
||||
init(window, queue, displayFormat);
|
||||
}
|
||||
|
||||
virtual ~OverlayHandler() {
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
vkDestroyDescriptorPool(m_deviceInfo->device, m_descriptorPool, nullptr);
|
||||
}
|
||||
|
||||
// ### Interface
|
||||
void stop() final { m_isStop = true; }
|
||||
|
||||
void submit(ImageData const& imageData) final;
|
||||
|
||||
void processEvent(SDL_Event const* event) final {
|
||||
[[unlikely]] if (!m_isInit || !m_isStop)
|
||||
return;
|
||||
ImGui_ImplSDL2_ProcessEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<IOverlayHandler> createOverlay(std::shared_ptr<vulkan::DeviceInfo>& deviceInfo, SDL_Window* window, vulkan::QueueInfo* queue,
|
||||
VkFormat displayFormat) {
|
||||
return std::make_unique<OverlayHandler>(deviceInfo, window, queue, displayFormat);
|
||||
}
|
||||
|
||||
void OverlayHandler::init(SDL_Window* window, vulkan::QueueInfo* queue, VkFormat displayFormat) {
|
||||
LOG_USE_MODULE(Overlay);
|
||||
|
||||
// Create intern vulkan data
|
||||
VkDescriptorPoolSize poolSizes[] = {{VK_DESCRIPTOR_TYPE_SAMPLER, 1000},
|
||||
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000},
|
||||
{VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000},
|
||||
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000},
|
||||
{VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000},
|
||||
{VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000},
|
||||
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000},
|
||||
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000},
|
||||
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000},
|
||||
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000},
|
||||
{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000}};
|
||||
|
||||
VkDescriptorPoolCreateInfo poolInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
|
||||
.maxSets = 1000,
|
||||
.poolSizeCount = std::size(poolSizes),
|
||||
.pPoolSizes = poolSizes,
|
||||
};
|
||||
|
||||
if (auto res = vkCreateDescriptorPool(m_deviceInfo->device, &poolInfo, nullptr, &m_descriptorPool); res != VK_SUCCESS) {
|
||||
LOG_ERR(L"Couldn't create descriptor pool %S", string_VkResult(res));
|
||||
return;
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
// ImGui::StyleColorsLight();
|
||||
|
||||
ImGui_ImplSDL2_InitForVulkan(window);
|
||||
|
||||
ImGui_ImplVulkan_InitInfo initInfo = {
|
||||
.Instance = m_deviceInfo->instance,
|
||||
.PhysicalDevice = m_deviceInfo->physicalDevice,
|
||||
.Device = m_deviceInfo->device,
|
||||
.QueueFamily = queue->family,
|
||||
.Queue = queue->queue,
|
||||
.DescriptorPool = m_descriptorPool,
|
||||
.RenderPass = nullptr, // Dynamic
|
||||
.MinImageCount = 2,
|
||||
.ImageCount = 3,
|
||||
.MSAASamples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.PipelineCache = nullptr,
|
||||
.Subpass = 0,
|
||||
.UseDynamicRendering = true,
|
||||
.PipelineRenderingCreateInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachmentFormats = &displayFormat,
|
||||
},
|
||||
|
||||
.Allocator = nullptr,
|
||||
.CheckVkResultFn = nullptr,
|
||||
|
||||
};
|
||||
|
||||
ImGui_ImplVulkan_Init(&initInfo);
|
||||
|
||||
m_isInit = true;
|
||||
}
|
||||
|
||||
void OverlayHandler::submit(ImageData const& imageData) {
|
||||
[[unlikely]] if (!m_isInit || m_isStop)
|
||||
return;
|
||||
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::Render();
|
||||
ImDrawData* drawData = ImGui::GetDrawData();
|
||||
|
||||
VkRenderingAttachmentInfo colorInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.imageView = imageData.imageView,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.resolveMode = VK_RESOLVE_MODE_NONE,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.clearValue = {},
|
||||
};
|
||||
|
||||
VkRenderingInfo renderingInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
||||
.renderArea = {{}, imageData.extent},
|
||||
.layerCount = 1,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachments = &colorInfo,
|
||||
.pDepthAttachment = nullptr,
|
||||
.pStencilAttachment = nullptr,
|
||||
};
|
||||
|
||||
vkCmdBeginRendering(imageData.cmdBuffer, &renderingInfo);
|
||||
ImGui_ImplVulkan_RenderDrawData(drawData, imageData.cmdBuffer);
|
||||
vkCmdEndRendering(imageData.cmdBuffer);
|
||||
}
|
||||
|
||||
void OverlayHandler::draw() {
|
||||
ImGui::ShowDemoWindow();
|
||||
}
|
28
core/videoout/overlay/overlay.h
Normal file
28
core/videoout/overlay/overlay.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include "../vulkan/vulkanSetup.h"
|
||||
#include "core/videoout/vulkan/vulkanTypes.h"
|
||||
#include "utility/utility.h"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <memory>
|
||||
|
||||
struct ImageData;
|
||||
|
||||
class IOverlayHandler {
|
||||
CLASS_NO_COPY(IOverlayHandler);
|
||||
|
||||
protected:
|
||||
IOverlayHandler() = default;
|
||||
|
||||
public:
|
||||
virtual ~IOverlayHandler() = default;
|
||||
|
||||
virtual void stop() = 0;
|
||||
|
||||
virtual void submit(ImageData const& imageData) = 0;
|
||||
|
||||
virtual void processEvent(SDL_Event const* event) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IOverlayHandler> createOverlay(std::shared_ptr<vulkan::DeviceInfo>& deviceInfo, SDL_Window* window, vulkan::QueueInfo* queue,
|
||||
VkFormat displayFormat);
|
@ -13,6 +13,7 @@
|
||||
#include "modules/libSceVideoOut/codes.h"
|
||||
#include "modules/libSceVideoOut/types.h"
|
||||
#include "modules_include/common.h"
|
||||
#include "overlay/overlay.h"
|
||||
#include "vulkan/vulkanHelper.h"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
@ -172,8 +173,10 @@ class VideoOut: public IVideoOut, private IEventsGraphics {
|
||||
|
||||
vulkan::VulkanObj* m_vulkanObj = nullptr;
|
||||
|
||||
std::unique_ptr<IGraphics> m_graphics;
|
||||
std::unique_ptr<IImageHandler> m_imageHandler;
|
||||
std::unique_ptr<IGraphics> m_graphics;
|
||||
|
||||
std::unique_ptr<IImageHandler> m_imageHandler;
|
||||
std::unique_ptr<IOverlayHandler> m_overlayHandler;
|
||||
|
||||
std::thread m_threadSDL2;
|
||||
std::condition_variable m_condSDL2;
|
||||
@ -332,6 +335,8 @@ VideoOut::~VideoOut() {
|
||||
// printf("VideoOut| waiting on gpu idle\n");
|
||||
m_imageHandler->stop();
|
||||
m_graphics->stop();
|
||||
m_overlayHandler->stop();
|
||||
|
||||
vkQueueWaitIdle(m_imageHandler->getQueue()->queue);
|
||||
|
||||
// shutdown graphics first (uses vulkan)
|
||||
@ -347,6 +352,8 @@ VideoOut::~VideoOut() {
|
||||
m_imageHandler->deinit();
|
||||
m_imageHandler.reset();
|
||||
|
||||
m_overlayHandler.reset();
|
||||
|
||||
printf("VideoOut| Destroy vulkan\n");
|
||||
|
||||
deinitVulkan(m_vulkanObj);
|
||||
@ -492,6 +499,7 @@ int VideoOut::SDLInit(uint32_t flags) {
|
||||
void VideoOut::transferDisplay(ImageData const& imageData, vulkan::SwapchainData::DisplayBuffers& displayBufferMeta, VkSemaphore waitSema, size_t waitValue) {
|
||||
|
||||
vulkan::transfer2Display(&displayBufferMeta, imageData, m_graphics.get());
|
||||
m_overlayHandler->submit(imageData);
|
||||
vulkan::submitDisplayTransfer(&displayBufferMeta, imageData, m_imageHandler->getQueue(), waitSema, waitValue);
|
||||
}
|
||||
|
||||
@ -782,9 +790,11 @@ std::thread VideoOut::createSDLThread() {
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
||||
|
||||
// SDL polling helper
|
||||
auto func_pollSDL = [](auto& window) {
|
||||
auto func_pollSDL = [&](auto& window) {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
m_overlayHandler->processEvent(&event);
|
||||
|
||||
switch (event.type) {
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event.window.event) {
|
||||
@ -926,6 +936,9 @@ std::thread VideoOut::createSDLThread() {
|
||||
queue, &window);
|
||||
m_imageHandler->init(m_vulkanObj, window.surface);
|
||||
|
||||
auto [format, _] = vulkan::getDisplayFormat(m_vulkanObj);
|
||||
m_overlayHandler = createOverlay(m_vulkanObj->deviceInfo, window.window, queue, format);
|
||||
|
||||
*item.result = 0;
|
||||
} else {
|
||||
vulkan::createSurface(m_vulkanObj, window.window, window.surface);
|
||||
|
@ -80,6 +80,10 @@ void submitDisplayTransfer(SwapchainData::DisplayBuffers const* displayBuffer, I
|
||||
size_t waitValue) {
|
||||
LOG_USE_MODULE(vulkanHelper);
|
||||
|
||||
if (vkEndCommandBuffer(imageData.cmdBuffer) != VK_SUCCESS) {
|
||||
LOG_CRIT(L"Couldn't end commandbuffer");
|
||||
}
|
||||
|
||||
size_t waitValues[] = {0, waitValue};
|
||||
uint32_t waitCount = waitSema != nullptr ? 2 : 1;
|
||||
|
||||
@ -89,7 +93,7 @@ void submitDisplayTransfer(SwapchainData::DisplayBuffers const* displayBuffer, I
|
||||
.pWaitSemaphoreValues = waitValues,
|
||||
};
|
||||
|
||||
VkPipelineStageFlags waitStage[] = {VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT};
|
||||
VkPipelineStageFlags waitStage[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT};
|
||||
VkSemaphore sems[] = {imageData.semImageReady, waitSema};
|
||||
|
||||
VkSubmitInfo const submitInfo {
|
||||
@ -155,12 +159,6 @@ void transfer2Display(SwapchainData::DisplayBuffers const* displayBuffer, ImageD
|
||||
vkCmdPipelineBarrier(imageData.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
}
|
||||
// - Present layout
|
||||
|
||||
// End CmdBuffer -> Submit
|
||||
if (vkEndCommandBuffer(imageData.cmdBuffer) != VK_SUCCESS) {
|
||||
LOG_CRIT(L"Couldn't end commandbuffer");
|
||||
}
|
||||
// -
|
||||
}
|
||||
|
||||
void presentImage(ImageData const& imageData, VkSwapchainKHR swapchain, QueueInfo const* queue) {
|
||||
|
Loading…
Reference in New Issue
Block a user