vulkan: minor fixes (#6874)

- flush() and wait() before destroying a swapchain
 - Make sure the debug marker extension is enabled under correct
   circumstances.
 - Change shared_ptrs to unique_ptrs and raw pointers.
 - Rename most teardown methods to terminate()
This commit is contained in:
Powei Feng
2023-06-07 11:05:47 -07:00
committed by GitHub
parent b0238c1560
commit e0e2c76d2f
23 changed files with 111 additions and 174 deletions
@@ -116,8 +116,7 @@ VulkanBlitter::VulkanBlitter(VulkanStagePool& stagePool, VulkanPipelineCache& pi
mSamplerCache(samplerCache) {}
void VulkanBlitter::initialize(VkPhysicalDevice physicalDevice, VkDevice device,
VmaAllocator allocator, std::shared_ptr<VulkanCommands> commands,
std::shared_ptr<VulkanTexture> emptyTexture) noexcept {
VmaAllocator allocator, VulkanCommands* commands, VulkanTexture* emptyTexture) noexcept {
mPhysicalDevice = physicalDevice;
mDevice = device;
mAllocator = allocator;
@@ -181,7 +180,7 @@ void VulkanBlitter::blitDepth(BlitArgs args) {
args.dstRectPair);
}
void VulkanBlitter::shutdown() noexcept {
void VulkanBlitter::terminate() noexcept {
if (mDevice) {
delete mDepthResolveProgram;
mDepthResolveProgram = nullptr;
@@ -198,9 +197,6 @@ void VulkanBlitter::shutdown() noexcept {
mParamsBuffer = nullptr;
}
}
mCommands.reset();
mEmptyTexture.reset();
}
// If we created these shader modules in the constructor, the device might not be ready yet.
+4 -5
View File
@@ -36,8 +36,7 @@ public:
VulkanFboCache& fboCache, VulkanSamplerCache& samplerCache) noexcept;
void initialize(VkPhysicalDevice physicalDevice, VkDevice device, VmaAllocator allocator,
std::shared_ptr<VulkanCommands> commands,
std::shared_ptr<VulkanTexture> emptyTexture) noexcept;
VulkanCommands* commands, VulkanTexture* emptyTexture) noexcept;
struct BlitArgs {
const VulkanRenderTarget* dstTarget;
@@ -51,7 +50,7 @@ public:
void blitColor(BlitArgs args);
void blitDepth(BlitArgs args);
void shutdown() noexcept;
void terminate() noexcept;
private:
void lazyInit() noexcept;
@@ -67,8 +66,8 @@ private:
UTILS_UNUSED VkPhysicalDevice mPhysicalDevice;
VkDevice mDevice;
VmaAllocator mAllocator;
std::shared_ptr<VulkanCommands> mCommands;
std::shared_ptr<VulkanTexture> mEmptyTexture;
VulkanCommands* mCommands;
VulkanTexture* mEmptyTexture;
VulkanStagePool& mStagePool;
VulkanPipelineCache& mPipelineCache;
+1 -2
View File
@@ -23,7 +23,7 @@ using namespace bluevk;
namespace filament::backend {
VulkanBuffer::VulkanBuffer(VmaAllocator allocator, std::shared_ptr<VulkanCommands> commands,
VulkanBuffer::VulkanBuffer(VmaAllocator allocator, VulkanCommands* commands,
VulkanStagePool& stagePool, VkBufferUsageFlags usage, uint32_t numBytes)
: mAllocator(allocator), mCommands(commands), mStagePool(stagePool), mUsage(usage) {
@@ -51,7 +51,6 @@ void VulkanBuffer::terminate() {
vmaDestroyBuffer(mAllocator, mGpuBuffer, mGpuMemory);
mGpuMemory = VK_NULL_HANDLE;
mGpuBuffer = VK_NULL_HANDLE;
mCommands.reset();
}
void VulkanBuffer::loadFromCpu(const void* cpuData, uint32_t byteOffset, uint32_t numBytes) const {
+3 -3
View File
@@ -25,15 +25,15 @@ namespace filament::backend {
// Encapsulates a Vulkan buffer, its attached DeviceMemory and a staging area.
class VulkanBuffer {
public:
VulkanBuffer(VmaAllocator allocator, std::shared_ptr<VulkanCommands> commands,
VulkanStagePool& stagePool, VkBufferUsageFlags usage, uint32_t numBytes);
VulkanBuffer(VmaAllocator allocator, VulkanCommands* commands, VulkanStagePool& stagePool,
VkBufferUsageFlags usage, uint32_t numBytes);
~VulkanBuffer();
void terminate();
void loadFromCpu(const void* cpuData, uint32_t byteOffset, uint32_t numBytes) const;
VkBuffer getGpuBuffer() const { return mGpuBuffer; }
private:
VmaAllocator mAllocator;
std::shared_ptr<VulkanCommands> mCommands;
VulkanCommands* mCommands;
VulkanStagePool& mStagePool;
VmaAllocation mGpuMemory = VK_NULL_HANDLE;
+1 -66
View File
@@ -39,73 +39,8 @@ struct VulkanTexture;
class VulkanStagePool;
struct VulkanTimerQuery;
// TODO: We used std::shared_ptr in various places across the vulkan backend, but VulkanTexture*
// also maps to HwTexture so it's not possible to switch in VulkanAttachment. Hence we introduce
// this temporary class. We need to revisit the ownership pattern and use of smart pointer in the
// vulkan backend, in particular std::shared_ptr uses atomic, which is overhead we do not need.
struct TexturePointer {
TexturePointer() = default;
explicit TexturePointer(VulkanTexture* tex) :mTexture(tex) {}
explicit TexturePointer(std::shared_ptr<VulkanTexture> tex) :mTexture(tex) {}
inline TexturePointer& operator=(VulkanTexture* tex) {
mTexture = tex;
return *this;
}
inline TexturePointer& operator=(std::shared_ptr<VulkanTexture> tex) {
mTexture = tex;
return *this;
}
// Be careful not to leak here. Should only be used in local scope.
explicit operator VulkanTexture*() const {
if (mTexture.index() == 0) {
return std::get<0>(mTexture);
}
return std::get<1>(mTexture).get();
}
// Be careful not to leak here. Should only be used in local scope.
explicit operator VulkanTexture const*() const {
if (mTexture.index() == 0) {
return std::get<0>(mTexture);
}
return std::get<1>(mTexture).get();
}
explicit operator std::shared_ptr<VulkanTexture>() const {
assert_invariant(mTexture.index() == 1);
return std::get<1>(mTexture);
}
inline operator bool() const {
if (mTexture.index() == 0) {
return std::get<0>(mTexture) != nullptr;
}
return (bool) std::get<1>(mTexture);
}
inline VulkanTexture* operator->() {
if (mTexture.index() == 0) {
return std::get<0>(mTexture);
}
return std::get<1>(mTexture).get();
}
inline VulkanTexture const* operator->() const {
if (mTexture.index() == 0) {
return std::get<0>(mTexture);
}
return std::get<1>(mTexture).get();
}
private:
std::variant<VulkanTexture*, std::shared_ptr<VulkanTexture>> mTexture;
};
struct VulkanAttachment {
TexturePointer texture;
VulkanTexture* texture;
uint8_t level = 0;
uint16_t layer = 0;
VkImage getImage() const;
@@ -84,7 +84,7 @@ void VulkanDisposer::gc() noexcept {
disposables.swap(mDisposables);
}
void VulkanDisposer::reset() noexcept {
void VulkanDisposer::terminate() noexcept {
#ifndef NDEBUG
utils::slog.i << mDisposables.size() << " disposables are outstanding." << utils::io::endl;
#endif
+1 -1
View File
@@ -44,7 +44,7 @@ public:
void gc() noexcept;
// Invokes the destructor function for all disposables, regardless of reference count.
void reset() noexcept;
void terminate() noexcept;
private:
struct Disposable {
+32 -31
View File
@@ -92,12 +92,11 @@ VmaAllocator createAllocator(VkInstance instance, VkPhysicalDevice physicalDevic
return allocator;
}
std::shared_ptr<VulkanTexture> createEmptyTexture(VkDevice device, VkPhysicalDevice physicalDevice,
VulkanContext const& context, VmaAllocator allocator,
std::shared_ptr<VulkanCommands> commands, VulkanStagePool& stagePool) {
std::shared_ptr<VulkanTexture> emptyTexture = std::make_shared<VulkanTexture>(device,
physicalDevice, context, allocator, commands, SamplerType::SAMPLER_2D, 1,
TextureFormat::RGBA8, 1, 1, 1, 1,
VulkanTexture* createEmptyTexture(VkDevice device, VkPhysicalDevice physicalDevice,
VulkanContext const& context, VmaAllocator allocator, VulkanCommands* commands,
VulkanStagePool& stagePool) {
VulkanTexture* emptyTexture = new VulkanTexture(device, physicalDevice, context, allocator,
commands, SamplerType::SAMPLER_2D, 1, TextureFormat::RGBA8, 1, 1, 1, 1,
TextureUsage::DEFAULT | TextureUsage::COLOR_ATTACHMENT | TextureUsage::SUBPASS_INPUT,
stagePool);
uint32_t black = 0;
@@ -186,22 +185,22 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& contex
}
#endif
mTimestamps = std::make_unique<VulkanTimestamps>(mPlatform->getDevice());
mCommands = std::make_shared<VulkanCommands>(mPlatform->getDevice(),
mCommands = std::make_unique<VulkanCommands>(mPlatform->getDevice(),
mPlatform->getGraphicsQueue(), mPlatform->getGraphicsQueueFamilyIndex());
mCommands->setObserver(&mPipelineCache);
mPipelineCache.setDevice(mPlatform->getDevice(), mAllocator);
// TOOD: move them all to be initialized by constructor
mStagePool.initialize(mAllocator, mCommands);
mStagePool.initialize(mAllocator, mCommands.get());
mFramebufferCache.initialize(mPlatform->getDevice());
mSamplerCache.initialize(mPlatform->getDevice());
mEmptyTexture = createEmptyTexture(mPlatform->getDevice(), mPlatform->getPhysicalDevice(),
mContext, mAllocator, mCommands, mStagePool);
mEmptyTexture.reset(createEmptyTexture(mPlatform->getDevice(), mPlatform->getPhysicalDevice(),
mContext, mAllocator, mCommands.get(), mStagePool));
mPipelineCache.setDummyTexture(mEmptyTexture->getPrimaryImageView());
mBlitter.initialize(mPlatform->getPhysicalDevice(), mPlatform->getDevice(), mAllocator,
mCommands, mEmptyTexture);
mCommands.get(), mEmptyTexture.get());
}
VulkanDriver::~VulkanDriver() noexcept = default;
@@ -225,20 +224,22 @@ ShaderModel VulkanDriver::getShaderModel() const noexcept {
}
void VulkanDriver::terminate() {
mEmptyTexture.reset();
// Command buffers should come first since it might have commands depending on resources that
// are about to be destroyed.
mCommands.reset();
mEmptyTexture.reset();
mTimestamps.reset();
mBlitter.shutdown();
mBlitter.terminate();
// Allow the stage pool and disposer to clean up.
mStagePool.gc();
mDisposer.reset();
mDisposer.terminate();
mStagePool.reset();
mPipelineCache.destroyCache();
mStagePool.terminate();
mPipelineCache.terminate();
mFramebufferCache.reset();
mSamplerCache.reset();
mSamplerCache.terminate();
vmaDestroyAllocator(mAllocator);
@@ -335,7 +336,7 @@ void VulkanDriver::destroyVertexBuffer(Handle<HwVertexBuffer> vbh) {
void VulkanDriver::createIndexBufferR(Handle<HwIndexBuffer> ibh, ElementType elementType,
uint32_t indexCount, BufferUsage usage) {
auto elementSize = (uint8_t) getElementTypeSize(elementType);
auto indexBuffer = construct<VulkanIndexBuffer>(ibh, mAllocator, mCommands, mStagePool,
auto indexBuffer = construct<VulkanIndexBuffer>(ibh, mAllocator, mCommands.get(), mStagePool,
elementSize, indexCount);
mDisposer.createDisposable(indexBuffer,
[this, ibh]() { destructBuffer<VulkanIndexBuffer>(ibh); });
@@ -350,7 +351,7 @@ void VulkanDriver::destroyIndexBuffer(Handle<HwIndexBuffer> ibh) {
void VulkanDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byteCount,
BufferObjectBinding bindingType, BufferUsage usage) {
auto bufferObject = construct<VulkanBufferObject>(boh, mAllocator, mCommands, mStagePool,
auto bufferObject = construct<VulkanBufferObject>(boh, mAllocator, mCommands.get(), mStagePool,
byteCount, bindingType, usage);
mDisposer.createDisposable(bufferObject,
[this, boh]() { destructBuffer<VulkanBufferObject>(boh); });
@@ -374,8 +375,8 @@ void VulkanDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
TextureUsage usage) {
auto vktexture = construct<VulkanTexture>(th, mPlatform->getDevice(),
mPlatform->getPhysicalDevice(), mContext, mAllocator, mCommands, target, levels, format,
samples, w, h, depth, usage, mStagePool);
mPlatform->getPhysicalDevice(), mContext, mAllocator, mCommands.get(), target, levels,
format, samples, w, h, depth, usage, mStagePool);
mDisposer.createDisposable(vktexture, [this, th]() { destruct<VulkanTexture>(th); });
}
@@ -386,8 +387,8 @@ void VulkanDriver::createTextureSwizzledR(Handle<HwTexture> th, SamplerType targ
TextureSwizzle swizzleArray[] = {r, g, b, a};
const VkComponentMapping swizzleMap = getSwizzleMap(swizzleArray);
auto vktexture = construct<VulkanTexture>(th, mPlatform->getDevice(),
mPlatform->getPhysicalDevice(), mContext, mAllocator, mCommands, target, levels, format,
samples, w, h, depth, usage, mStagePool, swizzleMap);
mPlatform->getPhysicalDevice(), mContext, mAllocator, mCommands.get(), target, levels,
format, samples, w, h, depth, usage, mStagePool, swizzleMap);
mDisposer.createDisposable(vktexture, [this, th]() {
destruct<VulkanTexture>(th);
});
@@ -441,7 +442,7 @@ void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
for (int i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; i++) {
if (color[i].handle) {
colorTargets[i] = {
.texture = TexturePointer(handle_cast<VulkanTexture*>(color[i].handle)),
.texture = handle_cast<VulkanTexture*>(color[i].handle),
.level = color[i].level,
.layer = color[i].layer,
};
@@ -455,7 +456,7 @@ void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
VulkanAttachment depthStencil[2] = {};
if (depth.handle) {
depthStencil[0] = {
.texture = TexturePointer(handle_cast<VulkanTexture*>(depth.handle)),
.texture = handle_cast<VulkanTexture*>(depth.handle),
.level = depth.level,
.layer = depth.layer,
};
@@ -467,7 +468,7 @@ void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
if (stencil.handle) {
depthStencil[1] = {
.texture = TexturePointer(handle_cast<VulkanTexture*>(stencil.handle)),
.texture = handle_cast<VulkanTexture*>(stencil.handle),
.level = stencil.level,
.layer = stencil.layer,
};
@@ -484,8 +485,8 @@ void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
assert_invariant(tmin.x >= width && tmin.y >= height);
auto renderTarget = construct<VulkanRenderTarget>(rth, mPlatform->getDevice(),
mPlatform->getPhysicalDevice(), mContext, mAllocator, mCommands, width, height, samples,
colorTargets, depthStencil, mStagePool);
mPlatform->getPhysicalDevice(), mContext, mAllocator, mCommands.get(), width, height,
samples, colorTargets, depthStencil, mStagePool);
mDisposer.createDisposable(renderTarget, [this, rth]() { destruct<VulkanRenderTarget>(rth); });
}
@@ -510,15 +511,15 @@ void VulkanDriver::createSyncR(Handle<HwSync> sh, int) {
}
void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags) {
construct<VulkanSwapChain>(sch, mPlatform, mContext, mAllocator, mCommands, mStagePool,
construct<VulkanSwapChain>(sch, mPlatform, mContext, mAllocator, mCommands.get(), mStagePool,
nativeWindow, flags);
}
void VulkanDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
uint32_t height, uint64_t flags) {
assert_invariant(width > 0 && height > 0 && "Vulkan requires non-zero swap chain dimensions.");
construct<VulkanSwapChain>(sch, mPlatform, mContext, mAllocator, mCommands, mStagePool, nullptr,
flags, VkExtent2D{width, height});
construct<VulkanSwapChain>(sch, mPlatform, mContext, mAllocator, mCommands.get(), mStagePool,
nullptr, flags, VkExtent2D{width, height});
}
void VulkanDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {
+2 -2
View File
@@ -138,9 +138,9 @@ private:
void collectGarbage();
VulkanPlatform* mPlatform = nullptr;
std::shared_ptr<VulkanCommands> mCommands;
std::unique_ptr<VulkanCommands> mCommands;
std::unique_ptr<VulkanTimestamps> mTimestamps;
std::shared_ptr<VulkanTexture> mEmptyTexture;
std::unique_ptr<VulkanTexture> mEmptyTexture;
VulkanSwapChain* mCurrentSwapChain = nullptr;
VulkanRenderTarget* mDefaultRenderTarget = nullptr;
@@ -68,7 +68,7 @@ void VulkanFboCache::initialize(VkDevice device) noexcept { mDevice = device; }
VulkanFboCache::~VulkanFboCache() {
ASSERT_POSTCONDITION(mFramebufferCache.empty() && mRenderPassCache.empty(),
"Please explicitly call reset() while the VkDevice is still alive.");
"Please explicitly call terminate() while the VkDevice is still alive.");
}
VkFramebuffer VulkanFboCache::getFramebuffer(FboKey config) noexcept {
@@ -132,15 +132,15 @@ VulkanRenderTarget::VulkanRenderTarget() : HwRenderTarget(0, 0), mOffscreen(fals
void VulkanRenderTarget::bindToSwapChain(VulkanSwapChain& swapChain) {
assert_invariant(!mOffscreen);
VkExtent2D const extent = swapChain.getExtent();
mColor[0] = { .texture = TexturePointer(swapChain.getCurrentColor()) };
mDepth = { .texture = TexturePointer(swapChain.getDepth()) };
mColor[0] = { .texture = swapChain.getCurrentColor() };
mDepth = { .texture = swapChain.getDepth() };
width = extent.width;
height = extent.height;
}
VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physicalDevice,
VulkanContext const& context, VmaAllocator allocator,
std::shared_ptr<VulkanCommands> commands, uint32_t width, uint32_t height, uint8_t samples,
VulkanCommands* commands, uint32_t width, uint32_t height, uint8_t samples,
VulkanAttachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT],
VulkanAttachment depthStencil[2], VulkanStagePool& stagePool)
: HwRenderTarget(width, height), mOffscreen(true), mSamples(samples) {
@@ -167,13 +167,13 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
if (texture && texture->samples == 1) {
auto msTexture = texture->getSidecar();
if (UTILS_UNLIKELY(!msTexture)) {
msTexture = std::make_shared<VulkanTexture>(device, physicalDevice, context,
msTexture = new VulkanTexture(device, physicalDevice, context,
allocator, commands, texture->target,
((VulkanTexture const*) texture)->levels, texture->format, samples,
texture->width, texture->height, texture->depth, texture->usage, stagePool);
texture->setSidecar(msTexture);
}
mMsaaAttachments[index] = {.texture = TexturePointer(msTexture)};
mMsaaAttachments[index] = {.texture = msTexture};
}
if (texture && texture->samples > 1) {
mMsaaAttachments[index] = mColor[index];
@@ -194,9 +194,9 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
uint8_t const msLevel = 1;
// Create sidecar MSAA texture for the depth attachment if it does not already exist.
std::shared_ptr<VulkanTexture> msTexture = depthTexture->getSidecar();
VulkanTexture* msTexture = depthTexture->getSidecar();
if (UTILS_UNLIKELY(!msTexture)) {
msTexture = std::make_shared<VulkanTexture>(device, physicalDevice, context, allocator,
msTexture = new VulkanTexture(device, physicalDevice, context, allocator,
commands, depthTexture->target, msLevel, depthTexture->format, samples,
depthTexture->width, depthTexture->height, depthTexture->depth, depthTexture->usage,
stagePool);
@@ -204,7 +204,7 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
}
mMsaaDepthAttachment = {
.texture = TexturePointer(msTexture),
.texture = msTexture,
.level = msLevel,
.layer = mDepth.layer,
};
@@ -264,7 +264,7 @@ VulkanVertexBuffer::VulkanVertexBuffer(VulkanContext& context, VulkanStagePool&
buffers(bufferCount, nullptr) {}
VulkanBufferObject::VulkanBufferObject(VmaAllocator allocator,
std::shared_ptr<VulkanCommands> commands, VulkanStagePool& stagePool, uint32_t byteCount,
VulkanCommands* commands, VulkanStagePool& stagePool, uint32_t byteCount,
BufferObjectBinding bindingType, BufferUsage usage)
: HwBufferObject(byteCount),
buffer(allocator, commands, stagePool, getBufferObjectUsage(bindingType), byteCount),
+3 -3
View File
@@ -53,7 +53,7 @@ struct VulkanRenderTarget : private HwRenderTarget {
// Creates an offscreen render target.
VulkanRenderTarget(VkDevice device, VkPhysicalDevice physicalDevice,
VulkanContext const& context, VmaAllocator allocator,
std::shared_ptr<VulkanCommands> commands, uint32_t width, uint32_t height,
VulkanCommands* commands, uint32_t width, uint32_t height,
uint8_t samples, VulkanAttachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT],
VulkanAttachment depthStencil[2], VulkanStagePool& stagePool);
@@ -90,7 +90,7 @@ struct VulkanVertexBuffer : public HwVertexBuffer {
};
struct VulkanIndexBuffer : public HwIndexBuffer {
VulkanIndexBuffer(VmaAllocator allocator, std::shared_ptr<VulkanCommands> commands,
VulkanIndexBuffer(VmaAllocator allocator, VulkanCommands* commands,
VulkanStagePool& stagePool, uint8_t elementSize, uint32_t indexCount)
: HwIndexBuffer(elementSize, indexCount),
buffer(allocator, commands, stagePool, VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
@@ -102,7 +102,7 @@ struct VulkanIndexBuffer : public HwIndexBuffer {
};
struct VulkanBufferObject : public HwBufferObject {
VulkanBufferObject(VmaAllocator allocator, std::shared_ptr<VulkanCommands> commands,
VulkanBufferObject(VmaAllocator allocator, VulkanCommands* commands,
VulkanStagePool& stagePool, uint32_t byteCount, BufferObjectBinding bindingType,
BufferUsage usage);
void terminate() {
@@ -86,7 +86,7 @@ VulkanPipelineCache::VulkanPipelineCache() : mCurrentRasterState(createDefaultRa
}
VulkanPipelineCache::~VulkanPipelineCache() {
// This does nothing because VulkanDriver::terminate() calls destroyCache() in order to
// This does nothing because VulkanDriver::terminate() calls terminate() in order to
// be explicit about teardown order of various components.
}
@@ -639,7 +639,7 @@ void VulkanPipelineCache::bindInputAttachment(uint32_t bindingIndex,
mDescriptorRequirements.inputAttachments[bindingIndex] = targetInfo;
}
void VulkanPipelineCache::destroyCache() noexcept {
void VulkanPipelineCache::terminate() noexcept {
// Symmetric to createLayoutsAndDescriptors.
destroyLayoutsAndDescriptors();
for (auto& iter : mPipelines) {
@@ -169,7 +169,7 @@ public:
// NOTE: In theory we should proffer "unbindSampler" but in practice we never destroy samplers.
// Destroys all managed Vulkan objects. This should be called before changing the VkDevice.
void destroyCache() noexcept;
void terminate() noexcept;
// vkCmdBindPipeline and vkCmdBindDescriptorSets establish bindings to a specific command
// buffer; they are not global to the device. Therefore we need to be notified when a
@@ -127,7 +127,7 @@ VkSampler VulkanSamplerCache::getSampler(SamplerParams params) noexcept {
return sampler;
}
void VulkanSamplerCache::reset() noexcept {
void VulkanSamplerCache::terminate() noexcept {
for (auto pair : mCache) {
vkDestroySampler(mDevice, pair.second, VKALLOC);
}
@@ -29,7 +29,7 @@ class VulkanSamplerCache {
public:
void initialize(VkDevice device);
VkSampler getSampler(SamplerParams params) noexcept;
void reset() noexcept;
void terminate() noexcept;
private:
VkDevice mDevice;
tsl::robin_map<uint32_t, VkSampler> mCache;
@@ -26,8 +26,7 @@ static constexpr uint32_t TIME_BEFORE_EVICTION = VK_MAX_COMMAND_BUFFERS;
namespace filament::backend {
void VulkanStagePool::initialize(VmaAllocator allocator,
std::shared_ptr<VulkanCommands> commands) noexcept {
void VulkanStagePool::initialize(VmaAllocator allocator, VulkanCommands* commands) noexcept {
mAllocator = allocator;
mCommands = commands;
}
@@ -185,7 +184,7 @@ void VulkanStagePool::gc() noexcept {
}
}
void VulkanStagePool::reset() noexcept {
void VulkanStagePool::terminate() noexcept {
for (auto stage : mUsedStages) {
vmaDestroyBuffer(mAllocator, stage->buffer, stage->memory);
delete stage;
@@ -209,8 +208,6 @@ void VulkanStagePool::reset() noexcept {
delete image;
}
mFreeStages.clear();
mCommands.reset();
}
} // namespace filament::backend
@@ -45,7 +45,7 @@ struct VulkanStageImage {
// This class manages two types of host-mappable staging areas: buffer stages and image stages.
class VulkanStagePool {
public:
void initialize(VmaAllocator allocator, std::shared_ptr<VulkanCommands> commands) noexcept;
void initialize(VmaAllocator allocator, VulkanCommands* commands) noexcept;
// Finds or creates a stage whose capacity is at least the given number of bytes.
// The stage is automatically released back to the pool after TIME_BEFORE_EVICTION frames.
@@ -60,11 +60,11 @@ public:
// Destroys all unused stages and asserts that there are no stages currently in use.
// This should be called while the context's VkDevice is still alive.
void reset() noexcept;
void terminate() noexcept;
private:
VmaAllocator mAllocator;
std::shared_ptr<VulkanCommands> mCommands;
VulkanCommands* mCommands;
// Use an ordered multimap for quick (capacity => stage) lookups using lower_bound().
std::multimap<uint32_t, VulkanStage const*> mFreeStages;
@@ -26,8 +26,8 @@ using namespace utils;
namespace filament::backend {
VulkanSwapChain::VulkanSwapChain(VulkanPlatform* platform, VulkanContext const& context,
VmaAllocator allocator, std::shared_ptr<VulkanCommands> commands,
VulkanStagePool& stagePool, void* nativeWindow, uint64_t flags, VkExtent2D extent)
VmaAllocator allocator, VulkanCommands* commands, VulkanStagePool& stagePool,
void* nativeWindow, uint64_t flags, VkExtent2D extent)
: mPlatform(platform),
mCommands(commands),
mAllocator(allocator),
@@ -48,6 +48,11 @@ VulkanSwapChain::VulkanSwapChain(VulkanPlatform* platform, VulkanContext const&
}
VulkanSwapChain::~VulkanSwapChain() {
// Must wait for the inflight command buffers to finish since they might contain the images
// we're about to destroy.
mCommands->flush();
mCommands->wait();
mPlatform->destroy(swapChain);
vkDestroySemaphore(mPlatform->getDevice(), mImageReady, VKALLOC);
}
@@ -60,11 +65,11 @@ void VulkanSwapChain::update() {
VkDevice const device = mPlatform->getDevice();
for (auto const color: bundle.colors) {
mColors.push_back(std::make_shared<VulkanTexture>(device, mAllocator, mCommands, color,
mColors.push_back(std::make_unique<VulkanTexture>(device, mAllocator, mCommands, color,
bundle.colorFormat, 1, bundle.extent.width, bundle.extent.height,
TextureUsage::COLOR_ATTACHMENT, mStagePool));
}
mDepth = std::make_shared<VulkanTexture>(device, mAllocator, mCommands, bundle.depth,
mDepth = std::make_unique<VulkanTexture>(device, mAllocator, mCommands, bundle.depth,
bundle.depthFormat, 1, bundle.extent.width, bundle.extent.height,
TextureUsage::DEPTH_ATTACHMENT, mStagePool);
+9 -10
View File
@@ -37,7 +37,7 @@ struct VulkanSurfaceSwapChain;
// A wrapper around the platform implementation of swapchain.
struct VulkanSwapChain : public HwSwapChain {
VulkanSwapChain(VulkanPlatform* platform, VulkanContext const& context, VmaAllocator allocator,
std::shared_ptr<VulkanCommands> commands, VulkanStagePool& stagePool,
VulkanCommands* commands, VulkanStagePool& stagePool,
void* nativeWindow, uint64_t flags, VkExtent2D extent = {0, 0});
~VulkanSwapChain();
@@ -46,12 +46,12 @@ struct VulkanSwapChain : public HwSwapChain {
void acquire(bool& reized);
inline std::shared_ptr<VulkanTexture> getCurrentColor() const noexcept {
return mColors[mCurrentSwapIndex];
inline VulkanTexture* getCurrentColor() const noexcept {
return mColors[mCurrentSwapIndex].get();
}
inline std::shared_ptr<VulkanTexture> getDepth() const noexcept {
return mDepth;
inline VulkanTexture* getDepth() const noexcept {
return mDepth.get();
}
inline bool isFirstRenderPass() const noexcept {
@@ -70,16 +70,15 @@ private:
void update();
VulkanPlatform* mPlatform;
std::shared_ptr<VulkanCommands> mCommands;
VulkanCommands* mCommands;
VmaAllocator mAllocator;
VulkanStagePool& mStagePool;
bool const mHeadless;
// We create VulkanTextures based on VkImages. VulkanTexture has facilities for doing layout
// transitions, which are useful here. We use std::shared_ptr because they will be shared with
// VulkanRenderTarget.
utils::FixedCapacityVector<std::shared_ptr<VulkanTexture>> mColors;
std::shared_ptr<VulkanTexture> mDepth;
// transitions, which are useful here.
utils::FixedCapacityVector<std::unique_ptr<VulkanTexture>> mColors;
std::unique_ptr<VulkanTexture> mDepth;
VkExtent2D mExtent;
VkSemaphore mImageReady;
uint32_t mCurrentSwapIndex;
@@ -30,7 +30,7 @@ namespace filament::backend {
using ImgUtil = VulkanImageUtility;
VulkanTexture::VulkanTexture(VkDevice device, VmaAllocator allocator,
std::shared_ptr<VulkanCommands> commands, VkImage image, VkFormat format, uint8_t samples,
VulkanCommands* commands, VkImage image, VkFormat format, uint8_t samples,
uint32_t width, uint32_t height, TextureUsage tusage, VulkanStagePool& stagePool)
: HwTexture(SamplerType::SAMPLER_2D, 1, samples, width, height, 1, TextureFormat::UNUSED,
tusage),
@@ -47,7 +47,7 @@ VulkanTexture::VulkanTexture(VkDevice device, VmaAllocator allocator,
VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
VulkanContext const& context, VmaAllocator allocator,
std::shared_ptr<VulkanCommands> commands, SamplerType target, uint8_t levels,
VulkanCommands* commands, SamplerType target, uint8_t levels,
TextureFormat tformat, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
TextureUsage tusage, VulkanStagePool& stagePool, VkComponentMapping swizzle)
: HwTexture(target, levels, samples, w, h, depth, tformat, tusage),
+13 -14
View File
@@ -28,17 +28,15 @@ namespace filament::backend {
struct VulkanTexture : public HwTexture {
// Standard constructor for user-facing textures.
VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, VulkanContext const& context,
VmaAllocator allocator, std::shared_ptr<VulkanCommands> commands, SamplerType target,
uint8_t levels, TextureFormat tformat, uint8_t samples, uint32_t w, uint32_t h,
uint32_t depth, TextureUsage tusage, VulkanStagePool& stagePool,
VkComponentMapping swizzle={});
VmaAllocator allocator, VulkanCommands* commands, SamplerType target, uint8_t levels,
TextureFormat tformat, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
TextureUsage tusage, VulkanStagePool& stagePool, VkComponentMapping swizzle = {});
// Specialized constructor for internally created textures (e.g. from a swap chain)
// The texture will never destroy the given VkImage, but it does manages its subresources.
VulkanTexture(VkDevice device,
VmaAllocator allocator, std::shared_ptr<VulkanCommands> commands, VkImage image,
VkFormat format, uint8_t samples, uint32_t width, uint32_t height, TextureUsage tusage,
VulkanStagePool& stagePool);
VulkanTexture(VkDevice device, VmaAllocator allocator, VulkanCommands* commands, VkImage image,
VkFormat format, uint8_t samples, uint32_t width, uint32_t height, TextureUsage tusage,
VulkanStagePool& stagePool);
~VulkanTexture();
@@ -68,12 +66,12 @@ struct VulkanTexture : public HwTexture {
VulkanLayout getLayout(uint32_t layer, uint32_t level) const;
void setSidecar(std::shared_ptr<VulkanTexture> sidecar) {
mSidecarMSAA = sidecar;
void setSidecar(VulkanTexture* sidecar) {
mSidecarMSAA.reset(sidecar);
}
std::shared_ptr<VulkanTexture> getSidecar() const {
return mSidecarMSAA;
VulkanTexture* getSidecar() const {
return mSidecarMSAA.get();
}
void transitionLayout(VkCommandBuffer commands, const VkImageSubresourceRange& range,
@@ -96,7 +94,8 @@ private:
void updateImageWithBlit(const PixelBufferDescriptor& hostData, uint32_t width, uint32_t height,
uint32_t depth, uint32_t miplevel);
std::shared_ptr<VulkanTexture> mSidecarMSAA;
// The texture with the sidecar owns the sidecar.
std::unique_ptr<VulkanTexture> mSidecarMSAA;
const VkFormat mVkFormat;
const VkImageViewType mViewType;
const VkComponentMapping mSwizzle;
@@ -114,7 +113,7 @@ private:
VulkanStagePool& mStagePool;
VkDevice mDevice;
VmaAllocator mAllocator;
std::shared_ptr<VulkanCommands> mCommands;
VulkanCommands* mCommands;
};
} // namespace filament::backend
@@ -198,7 +198,7 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
return exts;
}
VkInstance createInstance(const ExtensionSet& requiredExts) {
VkInstance createInstance(ExtensionSet const& requiredExts) {
VkInstance instance;
VkInstanceCreateInfo instanceCreateInfo = {};
bool validationFeaturesSupported = false;
@@ -363,6 +363,13 @@ std::tuple<ExtensionSet, ExtensionSet> pruneExtensions(VkPhysicalDevice device,
&& newDeviceExts.find(VK_EXT_DEBUG_MARKER_EXTENSION_NAME) != newDeviceExts.end()) {
newDeviceExts.erase(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
}
// debugMarker must also request debugReport the instance extension. So check if that's present.
if (newDeviceExts.find(VK_EXT_DEBUG_MARKER_EXTENSION_NAME) != newDeviceExts.end()
&& newInstExts.find(VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == newInstExts.end()) {
newDeviceExts.erase(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
}
return std::tuple(newInstExts, newDeviceExts);
}