From 37902cd9d6c50a592c1653c94a552294fa5b3716 Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Thu, 27 Jul 2023 10:13:53 -0700 Subject: [PATCH] Implement a renderpass cache. Technically we can generate every possible render-pass up-front based on the possible combinations of ColorFmt and DepthFmt, but we should only allocate what the game asks for. Save that pattern for pipelines. --- include/renderer_vk/renderer_vk.hpp | 7 ++++ src/core/renderer_vk/renderer_vk.cpp | 59 +++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/include/renderer_vk/renderer_vk.hpp b/include/renderer_vk/renderer_vk.hpp index e7dfdf0c..700861b2 100644 --- a/include/renderer_vk/renderer_vk.hpp +++ b/include/renderer_vk/renderer_vk.hpp @@ -1,3 +1,6 @@ +#include +#include + #include "renderer.hpp" #include "vk_api.hpp" @@ -49,6 +52,10 @@ class RendererVK final : public Renderer { std::vector topScreenImages = {}; std::vector bottomScreenImages = {}; + std::map renderPassCache; + + vk::RenderPass getRenderPass(PICA::ColorFmt colorFormat, std::optional depthFormat); + // Recreate the swapchain, possibly re-using the old one in the case of a resize vk::Result recreateSwapchain(vk::SurfaceKHR surface, vk::Extent2D swapchainExtent); diff --git a/src/core/renderer_vk/renderer_vk.cpp b/src/core/renderer_vk/renderer_vk.cpp index 2c887cc8..05b40e43 100644 --- a/src/core/renderer_vk/renderer_vk.cpp +++ b/src/core/renderer_vk/renderer_vk.cpp @@ -8,6 +8,7 @@ #include "helpers.hpp" #include "renderer_vk/vk_debug.hpp" #include "renderer_vk/vk_memory.hpp" +#include "renderer_vk/vk_pica.hpp" // Finds the first queue family that satisfies `queueMask` and excludes `queueExcludeMask` bits // Returns -1 if not found @@ -24,6 +25,57 @@ static s32 findQueueFamily( return -1; } +vk::RenderPass RendererVK::getRenderPass(PICA::ColorFmt colorFormat, std::optional depthFormat) { + u32 renderPassHash = static_cast(colorFormat); + + if (depthFormat.has_value()) { + renderPassHash |= (static_cast(depthFormat.value()) << 8); + } + + // Cache hit + if (renderPassCache.contains(renderPassHash)) { + return renderPassCache.at(renderPassHash).get(); + } + + // Cache miss + vk::RenderPassCreateInfo renderPassInfo = {}; + + std::vector renderPassAttachments = {}; + + vk::AttachmentDescription colorAttachment = {}; + colorAttachment.format = Vulkan::colorFormatToVulkan(colorFormat); + colorAttachment.samples = vk::SampleCountFlagBits::e1; + colorAttachment.loadOp = vk::AttachmentLoadOp::eLoad; + colorAttachment.storeOp = vk::AttachmentStoreOp::eStore; + colorAttachment.stencilLoadOp = vk::AttachmentLoadOp::eLoad; + colorAttachment.stencilStoreOp = vk::AttachmentStoreOp::eStore; + colorAttachment.initialLayout = vk::ImageLayout::eColorAttachmentOptimal; + colorAttachment.finalLayout = vk::ImageLayout::eColorAttachmentOptimal; + renderPassAttachments.emplace_back(colorAttachment); + + if (depthFormat.has_value()) { + vk::AttachmentDescription depthAttachment = {}; + depthAttachment.format = Vulkan::depthFormatToVulkan(depthFormat.value()); + depthAttachment.samples = vk::SampleCountFlagBits::e1; + depthAttachment.loadOp = vk::AttachmentLoadOp::eLoad; + depthAttachment.storeOp = vk::AttachmentStoreOp::eStore; + depthAttachment.stencilLoadOp = vk::AttachmentLoadOp::eLoad; + depthAttachment.stencilStoreOp = vk::AttachmentStoreOp::eStore; + depthAttachment.initialLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal; + depthAttachment.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal; + renderPassAttachments.emplace_back(depthAttachment); + } + + renderPassInfo.setAttachments(renderPassAttachments); + + if (auto createResult = device->createRenderPassUnique(renderPassInfo); createResult.result == vk::Result::eSuccess) { + return (renderPassCache[renderPassHash] = std::move(createResult.value)).get(); + } else { + Helpers::panic("Error creating render pass: %s\n", vk::to_string(createResult.result).c_str()); + } + return {}; +} + vk::Result RendererVK::recreateSwapchain(vk::SurfaceKHR surface, vk::Extent2D swapchainExtent) { static constexpr u32 screenTextureWidth = 400; // Top screen is 400 pixels wide, bottom is 320 static constexpr u32 screenTextureHeight = 2 * 240; // Both screens are 240 pixels tall @@ -695,6 +747,11 @@ void RendererVK::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u void RendererVK::textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) {} -void RendererVK::drawVertices(PICA::PrimType primType, std::span vertices) {} +void RendererVK::drawVertices(PICA::PrimType primType, std::span vertices) { + const u32 depthControl = regs[PICA::InternalRegs::DepthAndColorMask]; + const bool depthEnable = depthControl & 1; + + const vk::RenderPass curRenderPass = getRenderPass(colourBufferFormat, depthEnable ? std::make_optional(depthBufferFormat) : std::nullopt); +} void RendererVK::screenshot(const std::string& name) {}