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:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user