renderer_vulkan: Cleanup code

This commit is contained in:
GPUCode
2023-02-01 00:46:48 +02:00
parent 5c401b8ea0
commit b6427d0ee0
3 changed files with 80 additions and 48 deletions

View File

@ -135,11 +135,8 @@ RendererVulkan::~RendererVulkan() {
} }
for (auto& info : screen_infos) { for (auto& info : screen_infos) {
const HostTextureTag tag = {.format = info.texture.alloc.format, device.destroyImageView(info.texture.image_view);
.width = info.texture.width, vmaDestroyImage(instance.GetAllocator(), info.texture.image, info.texture.allocation);
.height = info.texture.height};
runtime.Recycle(tag, std::move(info.texture.alloc));
} }
render_window.mailbox.reset(); render_window.mailbox.reset();
@ -205,6 +202,7 @@ void RendererVulkan::RenderToMailbox(const Layout::FramebufferLayout& layout,
{ {
MICROPROFILE_SCOPE(Vulkan_WaitPresent); MICROPROFILE_SCOPE(Vulkan_WaitPresent);
frame = mailbox->GetRenderFrame(); frame = mailbox->GetRenderFrame();
std::scoped_lock lock{frame->fence_mutex}; std::scoped_lock lock{frame->fence_mutex};
[[maybe_unused]] vk::Result result = [[maybe_unused]] vk::Result result =
device.waitForFences(frame->present_done, false, std::numeric_limits<u64>::max()); device.waitForFences(frame->present_done, false, std::numeric_limits<u64>::max());
@ -269,22 +267,17 @@ void RendererVulkan::RenderToMailbox(const Layout::FramebufferLayout& layout,
} }
void RendererVulkan::BeginRendering() { void RendererVulkan::BeginRendering() {
vk::Device device = instance.GetDevice();
std::array<vk::DescriptorImageInfo, 4> present_textures;
for (std::size_t i = 0; i < screen_infos.size(); i++) { for (std::size_t i = 0; i < screen_infos.size(); i++) {
const auto& info = screen_infos[i]; const auto& info = screen_infos[i];
present_textures[i] = vk::DescriptorImageInfo{ present_textures[i] = vk::DescriptorImageInfo{
.imageView = info.display_texture ? info.display_texture->image_view .imageView = info.image_view,
: info.texture.alloc.image_view,
.imageLayout = vk::ImageLayout::eGeneral, .imageLayout = vk::ImageLayout::eGeneral,
}; };
} }
present_textures[3].sampler = present_samplers[current_sampler];
present_textures[3] = vk::DescriptorImageInfo{.sampler = present_samplers[current_sampler]};
vk::DescriptorSet set = desc_manager.AllocateSet(present_descriptor_layout); vk::DescriptorSet set = desc_manager.AllocateSet(present_descriptor_layout);
device.updateDescriptorSetWithTemplate(set, present_update_template, present_textures[0]); instance.GetDevice().updateDescriptorSetWithTemplate(set, present_update_template, present_textures[0]);
scheduler.Record([this, set, pipeline_index = current_pipeline](vk::CommandBuffer cmdbuf) { scheduler.Record([this, set, pipeline_index = current_pipeline](vk::CommandBuffer cmdbuf) {
cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, present_pipelines[pipeline_index]); cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, present_pipelines[pipeline_index]);
@ -317,6 +310,10 @@ void RendererVulkan::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& fram
if (!rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, static_cast<u32>(pixel_stride), if (!rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, static_cast<u32>(pixel_stride),
screen_info)) { screen_info)) {
// Reset the screen info's display texture to its own permanent texture
screen_info.image_view = screen_info.texture.image_view;
screen_info.texcoords = {0.f, 0.f, 1.f, 1.f};
ASSERT(false); ASSERT(false);
} }
} }
@ -398,7 +395,6 @@ void RendererVulkan::BuildLayouts() {
.templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet, .templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet,
.descriptorSetLayout = present_descriptor_layout, .descriptorSetLayout = present_descriptor_layout,
}; };
present_update_template = device.createDescriptorUpdateTemplate(template_info); present_update_template = device.createDescriptorUpdateTemplate(template_info);
const vk::PushConstantRange push_range = { const vk::PushConstantRange push_range = {
@ -413,7 +409,6 @@ void RendererVulkan::BuildLayouts() {
.pushConstantRangeCount = 1, .pushConstantRangeCount = 1,
.pPushConstantRanges = &push_range, .pPushConstantRanges = &push_range,
}; };
present_pipeline_layout = device.createPipelineLayout(layout_info); present_pipeline_layout = device.createPipelineLayout(layout_info);
} }
@ -547,28 +542,63 @@ void RendererVulkan::BuildPipelines() {
void RendererVulkan::ConfigureFramebufferTexture(TextureInfo& texture, void RendererVulkan::ConfigureFramebufferTexture(TextureInfo& texture,
const GPU::Regs::FramebufferConfig& framebuffer) { const GPU::Regs::FramebufferConfig& framebuffer) {
TextureInfo old_texture = std::move(texture); vk::Device device = instance.GetDevice();
texture = TextureInfo{ if (texture.image_view) {
.alloc = device.destroyImageView(texture.image_view);
runtime.Allocate(framebuffer.width, framebuffer.height, }
VideoCore::PixelFormatFromGPUPixelFormat(framebuffer.color_format), if (texture.image) {
VideoCore::TextureType::Texture2D), vmaDestroyImage(instance.GetAllocator(), texture.image, texture.allocation);
.width = framebuffer.width, }
.height = framebuffer.height,
.format = framebuffer.color_format, const VideoCore::PixelFormat pixel_format = VideoCore::PixelFormatFromGPUPixelFormat(framebuffer.color_format);
const vk::Format format = instance.GetTraits(pixel_format).native;
const vk::ImageCreateInfo image_info = {
.imageType = vk::ImageType::e2D,
.format = format,
.extent = {framebuffer.width, framebuffer.height, 1},
.mipLevels = 1,
.arrayLayers = 1,
.samples = vk::SampleCountFlagBits::e1,
.usage = vk::ImageUsageFlagBits::eSampled,
}; };
// Recyle the old texture after allocation to avoid having duplicates of the same allocation in const VmaAllocationCreateInfo alloc_info = {
// the recycler .flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT,
if (old_texture.width != 0 && old_texture.height != 0) { .usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
const HostTextureTag tag = { .requiredFlags = 0,
.format = old_texture.alloc.format, .preferredFlags = 0,
.width = old_texture.width, .pool = VK_NULL_HANDLE,
.height = old_texture.height, .pUserData = nullptr,
}; };
runtime.Recycle(tag, std::move(old_texture.alloc)); VkImage unsafe_image{};
VkImageCreateInfo unsafe_image_info = static_cast<VkImageCreateInfo>(image_info);
VkResult result = vmaCreateImage(instance.GetAllocator(), &unsafe_image_info, &alloc_info,
&unsafe_image, &texture.allocation, nullptr);
if (result != VK_SUCCESS) [[unlikely]] {
LOG_CRITICAL(Render_Vulkan, "Failed allocating texture with error {}", result);
UNREACHABLE();
} }
texture.image = vk::Image{unsafe_image};
const vk::ImageViewCreateInfo view_info = {
.image = texture.image,
.viewType = vk::ImageViewType::e2D,
.format = format,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
};
texture.image_view = device.createImageView(view_info);
texture.width = framebuffer.width;
texture.height = framebuffer.height;
texture.format = framebuffer.color_format;
} }
void RendererVulkan::LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b, void RendererVulkan::LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b,
@ -584,7 +614,7 @@ void RendererVulkan::LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color
}; };
renderpass_cache.ExitRenderpass(); renderpass_cache.ExitRenderpass();
scheduler.Record([image = texture.alloc.image, clear_color](vk::CommandBuffer cmdbuf) { scheduler.Record([image = texture.image, clear_color](vk::CommandBuffer cmdbuf) {
const vk::ImageSubresourceRange range = { const vk::ImageSubresourceRange range = {
.aspectMask = vk::ImageAspectFlagBits::eColor, .aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0, .baseMipLevel = 0,
@ -650,7 +680,7 @@ void RendererVulkan::ReloadPipeline() {
void RendererVulkan::DrawSingleScreenRotated(u32 screen_id, float x, float y, float w, float h) { void RendererVulkan::DrawSingleScreenRotated(u32 screen_id, float x, float y, float w, float h) {
auto& screen_info = screen_infos[screen_id]; auto& screen_info = screen_infos[screen_id];
const auto& texcoords = screen_info.display_texcoords; const auto& texcoords = screen_info.texcoords;
u32 size = sizeof(ScreenRectVertex) * 4; u32 size = sizeof(ScreenRectVertex) * 4;
auto [ptr, offset, invalidate] = vertex_buffer.Map(size, 16); auto [ptr, offset, invalidate] = vertex_buffer.Map(size, 16);
@ -690,7 +720,7 @@ void RendererVulkan::DrawSingleScreenRotated(u32 screen_id, float x, float y, fl
void RendererVulkan::DrawSingleScreen(u32 screen_id, float x, float y, float w, float h) { void RendererVulkan::DrawSingleScreen(u32 screen_id, float x, float y, float w, float h) {
auto& screen_info = screen_infos[screen_id]; auto& screen_info = screen_infos[screen_id];
const auto& texcoords = screen_info.display_texcoords; const auto& texcoords = screen_info.texcoords;
u32 size = sizeof(ScreenRectVertex) * 4; u32 size = sizeof(ScreenRectVertex) * 4;
auto [ptr, offset, invalidate] = vertex_buffer.Map(size, 16); auto [ptr, offset, invalidate] = vertex_buffer.Map(size, 16);
@ -728,7 +758,7 @@ void RendererVulkan::DrawSingleScreen(u32 screen_id, float x, float y, float w,
void RendererVulkan::DrawSingleScreenStereoRotated(u32 screen_id_l, u32 screen_id_r, float x, void RendererVulkan::DrawSingleScreenStereoRotated(u32 screen_id_l, u32 screen_id_r, float x,
float y, float w, float h) { float y, float w, float h) {
const ScreenInfo& screen_info_l = screen_infos[screen_id_l]; const ScreenInfo& screen_info_l = screen_infos[screen_id_l];
const auto& texcoords = screen_info_l.display_texcoords; const auto& texcoords = screen_info_l.texcoords;
u32 size = sizeof(ScreenRectVertex) * 4; u32 size = sizeof(ScreenRectVertex) * 4;
auto [ptr, offset, invalidate] = vertex_buffer.Map(size, 16); auto [ptr, offset, invalidate] = vertex_buffer.Map(size, 16);
@ -766,7 +796,7 @@ void RendererVulkan::DrawSingleScreenStereoRotated(u32 screen_id_l, u32 screen_i
void RendererVulkan::DrawSingleScreenStereo(u32 screen_id_l, u32 screen_id_r, float x, float y, void RendererVulkan::DrawSingleScreenStereo(u32 screen_id_l, u32 screen_id_r, float x, float y,
float w, float h) { float w, float h) {
const ScreenInfo& screen_info_l = screen_infos[screen_id_l]; const ScreenInfo& screen_info_l = screen_infos[screen_id_l];
const auto& texcoords = screen_info_l.display_texcoords; const auto& texcoords = screen_info_l.texcoords;
u32 size = sizeof(ScreenRectVertex) * 4; u32 size = sizeof(ScreenRectVertex) * 4;
auto [ptr, offset, invalidate] = vertex_buffer.Map(size, 16); auto [ptr, offset, invalidate] = vertex_buffer.Map(size, 16);

View File

@ -30,16 +30,18 @@ struct FramebufferLayout;
namespace Vulkan { namespace Vulkan {
struct TextureInfo { struct TextureInfo {
ImageAlloc alloc;
u32 width; u32 width;
u32 height; u32 height;
GPU::Regs::PixelFormat format; GPU::Regs::PixelFormat format;
vk::Image image;
vk::ImageView image_view;
VmaAllocation allocation;
}; };
struct ScreenInfo { struct ScreenInfo {
ImageAlloc* display_texture = nullptr;
Common::Rectangle<float> display_texcoords;
TextureInfo texture; TextureInfo texture;
Common::Rectangle<f32> texcoords;
vk::ImageView image_view;
vk::Sampler sampler; vk::Sampler sampler;
}; };
@ -55,11 +57,11 @@ struct PresentUniformData {
static_assert(sizeof(PresentUniformData) < 256, "PresentUniformData must be below 256 bytes!"); static_assert(sizeof(PresentUniformData) < 256, "PresentUniformData must be below 256 bytes!");
constexpr u32 PRESENT_PIPELINES = 3;
class RasterizerVulkan; class RasterizerVulkan;
class RendererVulkan : public RendererBase { class RendererVulkan : public RendererBase {
static constexpr std::size_t PRESENT_PIPELINES = 3;
public: public:
explicit RendererVulkan(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window); explicit RendererVulkan(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window);
~RendererVulkan() override; ~RendererVulkan() override;
@ -100,7 +102,6 @@ private:
void UpdateFramerate(); void UpdateFramerate();
/// Loads framebuffer from emulated memory into the display information structure
void LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer, void LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
ScreenInfo& screen_info, bool right_eye); ScreenInfo& screen_info, bool right_eye);
@ -134,6 +135,7 @@ private:
// Display information for top and bottom screens respectively // Display information for top and bottom screens respectively
std::array<ScreenInfo, 3> screen_infos{}; std::array<ScreenInfo, 3> screen_infos{};
std::array<vk::DescriptorImageInfo, 4> present_textures{};
PresentUniformData draw_info{}; PresentUniformData draw_info{};
vk::ClearColorValue clear_color{}; vk::ClearColorValue clear_color{};
}; };

View File

@ -1009,14 +1009,14 @@ bool RasterizerVulkan::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con
return false; return false;
} }
u32 scaled_width = src_surface->GetScaledWidth(); const u32 scaled_width = src_surface->GetScaledWidth();
u32 scaled_height = src_surface->GetScaledHeight(); const u32 scaled_height = src_surface->GetScaledHeight();
screen_info.display_texcoords = Common::Rectangle<float>( screen_info.texcoords = Common::Rectangle<f32>(
(float)src_rect.bottom / (float)scaled_height, (float)src_rect.left / (float)scaled_width, (float)src_rect.bottom / (float)scaled_height, (float)src_rect.left / (float)scaled_width,
(float)src_rect.top / (float)scaled_height, (float)src_rect.right / (float)scaled_width); (float)src_rect.top / (float)scaled_height, (float)src_rect.right / (float)scaled_width);
screen_info.display_texture = &src_surface->alloc; screen_info.image_view = src_surface->GetImageView();
return true; return true;
} }