summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_vulkan/vk_render_pass_cache.cpp')
-rw-r--r--src/video_core/renderer_vulkan/vk_render_pass_cache.cpp96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp
new file mode 100644
index 000000000..451ffe019
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp
@@ -0,0 +1,96 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <unordered_map>
+
+#include <boost/container/static_vector.hpp>
+
+#include "video_core/renderer_vulkan/maxwell_to_vk.h"
+#include "video_core/renderer_vulkan/vk_render_pass_cache.h"
+#include "video_core/surface.h"
+#include "video_core/vulkan_common/vulkan_device.h"
+#include "video_core/vulkan_common/vulkan_wrapper.h"
+
+namespace Vulkan {
+namespace {
+using VideoCore::Surface::PixelFormat;
+
+VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format,
+ VkSampleCountFlagBits samples) {
+ using MaxwellToVK::SurfaceFormat;
+ return {
+ .flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT,
+ .format = SurfaceFormat(device, FormatType::Optimal, true, format).format,
+ .samples = samples,
+ .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
+ .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
+ .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .initialLayout = VK_IMAGE_LAYOUT_GENERAL,
+ .finalLayout = VK_IMAGE_LAYOUT_GENERAL,
+ };
+}
+} // Anonymous namespace
+
+RenderPassCache::RenderPassCache(const Device& device_) : device{&device_} {}
+
+VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
+ std::lock_guard lock{mutex};
+ const auto [pair, is_new] = cache.try_emplace(key);
+ if (!is_new) {
+ return *pair->second;
+ }
+ boost::container::static_vector<VkAttachmentDescription, 9> descriptions;
+ std::array<VkAttachmentReference, 8> references{};
+ u32 num_attachments{};
+ u32 num_colors{};
+ for (size_t index = 0; index < key.color_formats.size(); ++index) {
+ const PixelFormat format{key.color_formats[index]};
+ const bool is_valid{format != PixelFormat::Invalid};
+ references[index] = VkAttachmentReference{
+ .attachment = is_valid ? num_colors : VK_ATTACHMENT_UNUSED,
+ .layout = VK_IMAGE_LAYOUT_GENERAL,
+ };
+ if (is_valid) {
+ descriptions.push_back(AttachmentDescription(*device, format, key.samples));
+ num_attachments = static_cast<u32>(index + 1);
+ ++num_colors;
+ }
+ }
+ const bool has_depth{key.depth_format != PixelFormat::Invalid};
+ VkAttachmentReference depth_reference{};
+ if (key.depth_format != PixelFormat::Invalid) {
+ depth_reference = VkAttachmentReference{
+ .attachment = num_colors,
+ .layout = VK_IMAGE_LAYOUT_GENERAL,
+ };
+ descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples));
+ }
+ const VkSubpassDescription subpass{
+ .flags = 0,
+ .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
+ .inputAttachmentCount = 0,
+ .pInputAttachments = nullptr,
+ .colorAttachmentCount = num_attachments,
+ .pColorAttachments = references.data(),
+ .pResolveAttachments = nullptr,
+ .pDepthStencilAttachment = has_depth ? &depth_reference : nullptr,
+ .preserveAttachmentCount = 0,
+ .pPreserveAttachments = nullptr,
+ };
+ pair->second = device->GetLogical().CreateRenderPass({
+ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .attachmentCount = static_cast<u32>(descriptions.size()),
+ .pAttachments = descriptions.empty() ? nullptr : descriptions.data(),
+ .subpassCount = 1,
+ .pSubpasses = &subpass,
+ .dependencyCount = 0,
+ .pDependencies = nullptr,
+ });
+ return *pair->second;
+}
+
+} // namespace Vulkan