[Vulkan] Delayed ImmediateTexture destruction
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/ui/immediate_drawer.h"
|
||||
@@ -54,24 +54,28 @@ class VulkanImmediateDrawer : public ImmediateDrawer {
|
||||
|
||||
class VulkanImmediateTexture : public ImmediateTexture {
|
||||
public:
|
||||
VulkanImmediateTexture(uint32_t width, uint32_t height,
|
||||
VulkanImmediateDrawer* immediate_drawer,
|
||||
uintptr_t immediate_drawer_handle)
|
||||
: ImmediateTexture(width, height), immediate_drawer_(immediate_drawer) {
|
||||
handle = immediate_drawer_handle;
|
||||
}
|
||||
~VulkanImmediateTexture() {
|
||||
if (immediate_drawer_) {
|
||||
immediate_drawer_->HandleImmediateTextureDestroyed(handle);
|
||||
}
|
||||
}
|
||||
void DetachFromImmediateDrawer() {
|
||||
immediate_drawer_ = nullptr;
|
||||
handle = 0;
|
||||
}
|
||||
struct Resource {
|
||||
VkImage image;
|
||||
VkDeviceMemory memory;
|
||||
VkImageView image_view;
|
||||
uint32_t descriptor_index;
|
||||
};
|
||||
|
||||
private:
|
||||
VulkanImmediateTexture(uint32_t width, uint32_t height)
|
||||
: ImmediateTexture(width, height), immediate_drawer_(nullptr) {
|
||||
handle = reinterpret_cast<uintptr_t>(this);
|
||||
}
|
||||
~VulkanImmediateTexture() override;
|
||||
|
||||
// If null, this is either a blank texture, or the immediate drawer has been
|
||||
// destroyed.
|
||||
VulkanImmediateDrawer* immediate_drawer_;
|
||||
size_t immediate_drawer_index_;
|
||||
// Invalid if immediate_drawer_ is null, since it's managed by the immediate
|
||||
// drawer.
|
||||
Resource resource_;
|
||||
size_t pending_upload_index_;
|
||||
uint64_t last_usage_submission_ = 0;
|
||||
};
|
||||
|
||||
struct TextureDescriptorPool {
|
||||
@@ -86,19 +90,6 @@ class VulkanImmediateDrawer : public ImmediateDrawer {
|
||||
TextureDescriptorPool* recycled_next;
|
||||
};
|
||||
|
||||
// Tracked separately from VulkanImmediateTexture because copying may take
|
||||
// additional references.
|
||||
struct Texture {
|
||||
// Null for the white texture, reference held by the drawer itself instead
|
||||
// of immediate textures.
|
||||
VulkanImmediateTexture* immediate_texture;
|
||||
VkImage image;
|
||||
VkDeviceMemory memory;
|
||||
VkImageView image_view;
|
||||
uint32_t descriptor_index;
|
||||
uint32_t reference_count;
|
||||
};
|
||||
|
||||
bool EnsurePipelinesCreated();
|
||||
|
||||
// Allocates a combined image sampler in a pool and returns its index, or
|
||||
@@ -107,31 +98,15 @@ class VulkanImmediateDrawer : public ImmediateDrawer {
|
||||
VkDescriptorSet GetTextureDescriptor(uint32_t descriptor_index) const;
|
||||
void FreeTextureDescriptor(uint32_t descriptor_index);
|
||||
|
||||
// Returns SIZE_MAX in case of failure. The created texture will have a
|
||||
// reference count of 1 plus references needed for uploading, but will not be
|
||||
// attached to a VulkanImmediateTexture (will return the reference to the
|
||||
// caller, in short). If data is null, a (1, 1, 1, 1) image will be created,
|
||||
// which can be used as a replacement when drawing without a real texture.
|
||||
size_t CreateVulkanTexture(uint32_t width, uint32_t height,
|
||||
// If data is null, a (1, 1, 1, 1) image will be created, which can be used as
|
||||
// a replacement when drawing without a real texture.
|
||||
bool CreateTextureResource(uint32_t width, uint32_t height,
|
||||
ImmediateTextureFilter filter, bool is_repeated,
|
||||
const uint8_t* data);
|
||||
void ReleaseTexture(size_t index);
|
||||
uintptr_t GetTextureHandleForIndex(size_t index) const {
|
||||
return index != white_texture_index_ ? uintptr_t(index + 1) : 0;
|
||||
}
|
||||
size_t GetTextureIndexForHandle(uintptr_t handle) const {
|
||||
// 0 is a special value for no texture.
|
||||
return handle ? size_t(handle - 1) : white_texture_index_;
|
||||
}
|
||||
// For calling from VulkanImmediateTexture.
|
||||
void HandleImmediateTextureDestroyed(uintptr_t handle) {
|
||||
size_t index = GetTextureIndexForHandle(handle);
|
||||
if (index == white_texture_index_) {
|
||||
return;
|
||||
}
|
||||
textures_[index].immediate_texture = nullptr;
|
||||
ReleaseTexture(index);
|
||||
}
|
||||
const uint8_t* data,
|
||||
VulkanImmediateTexture::Resource& resource_out,
|
||||
size_t& pending_upload_index_out);
|
||||
void DestroyTextureResource(VulkanImmediateTexture::Resource& resource);
|
||||
void OnImmediateTextureDestroyed(VulkanImmediateTexture& texture);
|
||||
|
||||
VulkanContext& context_;
|
||||
|
||||
@@ -141,26 +116,28 @@ class VulkanImmediateDrawer : public ImmediateDrawer {
|
||||
TextureDescriptorPool* texture_descriptor_pool_unallocated_first_ = nullptr;
|
||||
TextureDescriptorPool* texture_descriptor_pool_recycled_first_ = nullptr;
|
||||
|
||||
std::vector<Texture> textures_;
|
||||
std::vector<size_t> textures_free_;
|
||||
VulkanImmediateTexture::Resource white_texture_ = {};
|
||||
std::vector<VulkanImmediateTexture*> textures_;
|
||||
struct PendingTextureUpload {
|
||||
size_t texture_index;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
// Null for internal resources such as the white texture.
|
||||
VulkanImmediateTexture* texture;
|
||||
// VK_NULL_HANDLE if need to clear rather than to copy.
|
||||
VkBuffer buffer;
|
||||
VkDeviceMemory buffer_memory;
|
||||
VkImage image;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
std::vector<PendingTextureUpload> texture_uploads_pending_;
|
||||
struct SubmittedTextureUpload {
|
||||
size_t texture_index;
|
||||
// VK_NULL_HANDLE if cleared rather than copied.
|
||||
struct SubmittedTextureUploadBuffer {
|
||||
VkBuffer buffer;
|
||||
VkDeviceMemory buffer_memory;
|
||||
uint64_t submission_index;
|
||||
};
|
||||
std::deque<SubmittedTextureUpload> texture_uploads_submitted_;
|
||||
size_t white_texture_index_;
|
||||
std::deque<SubmittedTextureUploadBuffer> texture_upload_buffers_submitted_;
|
||||
// Resource and last usage submission pairs.
|
||||
std::vector<std::pair<VulkanImmediateTexture::Resource, uint64_t>>
|
||||
textures_deleted_;
|
||||
|
||||
VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user