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"); 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) bool VulkanHostDisplay::ChangeRenderWindow(const WindowInfo& new_wi)
{ {
@ -87,8 +99,8 @@ bool VulkanHostDisplay::ChangeRenderWindow(const WindowInfo& new_wi)
} }
WindowInfo wi_copy(new_wi); WindowInfo wi_copy(new_wi);
VkSurfaceKHR surface = Vulkan::SwapChain::CreateVulkanSurface( VkSurfaceKHR surface =
g_vulkan_context->GetVulkanInstance(), g_vulkan_context->GetPhysicalDevice(), &wi_copy); Vulkan::SwapChain::CreateVulkanSurface(g_vulkan_context->GetVulkanInstance(), g_vulkan_context->GetPhysicalDevice(), &wi_copy);
if (surface == VK_NULL_HANDLE) if (surface == VK_NULL_HANDLE)
{ {
Console.Error("Failed to create new surface for swap chain"); 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(); 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() HostDisplay::AdapterAndModeList VulkanHostDisplay::GetAdapterAndModeList()
{ {
@ -147,27 +168,24 @@ std::string VulkanHostDisplay::GetDriverInfo() const
if (g_vulkan_context->GetOptionalExtensions().vk_khr_driver_properties) if (g_vulkan_context->GetOptionalExtensions().vk_khr_driver_properties)
{ {
const VkPhysicalDeviceDriverProperties& props = g_vulkan_context->GetDeviceDriverProperties(); const VkPhysicalDeviceDriverProperties& props = g_vulkan_context->GetDeviceDriverProperties();
ret = StringUtil::StdStringFromFormat( ret = StringUtil::StdStringFromFormat("Driver %u.%u.%u\nVulkan %u.%u.%u\nConformance Version %u.%u.%u.%u\n%s\n%s\n%s",
"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_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), 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.conformanceVersion.major, props.conformanceVersion.minor, props.conformanceVersion.subminor,
props.driverInfo, props.driverName, props.conformanceVersion.patch, props.driverInfo, props.driverName, g_vulkan_context->GetDeviceProperties().deviceName);
g_vulkan_context->GetDeviceProperties().deviceName);
} }
else else
{ {
ret = StringUtil::StdStringFromFormat( ret = StringUtil::StdStringFromFormat("Driver %u.%u.%u\nVulkan %u.%u.%u\n%s", VK_VERSION_MAJOR(driver_version),
"Driver %u.%u.%u\nVulkan %u.%u.%u\n%s", VK_VERSION_MINOR(driver_version), VK_VERSION_PATCH(driver_version), VK_API_VERSION_MAJOR(api_version),
VK_VERSION_MAJOR(driver_version), VK_VERSION_MINOR(driver_version), VK_VERSION_PATCH(driver_version), VK_API_VERSION_MINOR(api_version), VK_API_VERSION_PATCH(api_version), g_vulkan_context->GetDeviceProperties().deviceName);
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; 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_stride = Vulkan::Util::GetTexelSize(texture->GetFormat()) * width;
const u32 tight_size = tight_stride * height; 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); Console.WriteLn("Failed to allocate %u bytes in stream buffer for UploadBufferToTexture()", tight_size);
return false; return false;
} }
cmdbuf = g_vulkan_context->GetCurrentInitCommandBuffer();
} }
const u32 buf_offset = buf.GetCurrentOffset(); const u32 buf_offset = buf.GetCurrentOffset();
StringUtil::StrideMemCpy(buf.GetCurrentHostPointer(), tight_stride, data, data_stride, tight_stride, height); StringUtil::StrideMemCpy(buf.GetCurrentHostPointer(), tight_stride, data, data_stride, tight_stride, height);
buf.CommitMemory(tight_size); buf.CommitMemory(tight_size);
texture->UpdateFromBuffer( texture->UpdateFromBuffer(cmdbuf, 0, 0, 0, 0, width, height, width, buf.GetBuffer(), buf_offset);
g_vulkan_context->GetCurrentCommandBuffer(), 0, 0, 0, 0, width, height, width, buf.GetBuffer(), buf_offset);
return true; 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 VkFormat vk_format = VK_FORMAT_R8G8B8A8_UNORM;
static constexpr VkImageUsageFlags usage = 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)) 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 {}; 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 (data)
{ {
if (!UploadBufferToTexture(&texture, width, height, data, data_stride)) if (!UploadBufferToTexture(&texture, g_vulkan_context->GetCurrentInitCommandBuffer(), width, height, data, data_stride))
return {}; return {};
} }
else 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!) // clear it instead so we don't read uninitialized data (and keep the validation layer happy!)
static constexpr VkClearColorValue ccv = {}; static constexpr VkClearColorValue ccv = {};
static constexpr VkImageSubresourceRange isr = {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}; static constexpr VkImageSubresourceRange isr = {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u};
vkCmdClearColorImage( vkCmdClearColorImage(g_vulkan_context->GetCurrentInitCommandBuffer(), texture.GetImage(), texture.GetLayout(), &ccv, 1u, &isr);
g_vulkan_context->GetCurrentCommandBuffer(), 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)); return std::make_unique<VulkanHostDisplayTexture>(std::move(texture));
} }
void VulkanHostDisplay::UpdateTexture( void VulkanHostDisplay::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data, u32 data_stride)
HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data, u32 data_stride)
{ {
UploadBufferToTexture( UploadBufferToTexture(&static_cast<VulkanHostDisplayTexture*>(texture)->GetTexture(), g_vulkan_context->GetCurrentCommandBuffer(),
&static_cast<VulkanHostDisplayTexture*>(texture)->GetTexture(), width, height, data, data_stride); width, height, data, data_stride);
} }
void VulkanHostDisplay::SetVSync(VsyncMode mode) void VulkanHostDisplay::SetVSync(VsyncMode mode)
@ -248,9 +265,8 @@ bool VulkanHostDisplay::CreateRenderDevice(
// debug_device = true; // debug_device = true;
WindowInfo local_wi(wi); WindowInfo local_wi(wi);
if (!Vulkan::Context::Create( if (!Vulkan::Context::Create(adapter_name, &local_wi, &m_swap_chain, GetPreferredPresentModeForVsyncMode(vsync), threaded_presentation,
adapter_name, &local_wi, &m_swap_chain, GetPreferredPresentModeForVsyncMode(vsync), debug_device, debug_device))
threaded_presentation, debug_device, debug_device))
{ {
Console.Error("Failed to create Vulkan context"); Console.Error("Failed to create Vulkan context");
m_window_info = {}; m_window_info = {};
@ -269,9 +285,15 @@ bool VulkanHostDisplay::InitializeRenderDevice(std::string_view shader_cache_dir
return true; 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() bool VulkanHostDisplay::CreateImGuiContext()
{ {
@ -301,9 +323,15 @@ void VulkanHostDisplay::DestroyRenderDevice()
Vulkan::Context::Destroy(); 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) 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); swap_chain_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
const VkClearValue clear_value = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; const VkClearValue clear_value = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
const VkRenderPassBeginInfo rp = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, const VkRenderPassBeginInfo rp = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, m_swap_chain->GetClearRenderPass(),
m_swap_chain->GetClearRenderPass(), m_swap_chain->GetCurrentFramebuffer(), m_swap_chain->GetCurrentFramebuffer(), {{0, 0}, {swap_chain_texture.GetWidth(), swap_chain_texture.GetHeight()}}, 1u, &clear_value};
{{0, 0}, {swap_chain_texture.GetWidth(), swap_chain_texture.GetHeight()}}, 1u, &clear_value};
vkCmdBeginRenderPass(g_vulkan_context->GetCurrentCommandBuffer(), &rp, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(g_vulkan_context->GetCurrentCommandBuffer(), &rp, VK_SUBPASS_CONTENTS_INLINE);
const VkViewport vp{0.0f, 0.0f, static_cast<float>(swap_chain_texture.GetWidth()), const VkViewport vp{
static_cast<float>(swap_chain_texture.GetHeight()), 0.0f, 1.0f}; 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{ const VkRect2D scissor{{0, 0}, {static_cast<u32>(swap_chain_texture.GetWidth()), static_cast<u32>(swap_chain_texture.GetHeight())}};
{0, 0}, {static_cast<u32>(swap_chain_texture.GetWidth()), static_cast<u32>(swap_chain_texture.GetHeight())}};
vkCmdSetViewport(g_vulkan_context->GetCurrentCommandBuffer(), 0, 1, &vp); vkCmdSetViewport(g_vulkan_context->GetCurrentCommandBuffer(), 0, 1, &vp);
vkCmdSetScissor(g_vulkan_context->GetCurrentCommandBuffer(), 0, 1, &scissor); vkCmdSetScissor(g_vulkan_context->GetCurrentCommandBuffer(), 0, 1, &scissor);
return true; return true;
@ -379,9 +405,8 @@ void VulkanHostDisplay::EndPresent()
vkCmdEndRenderPass(g_vulkan_context->GetCurrentCommandBuffer()); vkCmdEndRenderPass(g_vulkan_context->GetCurrentCommandBuffer());
m_swap_chain->GetCurrentTexture().TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); m_swap_chain->GetCurrentTexture().TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
g_vulkan_context->SubmitCommandBuffer(m_swap_chain->GetImageAvailableSemaphore(), g_vulkan_context->SubmitCommandBuffer(m_swap_chain->GetImageAvailableSemaphore(), m_swap_chain->GetRenderingFinishedSemaphore(),
m_swap_chain->GetRenderingFinishedSemaphore(), m_swap_chain->GetSwapChain(), m_swap_chain->GetSwapChain(), m_swap_chain->GetCurrentImageIndex(), !m_swap_chain->IsPresentModeSynchronizing());
m_swap_chain->GetCurrentImageIndex(), !m_swap_chain->IsPresentModeSynchronizing());
g_vulkan_context->MoveToNextCommandBuffer(); g_vulkan_context->MoveToNextCommandBuffer();
} }