VulkanHostDisplay: Upload textures in init command buffer

This commit is contained in:
Connor McLaughlin 2022-06-05 00:20:26 +10:00 committed by refractionpcsx2
parent b74c65cc7c
commit f8fa41d4bf
1 changed files with 74 additions and 49 deletions

View File

@ -54,13 +54,25 @@ VulkanHostDisplay::~VulkanHostDisplay()
pxAssertRel(!m_swap_chain, "Swap chain should have been destroyed by now");
}
HostDisplay::RenderAPI VulkanHostDisplay::GetRenderAPI() const { return HostDisplay::RenderAPI::Vulkan; }
HostDisplay::RenderAPI VulkanHostDisplay::GetRenderAPI() const
{
return HostDisplay::RenderAPI::Vulkan;
}
void* VulkanHostDisplay::GetRenderDevice() const { return nullptr; }
void* VulkanHostDisplay::GetRenderDevice() const
{
return nullptr;
}
void* VulkanHostDisplay::GetRenderContext() const { return nullptr; }
void* VulkanHostDisplay::GetRenderContext() const
{
return nullptr;
}
void* VulkanHostDisplay::GetRenderSurface() const { return m_swap_chain.get(); }
void* VulkanHostDisplay::GetRenderSurface() const
{
return m_swap_chain.get();
}
bool VulkanHostDisplay::ChangeRenderWindow(const WindowInfo& new_wi)
{
@ -87,8 +99,8 @@ bool VulkanHostDisplay::ChangeRenderWindow(const WindowInfo& new_wi)
}
WindowInfo wi_copy(new_wi);
VkSurfaceKHR surface = Vulkan::SwapChain::CreateVulkanSurface(
g_vulkan_context->GetVulkanInstance(), g_vulkan_context->GetPhysicalDevice(), &wi_copy);
VkSurfaceKHR surface =
Vulkan::SwapChain::CreateVulkanSurface(g_vulkan_context->GetVulkanInstance(), g_vulkan_context->GetPhysicalDevice(), &wi_copy);
if (surface == VK_NULL_HANDLE)
{
Console.Error("Failed to create new surface for swap chain");
@ -121,11 +133,20 @@ void VulkanHostDisplay::ResizeRenderWindow(s32 new_window_width, s32 new_window_
m_window_info = m_swap_chain->GetWindowInfo();
}
bool VulkanHostDisplay::SupportsFullscreen() const { return false; }
bool VulkanHostDisplay::SupportsFullscreen() const
{
return false;
}
bool VulkanHostDisplay::IsFullscreen() { return false; }
bool VulkanHostDisplay::IsFullscreen()
{
return false;
}
bool VulkanHostDisplay::SetFullscreen(bool fullscreen, u32 width, u32 height, float refresh_rate) { return false; }
bool VulkanHostDisplay::SetFullscreen(bool fullscreen, u32 width, u32 height, float refresh_rate)
{
return false;
}
HostDisplay::AdapterAndModeList VulkanHostDisplay::GetAdapterAndModeList()
{
@ -147,27 +168,24 @@ std::string VulkanHostDisplay::GetDriverInfo() const
if (g_vulkan_context->GetOptionalExtensions().vk_khr_driver_properties)
{
const VkPhysicalDeviceDriverProperties& props = g_vulkan_context->GetDeviceDriverProperties();
ret = StringUtil::StdStringFromFormat(
"Driver %u.%u.%u\nVulkan %u.%u.%u\nConformance Version %u.%u.%u.%u\n%s\n%s\n%s",
ret = StringUtil::StdStringFromFormat("Driver %u.%u.%u\nVulkan %u.%u.%u\nConformance Version %u.%u.%u.%u\n%s\n%s\n%s",
VK_VERSION_MAJOR(driver_version), VK_VERSION_MINOR(driver_version), VK_VERSION_PATCH(driver_version),
VK_API_VERSION_MAJOR(api_version), VK_API_VERSION_MINOR(api_version), VK_API_VERSION_PATCH(api_version),
props.conformanceVersion.major, props.conformanceVersion.minor, props.conformanceVersion.subminor, props.conformanceVersion.patch,
props.driverInfo, props.driverName,
g_vulkan_context->GetDeviceProperties().deviceName);
props.conformanceVersion.major, props.conformanceVersion.minor, props.conformanceVersion.subminor,
props.conformanceVersion.patch, props.driverInfo, props.driverName, g_vulkan_context->GetDeviceProperties().deviceName);
}
else
{
ret = StringUtil::StdStringFromFormat(
"Driver %u.%u.%u\nVulkan %u.%u.%u\n%s",
VK_VERSION_MAJOR(driver_version), VK_VERSION_MINOR(driver_version), VK_VERSION_PATCH(driver_version),
VK_API_VERSION_MAJOR(api_version), VK_API_VERSION_MINOR(api_version), VK_API_VERSION_PATCH(api_version),
g_vulkan_context->GetDeviceProperties().deviceName);
ret = StringUtil::StdStringFromFormat("Driver %u.%u.%u\nVulkan %u.%u.%u\n%s", VK_VERSION_MAJOR(driver_version),
VK_VERSION_MINOR(driver_version), VK_VERSION_PATCH(driver_version), VK_API_VERSION_MAJOR(api_version),
VK_API_VERSION_MINOR(api_version), VK_API_VERSION_PATCH(api_version), g_vulkan_context->GetDeviceProperties().deviceName);
}
return ret;
}
static bool UploadBufferToTexture(Vulkan::Texture* texture, u32 width, u32 height, const void* data, u32 data_stride)
static bool UploadBufferToTexture(
Vulkan::Texture* texture, VkCommandBuffer cmdbuf, u32 width, u32 height, const void* data, u32 data_stride)
{
const u32 tight_stride = Vulkan::Util::GetTexelSize(texture->GetFormat()) * width;
const u32 tight_size = tight_stride * height;
@ -182,18 +200,19 @@ static bool UploadBufferToTexture(Vulkan::Texture* texture, u32 width, u32 heigh
Console.WriteLn("Failed to allocate %u bytes in stream buffer for UploadBufferToTexture()", tight_size);
return false;
}
cmdbuf = g_vulkan_context->GetCurrentInitCommandBuffer();
}
const u32 buf_offset = buf.GetCurrentOffset();
StringUtil::StrideMemCpy(buf.GetCurrentHostPointer(), tight_stride, data, data_stride, tight_stride, height);
buf.CommitMemory(tight_size);
texture->UpdateFromBuffer(
g_vulkan_context->GetCurrentCommandBuffer(), 0, 0, 0, 0, width, height, width, buf.GetBuffer(), buf_offset);
texture->UpdateFromBuffer(cmdbuf, 0, 0, 0, 0, width, height, width, buf.GetBuffer(), buf_offset);
return true;
}
std::unique_ptr<HostDisplayTexture> VulkanHostDisplay::CreateTexture(u32 width, u32 height, const void* data, u32 data_stride, bool dynamic /* = false */)
std::unique_ptr<HostDisplayTexture> VulkanHostDisplay::CreateTexture(
u32 width, u32 height, const void* data, u32 data_stride, bool dynamic /* = false */)
{
static constexpr VkFormat vk_format = VK_FORMAT_R8G8B8A8_UNORM;
static constexpr VkImageUsageFlags usage =
@ -203,11 +222,11 @@ std::unique_ptr<HostDisplayTexture> VulkanHostDisplay::CreateTexture(u32 width,
if (!texture.Create(width, height, 1, 1, vk_format, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage))
return {};
texture.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
texture.TransitionToLayout(g_vulkan_context->GetCurrentInitCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
if (data)
{
if (!UploadBufferToTexture(&texture, width, height, data, data_stride))
if (!UploadBufferToTexture(&texture, g_vulkan_context->GetCurrentInitCommandBuffer(), width, height, data, data_stride))
return {};
}
else
@ -215,20 +234,18 @@ std::unique_ptr<HostDisplayTexture> VulkanHostDisplay::CreateTexture(u32 width,
// clear it instead so we don't read uninitialized data (and keep the validation layer happy!)
static constexpr VkClearColorValue ccv = {};
static constexpr VkImageSubresourceRange isr = {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u};
vkCmdClearColorImage(
g_vulkan_context->GetCurrentCommandBuffer(), texture.GetImage(), texture.GetLayout(), &ccv, 1u, &isr);
vkCmdClearColorImage(g_vulkan_context->GetCurrentInitCommandBuffer(), texture.GetImage(), texture.GetLayout(), &ccv, 1u, &isr);
}
texture.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
texture.TransitionToLayout(g_vulkan_context->GetCurrentInitCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
return std::make_unique<VulkanHostDisplayTexture>(std::move(texture));
}
void VulkanHostDisplay::UpdateTexture(
HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data, u32 data_stride)
void VulkanHostDisplay::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data, u32 data_stride)
{
UploadBufferToTexture(
&static_cast<VulkanHostDisplayTexture*>(texture)->GetTexture(), width, height, data, data_stride);
UploadBufferToTexture(&static_cast<VulkanHostDisplayTexture*>(texture)->GetTexture(), g_vulkan_context->GetCurrentCommandBuffer(),
width, height, data, data_stride);
}
void VulkanHostDisplay::SetVSync(VsyncMode mode)
@ -248,9 +265,8 @@ bool VulkanHostDisplay::CreateRenderDevice(
// debug_device = true;
WindowInfo local_wi(wi);
if (!Vulkan::Context::Create(
adapter_name, &local_wi, &m_swap_chain, GetPreferredPresentModeForVsyncMode(vsync),
threaded_presentation, debug_device, debug_device))
if (!Vulkan::Context::Create(adapter_name, &local_wi, &m_swap_chain, GetPreferredPresentModeForVsyncMode(vsync), threaded_presentation,
debug_device, debug_device))
{
Console.Error("Failed to create Vulkan context");
m_window_info = {};
@ -269,9 +285,15 @@ bool VulkanHostDisplay::InitializeRenderDevice(std::string_view shader_cache_dir
return true;
}
bool VulkanHostDisplay::HasRenderDevice() const { return static_cast<bool>(g_vulkan_context); }
bool VulkanHostDisplay::HasRenderDevice() const
{
return static_cast<bool>(g_vulkan_context);
}
bool VulkanHostDisplay::HasRenderSurface() const { return static_cast<bool>(m_swap_chain); }
bool VulkanHostDisplay::HasRenderSurface() const
{
return static_cast<bool>(m_swap_chain);
}
bool VulkanHostDisplay::CreateImGuiContext()
{
@ -301,9 +323,15 @@ void VulkanHostDisplay::DestroyRenderDevice()
Vulkan::Context::Destroy();
}
bool VulkanHostDisplay::MakeRenderContextCurrent() { return true; }
bool VulkanHostDisplay::MakeRenderContextCurrent()
{
return true;
}
bool VulkanHostDisplay::DoneRenderContextCurrent() { return true; }
bool VulkanHostDisplay::DoneRenderContextCurrent()
{
return true;
}
bool VulkanHostDisplay::BeginPresent(bool frame_skip)
{
@ -356,15 +384,13 @@ bool VulkanHostDisplay::BeginPresent(bool frame_skip)
swap_chain_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
const VkClearValue clear_value = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
const VkRenderPassBeginInfo rp = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr,
m_swap_chain->GetClearRenderPass(), m_swap_chain->GetCurrentFramebuffer(),
{{0, 0}, {swap_chain_texture.GetWidth(), swap_chain_texture.GetHeight()}}, 1u, &clear_value};
const VkRenderPassBeginInfo rp = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, m_swap_chain->GetClearRenderPass(),
m_swap_chain->GetCurrentFramebuffer(), {{0, 0}, {swap_chain_texture.GetWidth(), swap_chain_texture.GetHeight()}}, 1u, &clear_value};
vkCmdBeginRenderPass(g_vulkan_context->GetCurrentCommandBuffer(), &rp, VK_SUBPASS_CONTENTS_INLINE);
const VkViewport vp{0.0f, 0.0f, static_cast<float>(swap_chain_texture.GetWidth()),
static_cast<float>(swap_chain_texture.GetHeight()), 0.0f, 1.0f};
const VkRect2D scissor{
{0, 0}, {static_cast<u32>(swap_chain_texture.GetWidth()), static_cast<u32>(swap_chain_texture.GetHeight())}};
const VkViewport vp{
0.0f, 0.0f, static_cast<float>(swap_chain_texture.GetWidth()), static_cast<float>(swap_chain_texture.GetHeight()), 0.0f, 1.0f};
const VkRect2D scissor{{0, 0}, {static_cast<u32>(swap_chain_texture.GetWidth()), static_cast<u32>(swap_chain_texture.GetHeight())}};
vkCmdSetViewport(g_vulkan_context->GetCurrentCommandBuffer(), 0, 1, &vp);
vkCmdSetScissor(g_vulkan_context->GetCurrentCommandBuffer(), 0, 1, &scissor);
return true;
@ -379,9 +405,8 @@ void VulkanHostDisplay::EndPresent()
vkCmdEndRenderPass(g_vulkan_context->GetCurrentCommandBuffer());
m_swap_chain->GetCurrentTexture().TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
g_vulkan_context->SubmitCommandBuffer(m_swap_chain->GetImageAvailableSemaphore(),
m_swap_chain->GetRenderingFinishedSemaphore(), m_swap_chain->GetSwapChain(),
m_swap_chain->GetCurrentImageIndex(), !m_swap_chain->IsPresentModeSynchronizing());
g_vulkan_context->SubmitCommandBuffer(m_swap_chain->GetImageAvailableSemaphore(), m_swap_chain->GetRenderingFinishedSemaphore(),
m_swap_chain->GetSwapChain(), m_swap_chain->GetCurrentImageIndex(), !m_swap_chain->IsPresentModeSynchronizing());
g_vulkan_context->MoveToNextCommandBuffer();
}