vk: improve framebuffer change
This commit is contained in:
@@ -42,7 +42,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define HandleAllocatorGL HandleAllocator<32, 96, 184> // ~4520 / pool / MiB
|
||||
#define HandleAllocatorVK HandleAllocator<64, 160, 312> // ~1820 / pool / MiB
|
||||
#define HandleAllocatorVK HandleAllocator<64, 160, 352> // ~1820 / pool / MiB
|
||||
#define HandleAllocatorMTL HandleAllocator<32, 64, 552> // ~1660 / pool / MiB
|
||||
// TODO WebGPU examine right size of handles
|
||||
#define HandleAllocatorWGPU HandleAllocator<64, 160, 552> // ~1820 / pool / MiB
|
||||
|
||||
@@ -95,9 +95,9 @@
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define FVK_DEBUG_FLAGS (FVK_DEBUG_PERFORMANCE | FVK_DEBUG_FORWARDED_FLAG)
|
||||
#define FVK_DEBUG_FLAGS (FVK_DEBUG_PERFORMANCE | FVK_DEBUG_FORWARDED_FLAG | FVK_DEBUG_RESOURCE_LEAK)
|
||||
#else
|
||||
#define FVK_DEBUG_FLAGS 0
|
||||
#define FVK_DEBUG_FLAGS (FVK_DEBUG_RESOURCE_LEAK)
|
||||
#endif
|
||||
|
||||
// Override the debug flags if we are forcing profiling mode
|
||||
|
||||
@@ -248,7 +248,7 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext& context,
|
||||
// swap the content later when createDefaultRenderTarget() is called. This frees
|
||||
// createDefaultRenderTarget() from being ordered with makeCurrent().
|
||||
mDefaultRenderTarget(
|
||||
fvkmemory::resource_ptr<VulkanRenderTarget>::construct(&mResourceManager)),
|
||||
fvkmemory::resource_ptr<VulkanRenderTarget>::construct(&mResourceManager, mPlatform->getDevice())),
|
||||
mAllocator(createAllocator(mPlatform->getInstance(), mPlatform->getPhysicalDevice(),
|
||||
mPlatform->getDevice())),
|
||||
mContext(context),
|
||||
@@ -484,6 +484,9 @@ void VulkanDriver::endFrame(uint32_t frameId) {
|
||||
FVK_PROFILE_MARKER(PROFILE_NAME_ENDFRAME);
|
||||
endCommandRecording();
|
||||
collectGarbage();
|
||||
//#if FVK_ENABLED(FVK_DEBUG_RESOURCE_LEAK)
|
||||
// mResourceManager.print();
|
||||
//#endif
|
||||
}
|
||||
|
||||
void VulkanDriver::updateDescriptorSetBuffer(
|
||||
@@ -1981,15 +1984,9 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
|
||||
mFramebufferCache.getRenderPass(rpkey, &mResourceManager);
|
||||
mPipelineCache.bindRenderPass(renderPass, 0);
|
||||
|
||||
// Create the VkFramebuffer or fetch it from cache.
|
||||
VulkanFboCache::FboKey fbkey = rt->getFboKey();
|
||||
fbkey.renderPass = renderPass->getVkRenderPass();
|
||||
fbkey.layers = 1;
|
||||
|
||||
rt->emitBarriersBeginRenderPass(*commandBuffer);
|
||||
|
||||
fvkmemory::resource_ptr<VulkanFramebuffer> vkfb =
|
||||
mFramebufferCache.getFramebuffer(fbkey, &mResourceManager, rt);
|
||||
VkFramebuffer vkfb = rt->getFramebuffer(renderPass->getVkRenderPass(), commandBuffer);
|
||||
|
||||
// Assign a label to the framebuffer for debugging purposes.
|
||||
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS | FVK_DEBUG_DEBUG_UTILS)
|
||||
@@ -2003,13 +2000,12 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
|
||||
// The current command buffer now has references to the render target and its attachments.
|
||||
commandBuffer->acquire(rt);
|
||||
commandBuffer->acquire(renderPass);
|
||||
commandBuffer->acquire(vkfb);
|
||||
|
||||
// Populate the structures required for vkCmdBeginRenderPass.
|
||||
VkRenderPassBeginInfo renderPassInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.renderPass = renderPass->getVkRenderPass(),
|
||||
.framebuffer = vkfb->getVkFramebuffer(),
|
||||
.framebuffer = vkfb,
|
||||
|
||||
// The renderArea field constrains the LoadOp, but scissoring does not.
|
||||
// Therefore, we do not set the scissor rect here, we only need it in draw().
|
||||
@@ -2023,10 +2019,10 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
|
||||
1] = {};
|
||||
if (clearVal != TargetBufferFlags::NONE) {
|
||||
// NOTE: clearValues must be populated in the same order as the attachments array in
|
||||
// VulkanFboCache::getFramebuffer. Values must be provided regardless of whether Vulkan is
|
||||
// VulkanRenderTarget::getFramebuffer. Values must be provided regardless of whether Vulkan is
|
||||
// actually clearing that particular target.
|
||||
for (int i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; i++) {
|
||||
if (fbkey.color[i]) {
|
||||
if (rpkey.colorFormat[i] != VK_FORMAT_UNDEFINED) {
|
||||
VkClearValue &clearValue = clearValues[renderPassInfo.clearValueCount++];
|
||||
clearValue.color.float32[0] = params.clearColor.r;
|
||||
clearValue.color.float32[1] = params.clearColor.g;
|
||||
@@ -2040,7 +2036,7 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
|
||||
renderPassInfo.clearValueCount++;
|
||||
}
|
||||
}
|
||||
if (fbkey.depth) {
|
||||
if (rpkey.depthFormat != VK_FORMAT_UNDEFINED) {
|
||||
VkClearValue &clearValue = clearValues[renderPassInfo.clearValueCount++];
|
||||
clearValue.depthStencil = {(float) params.clearDepth, 0};
|
||||
}
|
||||
@@ -2103,7 +2099,7 @@ void VulkanDriver::nextSubpass(int) {
|
||||
++mCurrentRenderPass.currentSubpass);
|
||||
|
||||
if (mCurrentRenderPass.params.subpassMask & 0x1) {
|
||||
VulkanAttachment& subpassInput = renderTarget->getColor0();
|
||||
VulkanAttachment const& subpassInput = renderTarget->getColor0();
|
||||
mDescriptorSetCache.updateInputAttachment({}, subpassInput);
|
||||
}
|
||||
}
|
||||
@@ -2710,9 +2706,6 @@ void VulkanDriver::acquireNextSwapchainImage() {
|
||||
|
||||
bool resized = false;
|
||||
mCurrentSwapChain->acquire(resized);
|
||||
if (resized) {
|
||||
mFramebufferCache.resetFramebuffers();
|
||||
}
|
||||
// Note that ordering this after the above lines is necessary since we set the swapchain image
|
||||
// to the render target in bindSwapChain().
|
||||
mDefaultRenderTarget->bindSwapChain(mCurrentSwapChain);
|
||||
|
||||
@@ -48,85 +48,14 @@ bool VulkanFboCache::RenderPassEq::operator()(const RenderPassKey& k1,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VulkanFboCache::FboKeyEqualFn::operator()(const FboKey& k1, const FboKey& k2) const {
|
||||
if (k1.renderPass != k2.renderPass) return false;
|
||||
if (k1.width != k2.width) return false;
|
||||
if (k1.height != k2.height) return false;
|
||||
if (k1.layers != k2.layers) return false;
|
||||
if (k1.samples != k2.samples) return false;
|
||||
if (k1.depth != k2.depth) return false;
|
||||
for (int i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; i++) {
|
||||
if (k1.color[i] != k2.color[i]) return false;
|
||||
if (k1.resolve[i] != k2.resolve[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
VulkanFboCache::VulkanFboCache(VkDevice device)
|
||||
: mDevice(device) {}
|
||||
|
||||
VulkanFboCache::~VulkanFboCache() {
|
||||
FILAMENT_CHECK_POSTCONDITION(mFramebufferCache.empty() && mRenderPassCache.empty())
|
||||
FILAMENT_CHECK_POSTCONDITION(mRenderPassCache.empty())
|
||||
<< "Please explicitly call terminate() while the VkDevice is still alive.";
|
||||
}
|
||||
|
||||
fvkmemory::resource_ptr<VulkanFramebuffer> VulkanFboCache::getFramebuffer(FboKey const& config,
|
||||
fvkmemory::ResourceManager* resManager,
|
||||
fvkmemory::resource_ptr<VulkanRenderTarget> renderTarget) noexcept {
|
||||
FboMap::iterator iter = mFramebufferCache.find(config);
|
||||
if (UTILS_LIKELY(iter != mFramebufferCache.end())) {
|
||||
iter.value().timestamp = mCurrentTime;
|
||||
return iter->second.handle;
|
||||
}
|
||||
|
||||
// The attachment list contains: Color Attachments, Resolve Attachments, and Depth Attachment.
|
||||
// For simplicity, create an array that can hold the maximum possible number of attachments.
|
||||
// Note that this needs to have the same ordering as the corollary array in getRenderPass.
|
||||
VkImageView attachments[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT + MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT + 1];
|
||||
uint32_t attachmentCount = 0;
|
||||
for (VkImageView attachment : config.color) {
|
||||
if (attachment) {
|
||||
attachments[attachmentCount++] = attachment;
|
||||
}
|
||||
}
|
||||
for (VkImageView attachment : config.resolve) {
|
||||
if (attachment) {
|
||||
attachments[attachmentCount++] = attachment;
|
||||
}
|
||||
}
|
||||
if (config.depth) {
|
||||
attachments[attachmentCount++] = config.depth;
|
||||
}
|
||||
|
||||
#if FVK_ENABLED(FVK_DEBUG_FBO_CACHE)
|
||||
FVK_LOGD << "Creating framebuffer " << config.width << "x" << config.height << " "
|
||||
<< "for render pass " << config.renderPass << ", "
|
||||
<< "samples = " << int(config.samples) << ", "
|
||||
<< "depth = " << (config.depth ? 1 : 0) << ", "
|
||||
<< "attachmentCount = " << attachmentCount;
|
||||
#endif
|
||||
|
||||
VkFramebufferCreateInfo info {
|
||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||
.renderPass = config.renderPass,
|
||||
.attachmentCount = attachmentCount,
|
||||
.pAttachments = attachments,
|
||||
.width = config.width,
|
||||
.height = config.height,
|
||||
.layers = config.layers,
|
||||
};
|
||||
mRenderPassRefCount[info.renderPass]++;
|
||||
VkFramebuffer framebuffer;
|
||||
VkResult error = vkCreateFramebuffer(mDevice, &info, VKALLOC, &framebuffer);
|
||||
FILAMENT_CHECK_POSTCONDITION(error == VK_SUCCESS) << "Unable to create framebuffer."
|
||||
<< " error=" << static_cast<int32_t>(error);
|
||||
fvkmemory::resource_ptr<VulkanFramebuffer> fbh =
|
||||
fvkmemory::resource_ptr<VulkanFramebuffer>::construct(resManager, mDevice, framebuffer,
|
||||
renderTarget);
|
||||
mFramebufferCache[config] = { fbh, mCurrentTime };
|
||||
return fbh;
|
||||
}
|
||||
|
||||
fvkmemory::resource_ptr<VulkanRenderPass> VulkanFboCache::getRenderPass(
|
||||
RenderPassKey const& config, fvkmemory::ResourceManager* resManager) noexcept {
|
||||
auto iter = mRenderPassCache.find(config);
|
||||
@@ -355,16 +284,7 @@ fvkmemory::resource_ptr<VulkanRenderPass> VulkanFboCache::getRenderPass(
|
||||
return rph;
|
||||
}
|
||||
|
||||
void VulkanFboCache::resetFramebuffers() noexcept {
|
||||
for (const auto& pair: mFramebufferCache) {
|
||||
mRenderPassRefCount[pair.first.renderPass]--;
|
||||
}
|
||||
mFramebufferCache.clear();
|
||||
}
|
||||
|
||||
void VulkanFboCache::terminate() noexcept {
|
||||
resetFramebuffers();
|
||||
|
||||
mRenderPassRefCount.clear();
|
||||
mRenderPassCache.clear();
|
||||
}
|
||||
@@ -381,18 +301,6 @@ void VulkanFboCache::gc() noexcept {
|
||||
}
|
||||
const uint32_t evictTime = mCurrentTime - TIME_BEFORE_EVICTION;
|
||||
|
||||
for (FboMap::iterator iter = mFramebufferCache.begin(); iter != mFramebufferCache.end(); ) {
|
||||
const FboVal fbo = iter->second;
|
||||
if (fbo.timestamp < evictTime && fbo.handle) {
|
||||
mRenderPassRefCount[iter->first.renderPass]--;
|
||||
|
||||
// erase(iterator) returns the iterator to the next element.
|
||||
iter = mFramebufferCache.erase(iter);
|
||||
} else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
for (RenderPassMap::iterator iter = mRenderPassCache.begin(); iter != mRenderPassCache.end(); ) {
|
||||
const VkRenderPass handle = iter->second.handle->getVkRenderPass();
|
||||
if (iter->second.timestamp < evictTime && handle && mRenderPassRefCount[handle] == 0) {
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
struct VulkanFramebuffer;
|
||||
struct VulkanRenderPass;
|
||||
|
||||
// Simple manager for VkFramebuffer and VkRenderPass objects.
|
||||
@@ -75,39 +74,12 @@ public:
|
||||
bool operator()(const RenderPassKey& k1, const RenderPassKey& k2) const;
|
||||
};
|
||||
|
||||
// FboKey is a small POD representing the immutable state that we wish to configure
|
||||
// in VkFramebuffer. It is hashed and used as a lookup key. There are several attachments, but
|
||||
// rather than storing a count, we simply zero out the unused slots.
|
||||
struct alignas(8) FboKey {
|
||||
VkRenderPass renderPass; // 8 bytes
|
||||
uint16_t width; // 2 bytes
|
||||
uint16_t height; // 2 bytes
|
||||
uint16_t layers; // 2 bytes
|
||||
uint16_t samples; // 2 bytes
|
||||
VkImageView color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT]; // 64 bytes
|
||||
VkImageView resolve[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT]; // 64 bytes
|
||||
VkImageView depth; // 8 bytes
|
||||
};
|
||||
struct FboVal {
|
||||
fvkmemory::resource_ptr<VulkanFramebuffer> handle;
|
||||
uint32_t timestamp;
|
||||
};
|
||||
static_assert(sizeof(VkRenderPass) == 8, "VkRenderPass has unexpected size.");
|
||||
static_assert(sizeof(VkImageView) == 8, "VkImageView has unexpected size.");
|
||||
static_assert(sizeof(FboKey) == 152, "FboKey has unexpected size.");
|
||||
using FboKeyHashFn = utils::hash::MurmurHashFn<FboKey>;
|
||||
struct FboKeyEqualFn {
|
||||
bool operator()(const FboKey& k1, const FboKey& k2) const;
|
||||
};
|
||||
|
||||
explicit VulkanFboCache(VkDevice device);
|
||||
~VulkanFboCache();
|
||||
|
||||
// Retrieves or creates a VkFramebuffer handle.
|
||||
fvkmemory::resource_ptr<VulkanFramebuffer> getFramebuffer(FboKey const& config,
|
||||
fvkmemory::ResourceManager* resManager,
|
||||
fvkmemory::resource_ptr<VulkanRenderTarget> renderTarget) noexcept;
|
||||
|
||||
// Retrieves or creates a VkRenderPass handle.
|
||||
fvkmemory::resource_ptr<VulkanRenderPass> getRenderPass(
|
||||
RenderPassKey const& config, fvkmemory::ResourceManager* resManager) noexcept;
|
||||
@@ -115,17 +87,11 @@ public:
|
||||
// Evicts old unused Vulkan objects. Call this once per frame.
|
||||
void gc() noexcept;
|
||||
|
||||
// Frees all Framebuffer objects. Call this every time a the swapchain is resized
|
||||
void resetFramebuffers() noexcept;
|
||||
|
||||
// Frees all Vulkan objects. Call this during shutdown before the device is destroyed.
|
||||
void terminate() noexcept;
|
||||
|
||||
private:
|
||||
VkDevice mDevice;
|
||||
using FboMap = tsl::robin_map<FboKey, FboVal, FboKeyHashFn, FboKeyEqualFn>;
|
||||
FboMap mFramebufferCache;
|
||||
|
||||
using RenderPassMap = tsl::robin_map<RenderPassKey, RenderPassVal, RenderPassHash, RenderPassEq>;
|
||||
RenderPassMap mRenderPassCache;
|
||||
tsl::robin_map<VkRenderPass, uint32_t> mRenderPassRefCount;
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
#include "vulkan/utils/Definitions.h"
|
||||
#include "vulkan/utils/Image.h"
|
||||
#include "vulkan/utils/Spirv.h"
|
||||
#include "vulkan/vulkan_core.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <backend/platforms/VulkanPlatform.h>
|
||||
|
||||
#include <utils/compiler.h> // UTILS_FALLTHROUGH
|
||||
@@ -398,19 +400,25 @@ void VulkanProgram::flushPushConstants(VkPipelineLayout layout) {
|
||||
}
|
||||
|
||||
// Creates a special "default" render target (i.e. associated with the swap chain)
|
||||
VulkanRenderTarget::VulkanRenderTarget()
|
||||
VulkanRenderTarget::VulkanRenderTarget(VkDevice device)
|
||||
: HwRenderTarget(0, 0),
|
||||
mOffscreen(false),
|
||||
mProtected(false),
|
||||
mInfo(std::make_unique<Auxiliary>()) {
|
||||
mInfo->rpkey.samples = mInfo->fbkey.samples = 1;
|
||||
mDevice(device) {
|
||||
assert_invariant(device != VK_NULL_HANDLE);
|
||||
mRpKey.samples = 1;
|
||||
}
|
||||
|
||||
VulkanRenderTarget::~VulkanRenderTarget() = default;
|
||||
VulkanRenderTarget::~VulkanRenderTarget() {
|
||||
if (mDevice == VK_NULL_HANDLE) {
|
||||
return;
|
||||
}
|
||||
for (auto const& [renderpass, framebuffer, fence] : mVkFrameBuffers) {
|
||||
vkDestroyFramebuffer(mDevice, framebuffer, VKALLOC);
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanRenderTarget::bindSwapChain(fvkmemory::resource_ptr<VulkanSwapChain> swapchain) {
|
||||
assert_invariant(!mOffscreen);
|
||||
assert_invariant(!mInfo->colors[0]);
|
||||
assert_invariant(!mColors[0]);
|
||||
|
||||
VkExtent2D const extent = swapchain->getExtent();
|
||||
width = extent.width;
|
||||
@@ -418,36 +426,50 @@ void VulkanRenderTarget::bindSwapChain(fvkmemory::resource_ptr<VulkanSwapChain>
|
||||
mProtected = swapchain->isProtected();
|
||||
|
||||
VulkanAttachment color = createSwapchainAttachment(swapchain->getCurrentColor());
|
||||
assert_invariant(mInfo->attachments.size() == 0);
|
||||
mInfo->attachments.push_back(color);
|
||||
assert_invariant(mAttachments.size() == 0);
|
||||
mAttachments.push_back(color);
|
||||
|
||||
auto& fbkey = mInfo->fbkey;
|
||||
auto& rpkey = mInfo->rpkey;
|
||||
auto& rpkey = mRpKey;
|
||||
|
||||
rpkey.colorFormat[0] = color.getFormat();
|
||||
rpkey.viewCount = color.layerCount;
|
||||
fbkey.width = width;
|
||||
fbkey.height = height;
|
||||
fbkey.color[0] = color.getImageView();
|
||||
fbkey.resolve[0] = VK_NULL_HANDLE;
|
||||
|
||||
mFboInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
mFboInfo.width = width;
|
||||
mFboInfo.height = height;
|
||||
mFboInfo.layers = 1;
|
||||
mFboInfo.pAttachments = mFboAttachments;
|
||||
|
||||
uint32_t attachmentCount = 0;
|
||||
mFboAttachments[attachmentCount++] = color.getImageView();
|
||||
|
||||
if (swapchain->getDepth()) {
|
||||
VulkanAttachment depth = createSwapchainAttachment(swapchain->getDepth());
|
||||
mInfo->attachments.push_back(depth);
|
||||
mInfo->depthIndex = 1;
|
||||
mAttachments.push_back(depth);
|
||||
mDepthIndex = 1;
|
||||
|
||||
rpkey.depthFormat = depth.getFormat();
|
||||
fbkey.depth = depth.getImageView();
|
||||
mFboAttachments[attachmentCount++] = depth.getImageView();
|
||||
} else {
|
||||
rpkey.depthFormat = VK_FORMAT_UNDEFINED;
|
||||
fbkey.depth = VK_NULL_HANDLE;
|
||||
}
|
||||
mInfo->colors.set(0);
|
||||
mFboInfo.attachmentCount = attachmentCount;
|
||||
mColors.set(0);
|
||||
|
||||
std::vector<FboData> nbuffers;
|
||||
for (auto const& [renderpass, framebuffer, fence] : mVkFrameBuffers) {
|
||||
if (fence->getStatus() == VK_SUCCESS) {
|
||||
vkDestroyFramebuffer(mDevice, framebuffer, VKALLOC);
|
||||
} else {
|
||||
nbuffers.push_back({renderpass,framebuffer,fence});
|
||||
}
|
||||
}
|
||||
std::swap(mVkFrameBuffers, nbuffers);
|
||||
}
|
||||
|
||||
void VulkanRenderTarget::releaseSwapchain() {
|
||||
mInfo->colors = {};
|
||||
mInfo->attachments.clear();
|
||||
mColors = {};
|
||||
mAttachments.clear();
|
||||
}
|
||||
|
||||
VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||
@@ -456,9 +478,10 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
|
||||
uint8_t samples, VulkanAttachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT],
|
||||
VulkanAttachment depthStencil[2], VulkanStagePool& stagePool, uint8_t layerCount)
|
||||
: HwRenderTarget(width, height),
|
||||
mDevice(device),
|
||||
mOffscreen(true),
|
||||
mProtected(false),
|
||||
mInfo(std::make_unique<Auxiliary>()) {
|
||||
mProtected(false) {
|
||||
assert_invariant(device != VK_NULL_HANDLE);
|
||||
auto& depth = depthStencil[0];
|
||||
|
||||
// Constrain the sample count according to both kinds of sample count masks obtained from
|
||||
@@ -467,19 +490,25 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
|
||||
samples = fvkutils::reduceSampleCount(samples,
|
||||
limits.framebufferDepthSampleCounts & limits.framebufferColorSampleCounts);
|
||||
|
||||
auto& rpkey = mInfo->rpkey;
|
||||
auto& rpkey = mRpKey;
|
||||
rpkey.samples = samples;
|
||||
rpkey.depthFormat = depth.getFormat();
|
||||
rpkey.viewCount = layerCount;
|
||||
|
||||
auto& fbkey = mInfo->fbkey;
|
||||
fbkey.width = width;
|
||||
fbkey.height = height;
|
||||
fbkey.samples = samples;
|
||||
auto& fboInfo = mFboInfo;
|
||||
fboInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
fboInfo.width = width;
|
||||
fboInfo.height = height;
|
||||
fboInfo.layers = 1;
|
||||
fboInfo.pAttachments = mFboAttachments;
|
||||
|
||||
std::vector<VulkanAttachment>& attachments = mInfo->attachments;
|
||||
std::vector<VulkanAttachment>& attachments = mAttachments;
|
||||
std::vector<VulkanAttachment> msaaAttachments;
|
||||
|
||||
VkImageView colorAttachments[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = {};
|
||||
VkImageView resolveAttachments[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = {};
|
||||
VkImageView depthAttachment = VK_NULL_HANDLE;
|
||||
|
||||
for (int index = 0; index < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; index++) {
|
||||
VulkanAttachment& attachment = color[index];
|
||||
auto texture = attachment.texture;
|
||||
@@ -491,11 +520,11 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
|
||||
mProtected |= texture->getIsProtected();
|
||||
|
||||
attachments.push_back(attachment);
|
||||
mInfo->colors.set(index);
|
||||
mColors.set(index);
|
||||
|
||||
rpkey.colorFormat[index] = attachment.getFormat();
|
||||
fbkey.color[index] = attachment.getImageView();
|
||||
fbkey.resolve[index] = VK_NULL_HANDLE;
|
||||
colorAttachments[index] = attachment.getImageView();
|
||||
resolveAttachments[index] = VK_NULL_HANDLE;
|
||||
|
||||
if (samples > 1) {
|
||||
VulkanAttachment msaaAttachment = {};
|
||||
@@ -513,30 +542,30 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
|
||||
.layerCount = layerCount,
|
||||
};
|
||||
|
||||
fbkey.resolve[index] = attachment.getImageView();
|
||||
resolveAttachments[index] = attachment.getImageView();
|
||||
} else {
|
||||
msaaAttachment = {
|
||||
.texture = texture,
|
||||
.layerCount = layerCount,
|
||||
};
|
||||
}
|
||||
fbkey.color[index] = msaaAttachment.getImageView();
|
||||
colorAttachments[index] = msaaAttachment.getImageView();
|
||||
msaaAttachments.push_back(msaaAttachment);
|
||||
}
|
||||
}
|
||||
|
||||
if (attachments.size() > 0 && samples > 1 && msaaAttachments.size() > 0) {
|
||||
mInfo->msaaIndex = (uint8_t) attachments.size();
|
||||
mMsaaIndex = (uint8_t) attachments.size();
|
||||
attachments.insert(attachments.end(), msaaAttachments.begin(), msaaAttachments.end());
|
||||
}
|
||||
|
||||
if (depth.texture) {
|
||||
auto depthTexture = depth.texture;
|
||||
mInfo->depthIndex = (uint8_t) attachments.size();
|
||||
mDepthIndex = (uint8_t) attachments.size();
|
||||
attachments.push_back(depth);
|
||||
fbkey.depth = depth.getImageView();
|
||||
depthAttachment = depth.getImageView();
|
||||
if (samples > 1) {
|
||||
mInfo->msaaDepthIndex = mInfo->depthIndex;
|
||||
mMsaaDepthIndex = mDepthIndex;
|
||||
if (depthTexture->samples == 1) {
|
||||
// MSAA depth texture must have the mipmap count of 1
|
||||
uint8_t const msLevel = 1;
|
||||
@@ -544,16 +573,54 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
|
||||
// exist.
|
||||
auto msaaTexture = initMsaaTexture(depthTexture, device, physicalDevice, context,
|
||||
allocator, commands, resourceManager, msLevel, samples, stagePool);
|
||||
mInfo->msaaDepthIndex = (uint8_t) attachments.size();
|
||||
mMsaaDepthIndex = (uint8_t) attachments.size();
|
||||
VulkanAttachment msaaAttachment = {
|
||||
.texture = msaaTexture,
|
||||
.layerCount = layerCount,
|
||||
};
|
||||
attachments.push_back(msaaAttachment);
|
||||
fbkey.depth = msaaAttachment.getImageView();
|
||||
depthAttachment = msaaAttachment.getImageView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t attachmentCount = 0;
|
||||
for (int index = 0; index < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; index++) {
|
||||
if (colorAttachments[index]) {
|
||||
mFboAttachments[attachmentCount++] = colorAttachments[index];
|
||||
}
|
||||
}
|
||||
for (int index = 0; index < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; index++) {
|
||||
if (resolveAttachments[index]) {
|
||||
mFboAttachments[attachmentCount++] = resolveAttachments[index];
|
||||
}
|
||||
}
|
||||
if (depthAttachment) {
|
||||
mFboAttachments[attachmentCount++] = depthAttachment;
|
||||
}
|
||||
fboInfo.attachmentCount = attachmentCount;
|
||||
}
|
||||
|
||||
VkFramebuffer VulkanRenderTarget::getFramebuffer(VkRenderPass renderPass, VulkanCommandBuffer* commands) {
|
||||
if (mOffscreen) {
|
||||
for (auto& [rp, fb, fence] : mVkFrameBuffers) {
|
||||
if (rp == renderPass) {
|
||||
fence = commands->getFenceStatus();
|
||||
return fb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VkDevice device = mDevice;
|
||||
|
||||
mFboInfo.renderPass = renderPass;
|
||||
VkFramebuffer framebuffer;
|
||||
VkResult error = vkCreateFramebuffer(device, &mFboInfo, VKALLOC, &framebuffer);
|
||||
FILAMENT_CHECK_POSTCONDITION(error == VK_SUCCESS) << "Unable to create framebuffer."
|
||||
<< " error=" << static_cast<int32_t>(error);
|
||||
mVkFrameBuffers.push_back({renderPass, framebuffer, commands->getFenceStatus()});
|
||||
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
void VulkanRenderTarget::transformClientRectToPlatform(VkRect2D* bounds) const {
|
||||
@@ -570,10 +637,10 @@ uint8_t VulkanRenderTarget::getColorTargetCount(const VulkanRenderPassContext& p
|
||||
return 1;
|
||||
}
|
||||
if (pass.currentSubpass == 1) {
|
||||
return mInfo->colors.count();
|
||||
return mColors.count();
|
||||
}
|
||||
uint8_t count = 0;
|
||||
mInfo->colors.forEachSetBit([&count, &pass](size_t index) {
|
||||
mColors.forEachSetBit([&count, &pass](size_t index) {
|
||||
if (!(pass.params.subpassMask & (1 << index))) {
|
||||
count++;
|
||||
}
|
||||
@@ -582,8 +649,7 @@ uint8_t VulkanRenderTarget::getColorTargetCount(const VulkanRenderPassContext& p
|
||||
}
|
||||
|
||||
void VulkanRenderTarget::emitBarriersBeginRenderPass(VulkanCommandBuffer& commands) {
|
||||
auto& attachments = mInfo->attachments;
|
||||
auto samples = mInfo->fbkey.samples;
|
||||
auto samples = mRpKey.samples;
|
||||
auto barrier = [&commands](VulkanAttachment& attachment, VulkanLayout const layout) {
|
||||
auto tex = attachment.texture;
|
||||
auto const& range = attachment.getSubresourceRange();
|
||||
@@ -594,24 +660,24 @@ void VulkanRenderTarget::emitBarriersBeginRenderPass(VulkanCommandBuffer& comman
|
||||
}
|
||||
};
|
||||
|
||||
for (size_t i = 0, count = mInfo->colors.count(); i < count; ++i) {
|
||||
auto& attachment = attachments[i];
|
||||
for (size_t i = 0, count = mColors.count(); i < count; ++i) {
|
||||
auto& attachment = mAttachments[i];
|
||||
auto tex = attachment.texture;
|
||||
if (samples == 1 || tex->samples == 1) {
|
||||
barrier(attachment, VulkanLayout::COLOR_ATTACHMENT);
|
||||
}
|
||||
}
|
||||
if (mInfo->msaaIndex != Auxiliary::UNDEFINED_INDEX) {
|
||||
for (size_t i = mInfo->msaaIndex, count = mInfo->msaaIndex + mInfo->colors.count();
|
||||
if (mMsaaIndex != UNDEFINED_INDEX) {
|
||||
for (size_t i = mMsaaIndex, count = mMsaaIndex + mColors.count();
|
||||
i < count; ++i) {
|
||||
barrier(attachments[i], VulkanLayout::COLOR_ATTACHMENT);
|
||||
barrier(mAttachments[i], VulkanLayout::COLOR_ATTACHMENT);
|
||||
}
|
||||
}
|
||||
if (mInfo->depthIndex != Auxiliary::UNDEFINED_INDEX) {
|
||||
barrier(attachments[mInfo->depthIndex], VulkanLayout::DEPTH_ATTACHMENT);
|
||||
if (mDepthIndex != UNDEFINED_INDEX) {
|
||||
barrier(mAttachments[mDepthIndex], VulkanLayout::DEPTH_ATTACHMENT);
|
||||
}
|
||||
if (mInfo->msaaDepthIndex != Auxiliary::UNDEFINED_INDEX) {
|
||||
barrier(attachments[mInfo->msaaDepthIndex], VulkanLayout::DEPTH_ATTACHMENT);
|
||||
if (mMsaaDepthIndex != UNDEFINED_INDEX) {
|
||||
barrier(mAttachments[mMsaaDepthIndex], VulkanLayout::DEPTH_ATTACHMENT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,7 +686,7 @@ void VulkanRenderTarget::emitBarriersEndRenderPass(VulkanCommandBuffer& commands
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& attachment: mInfo->attachments) {
|
||||
for (auto& attachment: mAttachments) {
|
||||
auto const& range = attachment.getSubresourceRange();
|
||||
bool const isDepth = attachment.isDepth();
|
||||
auto texture = attachment.texture;
|
||||
@@ -715,16 +781,6 @@ VulkanRenderPrimitive::VulkanRenderPrimitive(PrimitiveType pt,
|
||||
vertexBuffer(vb),
|
||||
indexBuffer(ib) {}
|
||||
|
||||
VulkanFramebuffer::VulkanFramebuffer(VkDevice device, VkFramebuffer framebuffer,
|
||||
fvkmemory::resource_ptr<VulkanRenderTarget> renderTarget)
|
||||
: mDevice(device),
|
||||
mFramebuffer(framebuffer),
|
||||
mRenderTarget(renderTarget) {}
|
||||
|
||||
VulkanFramebuffer::~VulkanFramebuffer() {
|
||||
vkDestroyFramebuffer(mDevice, mFramebuffer, VKALLOC);
|
||||
}
|
||||
|
||||
VulkanRenderPass::VulkanRenderPass(VkDevice device, VkRenderPass renderPass)
|
||||
: mDevice(device), mRenderPass(renderPass) {}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "VulkanFboCache.h"
|
||||
#include "VulkanSwapChain.h"
|
||||
#include "VulkanTexture.h"
|
||||
#include "utils/compiler.h"
|
||||
#include "vulkan/VulkanCommands.h"
|
||||
#include "vulkan/memory/Resource.h"
|
||||
#include "vulkan/memory/ResourcePointer.h"
|
||||
@@ -35,6 +36,7 @@
|
||||
#include <backend/Program.h>
|
||||
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/LruCache.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/StructureOfArrays.h>
|
||||
#include <utils/bitset.h>
|
||||
@@ -372,12 +374,10 @@ struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource {
|
||||
~VulkanRenderTarget();
|
||||
|
||||
// Creates a special "default" render target (i.e. associated with the swap chain)
|
||||
explicit VulkanRenderTarget();
|
||||
explicit VulkanRenderTarget(VkDevice device);
|
||||
|
||||
VulkanRenderTarget(VulkanRenderTarget&& target)
|
||||
: HwRenderTarget(0, 0),
|
||||
mOffscreen(false),
|
||||
mProtected(false) {
|
||||
: HwRenderTarget(0, 0) {
|
||||
swap(std::move(target));
|
||||
}
|
||||
|
||||
@@ -394,34 +394,30 @@ struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource {
|
||||
return {width, height};
|
||||
}
|
||||
|
||||
inline VulkanAttachment& getColor0() const {
|
||||
assert_invariant(mInfo->colors[0]);
|
||||
return mInfo->attachments[0];
|
||||
inline VulkanAttachment const& getColor0() const {
|
||||
assert_invariant(mColors[0]);
|
||||
return mAttachments[0];
|
||||
}
|
||||
|
||||
inline VulkanAttachment& getDepth() const {
|
||||
inline VulkanAttachment const& getDepth() const {
|
||||
assert_invariant(hasDepth());
|
||||
if (mInfo->fbkey.samples == 1) {
|
||||
return mInfo->attachments[mInfo->depthIndex];
|
||||
if (mRpKey.samples == 1) {
|
||||
return mAttachments[mDepthIndex];
|
||||
}
|
||||
return mInfo->attachments[mInfo->msaaDepthIndex];
|
||||
return mAttachments[mMsaaDepthIndex];
|
||||
}
|
||||
|
||||
inline VulkanFboCache::RenderPassKey const& getRenderPassKey() const {
|
||||
return mInfo->rpkey;
|
||||
}
|
||||
|
||||
inline VulkanFboCache::FboKey const& getFboKey() const {
|
||||
return mInfo->fbkey;
|
||||
return mRpKey;
|
||||
}
|
||||
|
||||
inline uint8_t getSamples() const {
|
||||
return mInfo->fbkey.samples;
|
||||
return mRpKey.samples;
|
||||
}
|
||||
|
||||
uint8_t getColorTargetCount(VulkanRenderPassContext const& pass) const;
|
||||
|
||||
inline bool hasDepth() const { return mInfo->depthIndex != Auxiliary::UNDEFINED_INDEX; }
|
||||
inline bool hasDepth() const { return mDepthIndex != UNDEFINED_INDEX; }
|
||||
|
||||
inline bool isSwapChain() const { return !mOffscreen; }
|
||||
inline bool isProtected() const { return mProtected; }
|
||||
@@ -431,41 +427,65 @@ struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource {
|
||||
void releaseSwapchain();
|
||||
|
||||
bool isSwapchainBound() const {
|
||||
return isSwapChain() && mInfo->colors[0];
|
||||
return isSwapChain() && mColors[0];
|
||||
}
|
||||
|
||||
void emitBarriersBeginRenderPass(VulkanCommandBuffer& commands);
|
||||
|
||||
void emitBarriersEndRenderPass(VulkanCommandBuffer& commands);
|
||||
|
||||
VkFramebuffer getFramebuffer(VkRenderPass renderPass, VulkanCommandBuffer* commands);
|
||||
|
||||
private:
|
||||
void swap(VulkanRenderTarget&& target) {
|
||||
std::swap(width, target.width);
|
||||
std::swap(height, target.height);
|
||||
|
||||
assert_invariant(target.mDevice != VK_NULL_HANDLE);
|
||||
//assert_invariant(mDevice != VK_NULL_HANDLE);
|
||||
|
||||
std::swap(mDevice, target.mDevice);
|
||||
std::swap(mColors, target.mColors);
|
||||
std::swap(mDepthIndex, target.mDepthIndex);
|
||||
std::swap(mMsaaDepthIndex, target.mMsaaDepthIndex);
|
||||
std::swap(mMsaaIndex, target.mMsaaIndex);
|
||||
|
||||
std::swap(mOffscreen, target.mOffscreen);
|
||||
std::swap(mProtected, target.mProtected);
|
||||
std::swap(mInfo, target.mInfo);
|
||||
|
||||
std::swap(mAttachments, target.mAttachments);
|
||||
std::swap(mRpKey, target.mRpKey);
|
||||
std::swap(mFboInfo, target.mFboInfo);
|
||||
std::swap(mFboAttachments, target.mFboAttachments);
|
||||
}
|
||||
|
||||
struct Auxiliary {
|
||||
static constexpr int8_t UNDEFINED_INDEX = -1;
|
||||
static constexpr int8_t UNDEFINED_INDEX = -1;
|
||||
|
||||
explicit Auxiliary() noexcept = default;
|
||||
VkDevice mDevice = VK_NULL_HANDLE; // 8 bytes
|
||||
utils::bitset32 mColors; // 4
|
||||
int8_t mDepthIndex = UNDEFINED_INDEX; // 1
|
||||
int8_t mMsaaDepthIndex = UNDEFINED_INDEX; // 1
|
||||
int8_t mMsaaIndex = UNDEFINED_INDEX; // 1
|
||||
bool mOffscreen = false; // 1
|
||||
|
||||
VulkanFboCache::RenderPassKey rpkey = {};
|
||||
VulkanFboCache::FboKey fbkey = {};
|
||||
std::vector<VulkanAttachment> attachments;
|
||||
utils::bitset32 colors;
|
||||
int8_t depthIndex = UNDEFINED_INDEX;
|
||||
int8_t msaaDepthIndex = UNDEFINED_INDEX;
|
||||
int8_t msaaIndex = UNDEFINED_INDEX;
|
||||
struct FboData {
|
||||
VkRenderPass renderpass;
|
||||
VkFramebuffer framebuffer;
|
||||
std::shared_ptr<VulkanCmdFence> fence;
|
||||
};
|
||||
bool mOffscreen;
|
||||
bool mProtected;
|
||||
|
||||
std::unique_ptr<Auxiliary> mInfo;
|
||||
std::vector<FboData> mVkFrameBuffers;
|
||||
std::vector<VulkanAttachment> mAttachments; // 24 bytes
|
||||
VulkanFboCache::RenderPassKey mRpKey = {}; // 56 bytes
|
||||
VkFramebufferCreateInfo mFboInfo = {}; // 64 bytes
|
||||
VkImageView mFboAttachments[
|
||||
MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT + MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT + 1] = {}; // 136
|
||||
bool mProtected = false; // 1
|
||||
UTILS_UNUSED bool padding[3] = {}; // 3
|
||||
};
|
||||
|
||||
static_assert(sizeof(VulkanRenderTarget) == 352);
|
||||
|
||||
struct VulkanBufferObject;
|
||||
|
||||
struct VulkanVertexBufferInfo : public HwVertexBufferInfo, fvkmemory::Resource {
|
||||
@@ -585,26 +605,6 @@ struct VulkanRenderPrimitive : public HwRenderPrimitive, fvkmemory::Resource {
|
||||
fvkmemory::resource_ptr<VulkanIndexBuffer> indexBuffer;
|
||||
};
|
||||
|
||||
struct VulkanFramebuffer : public fvkmemory::Resource {
|
||||
VulkanFramebuffer(VkDevice device,
|
||||
VkFramebuffer framebuffer,
|
||||
fvkmemory::resource_ptr<VulkanRenderTarget> renderTarget);
|
||||
~VulkanFramebuffer();
|
||||
|
||||
inline VkFramebuffer getVkFramebuffer() const noexcept {
|
||||
return mFramebuffer;
|
||||
}
|
||||
|
||||
private:
|
||||
VkDevice mDevice;
|
||||
VkFramebuffer mFramebuffer;
|
||||
|
||||
// We need to keep a reference to the renderTarget because the key of the framebuffer in the
|
||||
// cache has references to the image views that are derived from the textures of the render
|
||||
// target.
|
||||
fvkmemory::resource_ptr<VulkanRenderTarget> mRenderTarget;
|
||||
};
|
||||
|
||||
struct VulkanRenderPass : public fvkmemory::Resource {
|
||||
VulkanRenderPass(VkDevice device, VkRenderPass renderPass);
|
||||
~VulkanRenderPass();
|
||||
|
||||
@@ -42,7 +42,6 @@ template ResourceType getTypeEnum<VulkanSync>() noexcept;
|
||||
template ResourceType getTypeEnum<VulkanMemoryMappedBuffer>() noexcept;
|
||||
template ResourceType getTypeEnum<VulkanSemaphore>() noexcept;
|
||||
template ResourceType getTypeEnum<VulkanStream>() noexcept;
|
||||
template ResourceType getTypeEnum<VulkanFramebuffer>() noexcept;
|
||||
template ResourceType getTypeEnum<VulkanRenderPass>() noexcept;
|
||||
|
||||
template<typename D>
|
||||
@@ -110,9 +109,6 @@ ResourceType getTypeEnum() noexcept {
|
||||
if constexpr (std::is_same_v<D, VulkanStream>) {
|
||||
return ResourceType::STREAM;
|
||||
}
|
||||
if constexpr (std::is_same_v<D, VulkanFramebuffer>) {
|
||||
return ResourceType::FRAMEBUFFER;
|
||||
}
|
||||
if constexpr (std::is_same_v<D, VulkanRenderPass>) {
|
||||
return ResourceType::RENDER_PASS;
|
||||
}
|
||||
@@ -163,8 +159,6 @@ std::string_view getTypeStr(ResourceType type) {
|
||||
return "Semaphore";
|
||||
case ResourceType::STREAM:
|
||||
return "VulkanStream";
|
||||
case ResourceType::FRAMEBUFFER:
|
||||
return "Framebuffer";
|
||||
case ResourceType::RENDER_PASS:
|
||||
return "RenderPass";
|
||||
case ResourceType::UNDEFINED_TYPE:
|
||||
|
||||
@@ -56,9 +56,8 @@ enum class ResourceType : uint8_t {
|
||||
MEMORY_MAPPED_BUFFER = 18,
|
||||
SEMAPHORE = 19,
|
||||
STREAM = 20,
|
||||
FRAMEBUFFER = 21,
|
||||
RENDER_PASS = 22,
|
||||
UNDEFINED_TYPE = 23, // Must be the last enum because we use it for iterating over the enums.
|
||||
RENDER_PASS = 21,
|
||||
UNDEFINED_TYPE = 22, // Must be the last enum because we use it for iterating over the enums.
|
||||
};
|
||||
|
||||
template<typename D>
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <utils/Logger.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace filament::backend::fvkmemory {
|
||||
|
||||
namespace {
|
||||
@@ -34,9 +36,24 @@ ResourceManager::ResourceManager(size_t arenaSize, bool disableUseAfterFreeCheck
|
||||
void ResourceManager::gc() noexcept {
|
||||
FVK_SYSTRACE_CONTEXT();
|
||||
FVK_SYSTRACE_START("ResourceManager::gc");
|
||||
auto destroyAll = [this](GcList& list) {
|
||||
for (auto const& [type, id]: list) {
|
||||
destroyWithType(type, id);
|
||||
uint32_t counts[(size_t) ResourceType::UNDEFINED_TYPE] = {};
|
||||
auto destroyAll = [this, &counts](GcList& list) {
|
||||
FVK_SYSTRACE_CONTEXT();
|
||||
if (list.empty()) {
|
||||
return;
|
||||
}
|
||||
std::sort(list.begin(), list.end(), [](auto const& a, auto const& b) {
|
||||
return a.first < b.first;
|
||||
});
|
||||
for (size_t i = 0; i < list.size(); ) {
|
||||
ResourceType type = list[i].first;
|
||||
FVK_SYSTRACE_START(getTypeStr(type).data());
|
||||
while (i < list.size() && list[i].first == type) {
|
||||
destroyWithType(type, list[i].second);
|
||||
counts[(size_t) type]++;
|
||||
i++;
|
||||
}
|
||||
FVK_SYSTRACE_END();
|
||||
}
|
||||
list.clear();
|
||||
};
|
||||
@@ -45,14 +62,30 @@ void ResourceManager::gc() noexcept {
|
||||
// Note that we're not copying mThreadSafeGcList because the objects here do not have
|
||||
// resource_ptrs to other handle objects, so their desctruction would not add more elements
|
||||
// to mThreadSafeGcList.
|
||||
FVK_SYSTRACE_START("gc::threadSafeList");
|
||||
std::unique_lock<utils::Mutex> lock(mThreadSafeGcListMutex);
|
||||
destroyAll(mThreadSafeGcList);
|
||||
FVK_SYSTRACE_END();
|
||||
}
|
||||
|
||||
FVK_SYSTRACE_START("gc::mainList");
|
||||
GcList gcs;
|
||||
std::swap(gcs, mGcList);
|
||||
destroyAll(gcs);
|
||||
FVK_SYSTRACE_END();
|
||||
|
||||
bool hasGarbage = false;
|
||||
for (size_t i = 0; i < (size_t) ResourceType::UNDEFINED_TYPE; ++i) {
|
||||
if (counts[i] > 0) {
|
||||
if (!hasGarbage) {
|
||||
LOG(INFO) << "ResourceManager GC freed:";
|
||||
hasGarbage = true;
|
||||
}
|
||||
LOG(INFO) << " " << getTypeStr((ResourceType) i) << "=" << counts[i];
|
||||
}
|
||||
}
|
||||
|
||||
FVK_SYSTRACE_END();
|
||||
}
|
||||
|
||||
void ResourceManager::terminate() noexcept {
|
||||
@@ -126,9 +159,6 @@ void ResourceManager::destroyWithType(ResourceType type, HandleId id) {
|
||||
case ResourceType::STREAM:
|
||||
destruct<VulkanStream>(Handle<VulkanStream>(id));
|
||||
break;
|
||||
case ResourceType::FRAMEBUFFER:
|
||||
destruct<VulkanFramebuffer>(Handle<VulkanFramebuffer>(id));
|
||||
break;
|
||||
case ResourceType::RENDER_PASS:
|
||||
destruct<VulkanRenderPass>(Handle<VulkanRenderPass>(id));
|
||||
break;
|
||||
@@ -149,11 +179,11 @@ void ResourceManager::traceConstruction(ResourceType type, HandleId id) {
|
||||
|
||||
void ResourceManager::print() const noexcept {
|
||||
#if FVK_ENABLED(FVK_DEBUG_RESOURCE_LEAK)
|
||||
LOG(ERROR) << "-------------------";
|
||||
for (size_t i = 0; i < (size_t) ResourceType::UNDEFINED_TYPE; ++i) {
|
||||
LOG(ERROR) << " " << getTypeStr((ResourceType) i) << "=" << COUNTER[i];
|
||||
}
|
||||
LOG(ERROR) << "+++++++++++++++++++";
|
||||
LOG(ERROR) << "-------------------";
|
||||
for (size_t i = 0; i < (size_t) ResourceType::UNDEFINED_TYPE; ++i) {
|
||||
LOG(ERROR) << " " << getTypeStr((ResourceType) i) << "=" << COUNTER[i];
|
||||
}
|
||||
LOG(ERROR) << "+++++++++++++++++++";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user