mirror of
https://github.com/Takiiiiiiii/strato.git
synced 2025-07-17 08:46:39 +00:00
Implement Framebuffer Cache
Implements a cache for storing `VkFramebuffer` objects with a special path on devices with `VK_KHR_imageless_framebuffer` to allow for more cache hits due to an abstract image rather than a specific one. Caching framebuffers is a fairly crucial optimization due to the cost of creating framebuffers on TBDRs since it involves calculating tiling memory allocations and in the case of Adreno's proprietary driver involves several kernel calls for mapping and allocating the corresponding framebuffer memory.
This commit is contained in:
78
app/src/main/cpp/skyline/gpu/cache/framebuffer_cache.h
vendored
Normal file
78
app/src/main/cpp/skyline/gpu/cache/framebuffer_cache.h
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace skyline::gpu::cache {
|
||||
using FramebufferCreateInfo = vk::StructureChain<vk::FramebufferCreateInfo, vk::FramebufferAttachmentsCreateInfo>;
|
||||
|
||||
/**
|
||||
* @brief A cache for Vulkan framebuffers to avoid unnecessary recreation, optimized for both fixed image and imageless attachments
|
||||
* @note It is generally expensive to create a framebuffer on TBDRs since it involves calculating tiling memory allocations and in the case of Adreno's proprietary driver involves several kernel calls for mapping and allocating the corresponding framebuffer memory
|
||||
*/
|
||||
class FramebufferCache {
|
||||
private:
|
||||
GPU &gpu;
|
||||
std::mutex mutex; //!< Synchronizes access to the cache
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief An equivalent to VkFramebufferAttachmentImageInfo with more suitable semantics for storage
|
||||
* @url https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkFramebufferAttachmentImageInfo.html
|
||||
*/
|
||||
struct FramebufferImagelessAttachment {
|
||||
vk::ImageCreateFlags flags;
|
||||
vk::ImageUsageFlags usage;
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 layers;
|
||||
vk::Format format;
|
||||
|
||||
FramebufferImagelessAttachment(const vk::FramebufferAttachmentImageInfo &info);
|
||||
|
||||
bool operator==(const FramebufferImagelessAttachment &other) const = default;
|
||||
};
|
||||
|
||||
struct FramebufferCacheKey {
|
||||
vk::FramebufferCreateFlags flags;
|
||||
vk::RenderPass renderPass;
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 layers;
|
||||
std::variant<std::vector<vk::ImageView>, std::vector<FramebufferImagelessAttachment>> attachments;
|
||||
|
||||
FramebufferCacheKey(const FramebufferCreateInfo &createInfo);
|
||||
|
||||
bool operator==(const FramebufferCacheKey &other) const = default;
|
||||
};
|
||||
|
||||
struct FramebufferHash {
|
||||
using is_transparent = std::true_type;
|
||||
|
||||
size_t operator()(const FramebufferCacheKey &key) const;
|
||||
|
||||
size_t operator()(const FramebufferCreateInfo &key) const;
|
||||
};
|
||||
|
||||
struct FramebufferEqual {
|
||||
using is_transparent = std::true_type;
|
||||
|
||||
bool operator()(const FramebufferCacheKey &lhs, const FramebufferCacheKey &rhs) const;
|
||||
|
||||
bool operator()(const FramebufferCacheKey &lhs, const FramebufferCreateInfo &rhs) const;
|
||||
};
|
||||
|
||||
std::unordered_map<FramebufferCacheKey, vk::raii::Framebuffer, FramebufferHash, FramebufferEqual> framebufferCache;
|
||||
|
||||
public:
|
||||
FramebufferCache(GPU &gpu);
|
||||
|
||||
/**
|
||||
* @note When using imageless framebuffer attachments, VkFramebufferAttachmentImageInfo **must** have a single view format
|
||||
* @note When using image framebuffer attachments, it is expected that the supplied image handle will remain stable for the cache to function
|
||||
*/
|
||||
vk::Framebuffer GetFramebuffer(const FramebufferCreateInfo &createInfo);
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user