From d580dc6cddf3b16f13d9201b3fa586ea9836f982 Mon Sep 17 00:00:00 2001 From: CocoSimone Date: Fri, 5 Aug 2022 13:58:35 +0200 Subject: [PATCH] Imgui and ParallelRDP stuff --- external/parallel-rdp/CMakeLists.txt | 4 + external/parallel-rdp/ParallelRDPWrapper.cpp | 16 +- external/parallel-rdp/ParallelRDPWrapper.hpp | 6 +- src/cores/BaseCore.hpp | 5 + src/cores/n64/CMakeLists.txt | 4 +- src/cores/n64/Core.cpp | 2 - src/cores/n64/Core.hpp | 1 + src/cores/n64/core/CMakeLists.txt | 2 + src/frontend/App.cpp | 6 +- src/frontend/App.hpp | 4 +- src/frontend/CMakeLists.txt | 10 +- src/frontend/imgui/CMakeLists.txt | 8 +- src/frontend/imgui/Window.cpp | 400 +++++-------------- src/frontend/imgui/Window.hpp | 13 +- 14 files changed, 162 insertions(+), 319 deletions(-) diff --git a/external/parallel-rdp/CMakeLists.txt b/external/parallel-rdp/CMakeLists.txt index c1060f8f..fb3bd79d 100644 --- a/external/parallel-rdp/CMakeLists.txt +++ b/external/parallel-rdp/CMakeLists.txt @@ -58,6 +58,10 @@ target_include_directories(parallel-rdp PUBLIC ../../src/cores parallel-rdp-standalone .. + ../../src/frontend + ../imgui + ../imgui/imgui + ../imgui/imgui/backends ) if(WIN32) diff --git a/external/parallel-rdp/ParallelRDPWrapper.cpp b/external/parallel-rdp/ParallelRDPWrapper.cpp index d70cde51..a7cbf949 100644 --- a/external/parallel-rdp/ParallelRDPWrapper.cpp +++ b/external/parallel-rdp/ParallelRDPWrapper.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include using namespace Vulkan; using namespace RDP; @@ -196,7 +198,7 @@ void DrawFullscreenTexturedQuad(Util::IntrusivePtr image, Util::Intrusive cmd->draw(3, 1); } -void UpdateScreen(Util::IntrusivePtr image) { +void UpdateScreen(Window& imguiWindow, Util::IntrusivePtr image) { wsi->begin_frame(); if (!image) { @@ -225,13 +227,15 @@ void UpdateScreen(Util::IntrusivePtr image) { cmd->begin_render_pass(wsi->get_device().get_swapchain_render_pass(SwapchainRenderPass::ColorOnly)); DrawFullscreenTexturedQuad(image, cmd); - //ImGui_ImplVulkan_RenderDrawData(imgui_frame(), cmd->get_command_buffer()); + + ImGui_ImplVulkan_RenderDrawData(imguiWindow.Present(), cmd->get_command_buffer()); + cmd->end_render_pass(); wsi->get_device().submit(cmd); wsi->end_frame(); } -void UpdateScreenParallelRdp(const n64::VI& vi) { +void UpdateScreenParallelRdp(Window& imguiWindow, const n64::VI& vi) { command_processor->set_vi_register(VIRegister::Control, vi.status.raw); command_processor->set_vi_register(VIRegister::Origin, vi.origin); command_processor->set_vi_register(VIRegister::Width, vi.width); @@ -257,12 +261,12 @@ void UpdateScreenParallelRdp(const n64::VI& vi) { opts.downscale_steps = true; opts.crop_overscan_pixels = true; Util::IntrusivePtr image = command_processor->scanout(opts); - UpdateScreen(image); + UpdateScreen(imguiWindow, image); command_processor->begin_frame_context(); } -void UpdateScreenParallelRdpNoGame() { - UpdateScreen(static_cast>(nullptr)); +void UpdateScreenParallelRdpNoGame(Window& imguiWindow) { + UpdateScreen(imguiWindow, static_cast>(nullptr)); } void ParallelRdpEnqueueCommand(int command_length, u32* buffer) { diff --git a/external/parallel-rdp/ParallelRDPWrapper.hpp b/external/parallel-rdp/ParallelRDPWrapper.hpp index 7c274b46..ff07c4e3 100644 --- a/external/parallel-rdp/ParallelRDPWrapper.hpp +++ b/external/parallel-rdp/ParallelRDPWrapper.hpp @@ -4,6 +4,8 @@ #include #include +struct Window; + static SDL_Window* window; static u32 windowID; VkQueue GetGraphicsQueue(); @@ -15,9 +17,9 @@ VkFormat GetVkFormat(); VkCommandBuffer GetVkCommandBuffer(); void SubmitRequestedVkCommandBuffer(); void LoadParallelRDP(const u8* rdram); -void UpdateScreenParallelRdp(const n64::VI& vi); +void UpdateScreenParallelRdp(Window& imguiWindow, const n64::VI& vi); void ParallelRdpEnqueueCommand(int command_length, u32* buffer); void ParallelRdpOnFullSync(); -void UpdateScreenParallelRdpNoGame(); +void UpdateScreenParallelRdpNoGame(Window& imguiWindow); bool IsFramerateUnlocked(); void SetFramerateUnlocked(bool unlocked); \ No newline at end of file diff --git a/src/cores/BaseCore.hpp b/src/cores/BaseCore.hpp index 0f00ee6c..138f1cd4 100644 --- a/src/cores/BaseCore.hpp +++ b/src/cores/BaseCore.hpp @@ -1,12 +1,17 @@ #pragma once #include +enum class System { + GameBoy, Nintendo64 +}; + struct BaseCore { virtual ~BaseCore() = default; virtual void Run() {}; virtual void PollInputs(u32) {}; [[nodiscard]] bool& ShouldQuit() { return quit; } bool initialized = false; + System system; private: bool quit = false; }; \ No newline at end of file diff --git a/src/cores/n64/CMakeLists.txt b/src/cores/n64/CMakeLists.txt index 16d9f8d1..e9845536 100644 --- a/src/cores/n64/CMakeLists.txt +++ b/src/cores/n64/CMakeLists.txt @@ -12,4 +12,6 @@ target_link_libraries(n64 PUBLIC n64-core) target_include_directories(n64 PUBLIC . .. - ../../../external) \ No newline at end of file + ../../../external + ../../../external/imgui/imgui + ../../../external/imgui/imgui/backends) \ No newline at end of file diff --git a/src/cores/n64/Core.cpp b/src/cores/n64/Core.cpp index e9c992e9..e5618d5e 100644 --- a/src/cores/n64/Core.cpp +++ b/src/cores/n64/Core.cpp @@ -22,8 +22,6 @@ void Core::Run() { if((mmio.vi.current & 0x3FE) == mmio.vi.intr) { InterruptRaise(mmio.mi, cpu.regs, Interrupt::VI); } - - UpdateScreenParallelRdp(mmio.vi); } } diff --git a/src/cores/n64/Core.hpp b/src/cores/n64/Core.hpp index 80add198..ff5f8935 100644 --- a/src/cores/n64/Core.hpp +++ b/src/cores/n64/Core.hpp @@ -10,6 +10,7 @@ struct Core : BaseCore { explicit Core(const std::string&); void Run() override; void PollInputs(u32) override; + VI& GetVI() { return mem.mmio.vi; } private: Mem mem; Cpu cpu; diff --git a/src/cores/n64/core/CMakeLists.txt b/src/cores/n64/core/CMakeLists.txt index b6718f2a..e7a27bfd 100644 --- a/src/cores/n64/core/CMakeLists.txt +++ b/src/cores/n64/core/CMakeLists.txt @@ -42,6 +42,8 @@ target_include_directories(n64-core PUBLIC .. ../.. ../../../../external + ../../../external/imgui/imgui + ../../../external/imgui/imgui/backends mmio) target_link_libraries(n64-core PUBLIC n64-cpu parallel-rdp) diff --git a/src/frontend/App.cpp b/src/frontend/App.cpp index 52e0a606..2a256042 100644 --- a/src/frontend/App.cpp +++ b/src/frontend/App.cpp @@ -1,4 +1,5 @@ #include +#include void App::Run() { // Main loop @@ -15,6 +16,9 @@ void App::Run() { if(core->initialized) core->Run(); - window.Update(core); + if(core->system == System::Nintendo64) { + if(core->initialized) UpdateScreenParallelRdp(window, dynamic_cast(core.get())->GetVI()); + else UpdateScreenParallelRdpNoGame(window); + } } } \ No newline at end of file diff --git a/src/frontend/App.hpp b/src/frontend/App.hpp index af8c8c95..82a08e90 100644 --- a/src/frontend/App.hpp +++ b/src/frontend/App.hpp @@ -3,9 +3,9 @@ #include struct App { - App() = default; + App() : window(core) {}; void Run(); private: - std::unique_ptr core; + std::shared_ptr core; Window window; }; diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index 4a6ef758..f76072f8 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -7,5 +7,13 @@ add_library(frontend App.hpp App.cpp) -target_include_directories(frontend PUBLIC . ../../external ../cores ../cores/n64) +target_include_directories(frontend PUBLIC + . + ../../external + ../../external/parallel-rdp + ../../external/parallel-rdp/parallel-rdp-standalone/vulkan + ../../external/parallel-rdp/parallel-rdp-standalone/util + ../../external/parallel-rdp/parallel-rdp-standalone/volk + ../cores + ../cores/n64) target_link_libraries(frontend PUBLIC frontend-imgui) diff --git a/src/frontend/imgui/CMakeLists.txt b/src/frontend/imgui/CMakeLists.txt index 4f28735a..9481ae5a 100644 --- a/src/frontend/imgui/CMakeLists.txt +++ b/src/frontend/imgui/CMakeLists.txt @@ -8,5 +8,11 @@ add_library(frontend-imgui Window.cpp Window.hpp) -target_include_directories(frontend-imgui PUBLIC . ../../cores ../../../external) +target_include_directories(frontend-imgui PUBLIC + . + ../../cores + ../../../external + ../../../external/parallel-rdp/parallel-rdp-standalone/vulkan + ../../../external/parallel-rdp/parallel-rdp-standalone/util + ../../../external/parallel-rdp/parallel-rdp-standalone/volk) target_link_libraries(frontend-imgui PUBLIC imgui nfd) \ No newline at end of file diff --git a/src/frontend/imgui/Window.cpp b/src/frontend/imgui/Window.cpp index 2f613be6..d02da945 100644 --- a/src/frontend/imgui/Window.cpp +++ b/src/frontend/imgui/Window.cpp @@ -2,16 +2,12 @@ #include #include #include +#include +#include +#include -Window::Window() { +Window::Window(std::shared_ptr core) : core(std::move(core)) { InitSDL(); - u32 extCount; - SDL_Vulkan_GetInstanceExtensions(window, &extCount, nullptr); - std::vector extensions; - extensions.resize(extCount); - SDL_Vulkan_GetInstanceExtensions(window, &extCount, extensions.data()); - InitVulkan(extensions, extCount); - InitVulkanWindow(); InitImgui(); } @@ -24,6 +20,10 @@ void Window::InitSDL() { 1280, 720, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI ); + + if(volkInitialize() != VK_SUCCESS) { + util::panic("Failed to load Volk!"); + } } static void check_vk_result(VkResult err) { @@ -32,88 +32,32 @@ static void check_vk_result(VkResult err) { } } -void Window::InitVulkan(const std::vector& extensions, u32 extCount) { - VkResult err{}; +void Window::InitImgui() { + VkResult err; + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsLight(); + + instance = GetVkInstance(); + physicalDevice = GetVkPhysicalDevice(); + device = GetVkDevice(); + queueFamily = GetVkGraphicsQueueFamily(); + queue = GetGraphicsQueue(); + pipelineCache = nullptr; + descriptorPool = nullptr; + allocator = nullptr; + minImageCount = 2; - // Create Vulkan Instance { - VkInstanceCreateInfo create_info = {}; - create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - create_info.enabledExtensionCount = extCount; - create_info.ppEnabledExtensionNames = extensions.data(); - - err = vkCreateInstance(&create_info, nullptr, &instance); - check_vk_result(err); - } - - // Select GPU - { - uint32_t gpu_count; - err = vkEnumeratePhysicalDevices(instance, &gpu_count, nullptr); - check_vk_result(err); - IM_ASSERT(gpu_count > 0); - - auto* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count); - err = vkEnumeratePhysicalDevices(instance, &gpu_count, gpus); - check_vk_result(err); - - // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers - // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple - // dedicated GPUs) is out of scope of this sample. - int use_gpu = 0; - for (int i = 0; i < (int)gpu_count; i++) { - VkPhysicalDeviceProperties properties; - vkGetPhysicalDeviceProperties(gpus[i], &properties); - if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { - use_gpu = i; - break; - } - } - - physicalDevice = gpus[use_gpu]; - free(gpus); - } - - // Select graphics queue family - { - uint32_t count; - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr); - auto* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, queues); - for (uint32_t i = 0; i < count; i++) { - if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { - queueFamily = i; - break; - } - } - free(queues); - IM_ASSERT(queueFamily != (uint32_t)-1); - } - - // Create Logical Device (with 1 queue) - { - int device_extension_count = 1; - const char* device_extensions[] = { "VK_KHR_swapchain" }; - const float queue_priority[] = { 1.0f }; - VkDeviceQueueCreateInfo queue_info[1] = {}; - queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_info[0].queueFamilyIndex = queueFamily; - queue_info[0].queueCount = 1; - queue_info[0].pQueuePriorities = queue_priority; - VkDeviceCreateInfo create_info = {}; - create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]); - create_info.pQueueCreateInfos = queue_info; - create_info.enabledExtensionCount = device_extension_count; - create_info.ppEnabledExtensionNames = device_extensions; - err = vkCreateDevice(physicalDevice, &create_info, nullptr, &device); - check_vk_result(err); - vkGetDeviceQueue(device, queueFamily, 0, &queue); - } - - // Create Descriptor Pool - { - VkDescriptorPoolSize pool_sizes[] = { + VkDescriptorPoolSize poolSizes[] = { { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 }, { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 }, @@ -126,80 +70,71 @@ void Window::InitVulkan(const std::vector& extensions, u32 extCount { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 }, { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 } }; - VkDescriptorPoolCreateInfo pool_info = {}; - pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes); - pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); - pool_info.pPoolSizes = pool_sizes; - err = vkCreateDescriptorPool(device, &pool_info, nullptr, &descriptorPool); + + VkDescriptorPoolCreateInfo poolInfo{}; + + poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; + poolInfo.maxSets = 1000 * IM_ARRAYSIZE(poolSizes); + poolInfo.poolSizeCount = (uint32_t)IM_ARRAYSIZE(poolSizes); + poolInfo.pPoolSizes = poolSizes; + err = vkCreateDescriptorPool(device, &poolInfo, allocator, &descriptorPool); check_vk_result(err); } -} -void Window::InitVulkanWindow() { - VkSurfaceKHR surface; - if (!SDL_Vulkan_CreateSurface(window, instance, &surface)) { - util::panic("Failed to create Vulkan surface."); + VkRenderPass renderPass; + { + VkAttachmentDescription attachment = {}; + attachment.format = GetVkFormat(); + attachment.samples = VK_SAMPLE_COUNT_1_BIT; + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + VkAttachmentReference colorAttachment = {}; + colorAttachment.attachment = 0; + colorAttachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorAttachment; + VkSubpassDependency dependency = {}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcAccessMask = 0; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + VkRenderPassCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + info.attachmentCount = 1; + info.pAttachments = &attachment; + info.subpassCount = 1; + info.pSubpasses = &subpass; + info.dependencyCount = 1; + info.pDependencies = &dependency; + err = vkCreateRenderPass(device, &info, allocator, &renderPass); + check_vk_result(err); } - // Create Framebuffers - int w, h; - SDL_GetWindowSize(window, &w, &h); - windowData.Surface = surface; - - // Check for WSI support - VkBool32 res; - vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamily, windowData.Surface, &res); - if (res != VK_TRUE) { - fprintf(stderr, "Error no WSI support on physical device 0\n"); - exit(-1); - } - - // Select Surface Format - const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; - const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - windowData.SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(physicalDevice, windowData.Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace); - - // Select Present Mode - VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR }; - - windowData.PresentMode = ImGui_ImplVulkanH_SelectPresentMode(physicalDevice, windowData.Surface, &present_modes[0], IM_ARRAYSIZE(present_modes)); - - IM_ASSERT(minImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(instance, physicalDevice, device, &windowData, queueFamily, nullptr, w, h, minImageCount); -} - -void Window::InitImgui() { - VkResult err; - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - (void)io; - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls - - // Setup Dear ImGui style - ImGui::StyleColorsDark(); - //ImGui::StyleColorsLight(); - // Setup Platform/Renderer backends ImGui_ImplSDL2_InitForVulkan(window); - ImGui_ImplVulkan_InitInfo init_info = {}; - init_info.Instance = instance; - init_info.PhysicalDevice = physicalDevice; - init_info.Device = device; - init_info.QueueFamily = queueFamily; - init_info.Queue = queue; - init_info.PipelineCache = pipelineCache; - init_info.DescriptorPool = descriptorPool; - init_info.Subpass = 0; - init_info.MinImageCount = minImageCount; - init_info.ImageCount = windowData.ImageCount; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; - init_info.Allocator = nullptr; - init_info.CheckVkResultFn = check_vk_result; - ImGui_ImplVulkan_Init(&init_info, windowData.RenderPass); + ImGui_ImplVulkan_InitInfo initInfo = {}; + initInfo.Instance = instance; + initInfo.PhysicalDevice = physicalDevice; + initInfo.Device = device; + initInfo.QueueFamily = queueFamily; + initInfo.Queue = queue; + initInfo.PipelineCache = pipelineCache; + initInfo.DescriptorPool = descriptorPool; + initInfo.Allocator = allocator; + initInfo.MinImageCount = minImageCount; + initInfo.ImageCount = 2; + initInfo.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + initInfo.CheckVkResultFn = check_vk_result; + ImGui_ImplVulkan_Init(&initInfo, renderPass); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. @@ -218,32 +153,9 @@ void Window::InitImgui() { // Upload Fonts { - // Use any command queue - VkCommandPool command_pool = windowData.Frames[windowData.FrameIndex].CommandPool; - VkCommandBuffer command_buffer = windowData.Frames[windowData.FrameIndex].CommandBuffer; - - err = vkResetCommandPool(device, command_pool, 0); - check_vk_result(err); - VkCommandBufferBeginInfo begin_info = {}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - err = vkBeginCommandBuffer(command_buffer, &begin_info); - check_vk_result(err); - - ImGui_ImplVulkan_CreateFontsTexture(command_buffer); - - VkSubmitInfo end_info = {}; - end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - end_info.commandBufferCount = 1; - end_info.pCommandBuffers = &command_buffer; - err = vkEndCommandBuffer(command_buffer); - check_vk_result(err); - err = vkQueueSubmit(queue, 1, &end_info, VK_NULL_HANDLE); - check_vk_result(err); - - err = vkDeviceWaitIdle(device); - check_vk_result(err); - ImGui_ImplVulkan_DestroyFontUploadObjects(); + VkCommandBuffer commandBuffer = GetVkCommandBuffer(); + ImGui_ImplVulkan_CreateFontsTexture(commandBuffer); + SubmitRequestedVkCommandBuffer(); } } @@ -253,115 +165,23 @@ Window::~Window() { ImGui_ImplVulkan_Shutdown(); ImGui_ImplSDL2_Shutdown(); ImGui::DestroyContext(); - ImGui_ImplVulkanH_DestroyWindow(instance, device, &windowData, nullptr); vkDestroyDescriptorPool(device, descriptorPool, nullptr); vkDestroyDevice(device, nullptr); vkDestroyInstance(instance, nullptr); } -void Window::Render(ImDrawData* drawData) { - VkResult err; - - VkSemaphore image_acquired_semaphore = windowData.FrameSemaphores[windowData.SemaphoreIndex].ImageAcquiredSemaphore; - VkSemaphore render_complete_semaphore = windowData.FrameSemaphores[windowData.SemaphoreIndex].RenderCompleteSemaphore; - err = vkAcquireNextImageKHR(device, windowData.Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &windowData.FrameIndex); - if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) { - rebuildSwapchain = true; - return; - } - check_vk_result(err); - - ImGui_ImplVulkanH_Frame* fd = &windowData.Frames[windowData.FrameIndex]; - { - err = vkWaitForFences(device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking - check_vk_result(err); - - err = vkResetFences(device, 1, &fd->Fence); - check_vk_result(err); - } - { - err = vkResetCommandPool(device, fd->CommandPool, 0); - check_vk_result(err); - VkCommandBufferBeginInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - err = vkBeginCommandBuffer(fd->CommandBuffer, &info); - check_vk_result(err); - } - { - VkRenderPassBeginInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - info.renderPass = windowData.RenderPass; - info.framebuffer = fd->Framebuffer; - info.renderArea.extent.width = windowData.Width; - info.renderArea.extent.height = windowData.Height; - info.clearValueCount = 1; - info.pClearValues = &windowData.ClearValue; - vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE); - } - - // Record dear imgui primitives into command buffer - ImGui_ImplVulkan_RenderDrawData(drawData, fd->CommandBuffer); - - // Submit command buffer - vkCmdEndRenderPass(fd->CommandBuffer); - { - VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkSubmitInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - info.waitSemaphoreCount = 1; - info.pWaitSemaphores = &image_acquired_semaphore; - info.pWaitDstStageMask = &wait_stage; - info.commandBufferCount = 1; - info.pCommandBuffers = &fd->CommandBuffer; - info.signalSemaphoreCount = 1; - info.pSignalSemaphores = &render_complete_semaphore; - - err = vkEndCommandBuffer(fd->CommandBuffer); - check_vk_result(err); - err = vkQueueSubmit(queue, 1, &info, fd->Fence); - check_vk_result(err); - } -} - -void Window::Present() { - if (rebuildSwapchain) { - return; - } - VkSemaphore render_complete_semaphore = windowData.FrameSemaphores[windowData.SemaphoreIndex].RenderCompleteSemaphore; - VkPresentInfoKHR info = {}; - info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - info.waitSemaphoreCount = 1; - info.pWaitSemaphores = &render_complete_semaphore; - info.swapchainCount = 1; - info.pSwapchains = &windowData.Swapchain; - info.pImageIndices = &windowData.FrameIndex; - VkResult err = vkQueuePresentKHR(queue, &info); - if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) { - rebuildSwapchain = true; - return; - } - check_vk_result(err); - windowData.SemaphoreIndex = (windowData.SemaphoreIndex + 1) % windowData.ImageCount; -} - -void Window::Update(std::unique_ptr& core) { - if (rebuildSwapchain) { - int width, height; - SDL_GetWindowSize(window, &width, &height); - if (width > 0 && height > 0) { - ImGui_ImplVulkan_SetMinImageCount(minImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(instance, physicalDevice, device, &windowData, queueFamily, nullptr, width, height, minImageCount); - windowData.FrameIndex = 0; - rebuildSwapchain = false; - } - } - - // Start the Dear ImGui frame +ImDrawData* Window::Present() { ImGui_ImplVulkan_NewFrame(); - ImGui_ImplSDL2_NewFrame(); + ImGui_ImplSDL2_NewFrame(window); ImGui::NewFrame(); + Render(); + + ImGui::Render(); + return ImGui::GetDrawData(); +} + +void Window::Render() { ImGui::BeginMainMenuBar(); if(ImGui::BeginMenu("File")) { if(ImGui::BeginMenu("Open")) { @@ -370,8 +190,9 @@ void Window::Update(std::unique_ptr& core) { const nfdu8filteritem_t filter {"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"}; nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr); if(result == NFD_OKAY) { - core = std::make_unique(outpath); + core = std::make_shared(outpath); core->initialized = true; + core->system = System::Nintendo64; NFD_FreePath(outpath); } } @@ -390,17 +211,4 @@ void Window::Update(std::unique_ptr& core) { ImGui::EndMenu(); } ImGui::EndMainMenuBar(); - - // Rendering - ImGui::Render(); - ImDrawData* draw_data = ImGui::GetDrawData(); - const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f); - if (!is_minimized) { - windowData.ClearValue.color.float32[0] = 0; - windowData.ClearValue.color.float32[1] = 0; - windowData.ClearValue.color.float32[2] = 0; - windowData.ClearValue.color.float32[3] = 0; - Render(draw_data); - Present(); - } } diff --git a/src/frontend/imgui/Window.hpp b/src/frontend/imgui/Window.hpp index 6ce26fc3..4cf80f99 100644 --- a/src/frontend/imgui/Window.hpp +++ b/src/frontend/imgui/Window.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#define VK_NO_PROTOTYPES #include #include #include @@ -9,9 +10,9 @@ #include struct Window { - Window(); + explicit Window(std::shared_ptr core); ~Window(); - void Update(std::unique_ptr&); + ImDrawData* Present(); [[nodiscard]] bool gotClosed(SDL_Event event) { return event.type == SDL_WINDOWEVENT @@ -19,12 +20,10 @@ struct Window { && event.window.windowID == SDL_GetWindowID(window); } private: + std::shared_ptr core; void InitSDL(); - void InitVulkan(const std::vector&, u32); - void InitVulkanWindow(); void InitImgui(); - void Render(ImDrawData*); - void Present(); + void Render(); SDL_Window* window{}; @@ -35,8 +34,8 @@ private: VkQueue queue{}; VkPipelineCache pipelineCache{}; VkDescriptorPool descriptorPool{}; + VkAllocationCallbacks* allocator{}; - ImGui_ImplVulkanH_Window windowData; u32 minImageCount = 2; bool rebuildSwapchain = false; };