renderer_vulkan: Cleanup code
This commit is contained in:
@ -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),
|
|
||||||
VideoCore::TextureType::Texture2D),
|
|
||||||
.width = framebuffer.width,
|
|
||||||
.height = framebuffer.height,
|
|
||||||
.format = framebuffer.color_format,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Recyle the old texture after allocation to avoid having duplicates of the same allocation in
|
|
||||||
// the recycler
|
|
||||||
if (old_texture.width != 0 && old_texture.height != 0) {
|
|
||||||
const HostTextureTag tag = {
|
|
||||||
.format = old_texture.alloc.format,
|
|
||||||
.width = old_texture.width,
|
|
||||||
.height = old_texture.height,
|
|
||||||
};
|
|
||||||
|
|
||||||
runtime.Recycle(tag, std::move(old_texture.alloc));
|
|
||||||
}
|
}
|
||||||
|
if (texture.image) {
|
||||||
|
vmaDestroyImage(instance.GetAllocator(), texture.image, texture.allocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
|
const VmaAllocationCreateInfo alloc_info = {
|
||||||
|
.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT,
|
||||||
|
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
||||||
|
.requiredFlags = 0,
|
||||||
|
.preferredFlags = 0,
|
||||||
|
.pool = VK_NULL_HANDLE,
|
||||||
|
.pUserData = nullptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
@ -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{};
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user