mirror of
https://github.com/libretro/parallel-gx1.git
synced 2026-11-07 04:26:01 -10:00
Vulkan: the 2D view the frontend reads made with the texture
A render target of one layer in a 2D array, which is what an XFB copy is, gets a second view at creation, 2D, of that layer, and keeps it for its life. Handing an XFB copy to the frontend in place uses it, so presenting creates and destroys nothing: before, every new picture made a view and queued the last one for destruction.
This commit is contained in:
1 parent
065c9c3bea
commit
64d3730c99
4 files changed
+26
-28
No files matched your search
@@ -12,7 +12,6 @@
|
||||
#ifdef HAS_VULKAN
|
||||
#include "VideoBackends/Vulkan/CommandBufferManager.h"
|
||||
#include "VideoBackends/Vulkan/StateTracker.h"
|
||||
#include "VideoBackends/Vulkan/VulkanContext.h"
|
||||
#endif
|
||||
|
||||
namespace Libretro
|
||||
@@ -232,15 +231,6 @@ VKOutput::~VKOutput()
|
||||
|
||||
void VKOutput::DropDirect()
|
||||
{
|
||||
/* the frontend's frames that read it were submitted before anything
|
||||
* the core submits next, so it goes once that completes */
|
||||
if (m_direct_image.image_view != VK_NULL_HANDLE)
|
||||
{
|
||||
if (Vulkan::g_command_buffer_mgr)
|
||||
Vulkan::g_command_buffer_mgr->DeferImageViewDestruction(m_direct_image.image_view);
|
||||
else
|
||||
vkDestroyImageView(Vulkan::g_vulkan_context->GetDevice(), m_direct_image.image_view, nullptr);
|
||||
}
|
||||
memset(&m_direct_image, 0, sizeof(m_direct_image));
|
||||
m_direct = nullptr;
|
||||
}
|
||||
@@ -333,9 +323,14 @@ bool VKOutput::PresentTexture(const AbstractTexture* texture, u32 width, u32 hei
|
||||
Vulkan::VKTexture* vk_texture =
|
||||
const_cast<Vulkan::VKTexture*>(static_cast<const Vulkan::VKTexture*>(texture));
|
||||
retro_vulkan_image image;
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
|
||||
/* the texture's own 2D view of its one layer: the frontend's shaders
|
||||
* read a 2D image */
|
||||
if (vk_texture->GetView2D() == VK_NULL_HANDLE)
|
||||
return false;
|
||||
|
||||
memset(&image, 0, sizeof(image));
|
||||
image.image_view = vk_texture->GetView2D();
|
||||
image.image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
image.create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
image.create_info.image = vk_texture->GetImage();
|
||||
@@ -350,15 +345,6 @@ bool VKOutput::PresentTexture(const AbstractTexture* texture, u32 width, u32 hei
|
||||
image.create_info.subresourceRange.levelCount = 1;
|
||||
image.create_info.subresourceRange.baseArrayLayer = 0;
|
||||
image.create_info.subresourceRange.layerCount = 1;
|
||||
/* a view per picture: an image's handle can come back for another one
|
||||
* once it is destroyed, so none is kept for the next */
|
||||
if (vkCreateImageView(Vulkan::g_vulkan_context->GetDevice(), &image.create_info, nullptr,
|
||||
&view) != VK_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
image.image_view = view;
|
||||
|
||||
vk_texture->TransitionToLayout(Vulkan::g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
Vulkan::g_command_buffer_mgr->SubmitCommandBuffer(false, false, true);
|
||||
|
||||
@@ -98,9 +98,9 @@ private:
|
||||
retro_vulkan_image m_images[OUTPUT_MAX_SLOTS];
|
||||
std::unique_ptr<Vulkan::VKTexture> m_textures[OUTPUT_MAX_SLOTS];
|
||||
std::unique_ptr<Vulkan::VKFramebuffer> m_framebuffers[OUTPUT_MAX_SLOTS];
|
||||
/* A texture handed on where it is, with a 2D view of its one layer of
|
||||
* its own, made for it: the frontend reads it until another picture is
|
||||
* handed on, so it is kept in shader-read layout meanwhile. */
|
||||
/* A texture handed on where it is, through its 2D view: the frontend
|
||||
* reads it until another picture is handed on, so it is kept in
|
||||
* shader-read layout meanwhile. */
|
||||
retro_vulkan_image m_direct_image;
|
||||
Vulkan::VKTexture* m_direct;
|
||||
retro_hw_render_interface_vulkan* m_iface;
|
||||
|
||||
@@ -47,6 +47,8 @@ VKTexture::~VKTexture()
|
||||
{
|
||||
StateTracker::GetInstance()->UnbindTexture(m_view);
|
||||
g_command_buffer_mgr->DeferImageViewDestruction(m_view);
|
||||
if (m_view_2d != VK_NULL_HANDLE)
|
||||
g_command_buffer_mgr->DeferImageViewDestruction(m_view_2d);
|
||||
|
||||
// If we don't have device memory allocated, the image is not owned by us (e.g. swapchain)
|
||||
if (m_alloc != VK_NULL_HANDLE)
|
||||
@@ -127,8 +129,14 @@ std::unique_ptr<VKTexture> VKTexture::Create(const TextureConfig& tex_config, st
|
||||
PanicAlertFmt("Unhandled texture type.");
|
||||
return nullptr;
|
||||
}
|
||||
if (!texture->CreateView(image_view_type))
|
||||
if (!texture->CreateView(image_view_type, &texture->m_view))
|
||||
return nullptr;
|
||||
if (tex_config.type == AbstractTextureType::Texture_2DArray && tex_config.layers == 1 &&
|
||||
tex_config.IsRenderTarget() &&
|
||||
!texture->CreateView(VK_IMAGE_VIEW_TYPE_2D, &texture->m_view_2d))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
@@ -138,13 +146,13 @@ std::unique_ptr<VKTexture> VKTexture::CreateAdopted(const TextureConfig& tex_con
|
||||
{
|
||||
std::unique_ptr<VKTexture> texture = std::make_unique<VKTexture>(
|
||||
tex_config, VmaAllocation(VK_NULL_HANDLE), image, "", layout, ComputeImageLayout::Undefined);
|
||||
if (!texture->CreateView(view_type))
|
||||
if (!texture->CreateView(view_type, &texture->m_view))
|
||||
return nullptr;
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
bool VKTexture::CreateView(VkImageViewType type)
|
||||
bool VKTexture::CreateView(VkImageViewType type, VkImageView* view)
|
||||
{
|
||||
VkImageViewCreateInfo view_info = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
@@ -157,7 +165,7 @@ bool VKTexture::CreateView(VkImageViewType type)
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY},
|
||||
{GetImageViewAspectForFormat(GetFormat()), 0, GetLevels(), 0, GetLayers()}};
|
||||
|
||||
VkResult res = vkCreateImageView(g_vulkan_context->GetDevice(), &view_info, nullptr, &m_view);
|
||||
VkResult res = vkCreateImageView(g_vulkan_context->GetDevice(), &view_info, nullptr, view);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkCreateImageView failed: ");
|
||||
|
||||
@@ -52,6 +52,9 @@ public:
|
||||
|
||||
VkImage GetImage() const { return m_image; }
|
||||
VkImageView GetView() const { return m_view; }
|
||||
/* A 2D view of a render target's one layer, for whoever reads it as a
|
||||
* plain 2D image: the frontend, when it is handed on; null otherwise. */
|
||||
VkImageView GetView2D() const { return m_view_2d; }
|
||||
VkImageLayout GetLayout() const { return m_layout; }
|
||||
VkFormat GetVkFormat() const { return GetVkFormatForHostTextureFormat(m_config.format); }
|
||||
bool IsAdopted() const { return m_alloc != VmaAllocation(VK_NULL_HANDLE); }
|
||||
@@ -72,11 +75,12 @@ public:
|
||||
void PrepareForRenderPass(VkCommandBuffer command_buffer) const;
|
||||
|
||||
private:
|
||||
bool CreateView(VkImageViewType type);
|
||||
bool CreateView(VkImageViewType type, VkImageView* view);
|
||||
|
||||
VmaAllocation m_alloc;
|
||||
VkImage m_image;
|
||||
VkImageView m_view = VK_NULL_HANDLE;
|
||||
VkImageView m_view_2d = VK_NULL_HANDLE;
|
||||
mutable VkImageLayout m_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
mutable ComputeImageLayout m_compute_layout = ComputeImageLayout::Undefined;
|
||||
mutable bool m_written_since_last_layout_change = false;
|
||||
|
||||
Reference in new issue
Block a user