From 9bdf09bd768f73073e9d1cbc65febfd7f7955db3 Mon Sep 17 00:00:00 2001 From: Liam Date: Thu, 18 Jan 2024 11:44:13 -0500 Subject: renderer_vulkan: implement layer stack composition --- src/video_core/renderer_vulkan/vk_blit_screen.cpp | 378 ++-------------------- 1 file changed, 34 insertions(+), 344 deletions(-) (limited to 'src/video_core/renderer_vulkan/vk_blit_screen.cpp') diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 8d01ec9fc..b2dcbf80b 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -1,65 +1,15 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include -#include -#include -#include - -#include "common/assert.h" -#include "common/common_types.h" -#include "common/settings.h" -#include "core/core.h" -#include "core/frontend/emu_window.h" -#include "video_core/gpu.h" -#include "video_core/host1x/gpu_device_memory_manager.h" +#include "video_core/framebuffer_config.h" #include "video_core/renderer_vulkan/present/filters.h" -#include "video_core/renderer_vulkan/present/fsr.h" -#include "video_core/renderer_vulkan/present/fxaa.h" -#include "video_core/renderer_vulkan/present/smaa.h" -#include "video_core/renderer_vulkan/renderer_vulkan.h" +#include "video_core/renderer_vulkan/present/layer.h" #include "video_core/renderer_vulkan/vk_blit_screen.h" +#include "video_core/renderer_vulkan/vk_present_manager.h" #include "video_core/renderer_vulkan/vk_scheduler.h" -#include "video_core/renderer_vulkan/vk_shader_util.h" -#include "video_core/surface.h" -#include "video_core/textures/decoders.h" -#include "video_core/vulkan_common/vulkan_device.h" -#include "video_core/vulkan_common/vulkan_memory_allocator.h" -#include "video_core/vulkan_common/vulkan_wrapper.h" namespace Vulkan { -namespace { - -u32 GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) { - using namespace VideoCore::Surface; - return BytesPerBlock(PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)); -} - -std::size_t GetSizeInBytes(const Tegra::FramebufferConfig& framebuffer) { - return static_cast(framebuffer.stride) * - static_cast(framebuffer.height) * GetBytesPerPixel(framebuffer); -} - -VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { - switch (framebuffer.pixel_format) { - case Service::android::PixelFormat::Rgba8888: - case Service::android::PixelFormat::Rgbx8888: - return VK_FORMAT_A8B8G8R8_UNORM_PACK32; - case Service::android::PixelFormat::Rgb565: - return VK_FORMAT_R5G6B5_UNORM_PACK16; - case Service::android::PixelFormat::Bgra8888: - return VK_FORMAT_B8G8R8A8_UNORM; - default: - UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", - static_cast(framebuffer.pixel_format)); - return VK_FORMAT_A8B8G8R8_UNORM_PACK32; - } -} - -} // Anonymous namespace - BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_, const Device& device_, MemoryAllocator& memory_allocator_, PresentManager& present_manager_, Scheduler& scheduler_) @@ -75,194 +25,35 @@ void BlitScreen::WaitIdle() { device.GetLogical().WaitIdle(); } -void BlitScreen::SetWindowAdaptPass(const Layout::FramebufferLayout& layout) { +void BlitScreen::SetWindowAdaptPass() { + layers.clear(); scaling_filter = Settings::values.scaling_filter.GetValue(); - const VkExtent2D adapt_size{ - .width = layout.screen.GetWidth(), - .height = layout.screen.GetHeight(), - }; - - fsr.reset(); - switch (scaling_filter) { case Settings::ScalingFilter::NearestNeighbor: - window_adapt = - MakeNearestNeighbor(device, memory_allocator, image_count, swapchain_view_format); + window_adapt = MakeNearestNeighbor(device, swapchain_view_format); break; case Settings::ScalingFilter::Bicubic: - window_adapt = MakeBicubic(device, memory_allocator, image_count, swapchain_view_format); + window_adapt = MakeBicubic(device, swapchain_view_format); break; case Settings::ScalingFilter::Gaussian: - window_adapt = MakeGaussian(device, memory_allocator, image_count, swapchain_view_format); + window_adapt = MakeGaussian(device, swapchain_view_format); break; case Settings::ScalingFilter::ScaleForce: - window_adapt = MakeScaleForce(device, memory_allocator, image_count, swapchain_view_format); + window_adapt = MakeScaleForce(device, swapchain_view_format); break; case Settings::ScalingFilter::Fsr: - fsr = std::make_unique(device, memory_allocator, image_count, adapt_size); - [[fallthrough]]; case Settings::ScalingFilter::Bilinear: default: - window_adapt = MakeBilinear(device, memory_allocator, image_count, swapchain_view_format); + window_adapt = MakeBilinear(device, swapchain_view_format); break; } } -void BlitScreen::SetAntiAliasPass() { - if (anti_alias && anti_aliasing == Settings::values.anti_aliasing.GetValue()) { - return; - } - - anti_aliasing = Settings::values.anti_aliasing.GetValue(); - - const VkExtent2D render_area{ - .width = Settings::values.resolution_info.ScaleUp(raw_width), - .height = Settings::values.resolution_info.ScaleUp(raw_height), - }; - - switch (anti_aliasing) { - case Settings::AntiAliasing::Fxaa: - anti_alias = std::make_unique(device, memory_allocator, image_count, render_area); - break; - case Settings::AntiAliasing::Smaa: - anti_alias = std::make_unique(device, memory_allocator, image_count, render_area); - break; - default: - anti_alias = std::make_unique(); - break; - } -} - -void BlitScreen::Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConfig& framebuffer, - const Layout::FramebufferLayout& layout, Frame* dst) { - const auto texture_info = rasterizer.AccelerateDisplay( - framebuffer, framebuffer.address + framebuffer.offset, framebuffer.stride); - const u32 texture_width = texture_info ? texture_info->width : framebuffer.width; - const u32 texture_height = texture_info ? texture_info->height : framebuffer.height; - const u32 scaled_width = texture_info ? texture_info->scaled_width : texture_width; - const u32 scaled_height = texture_info ? texture_info->scaled_height : texture_height; - const bool use_accelerated = texture_info.has_value(); - - RefreshResources(framebuffer); - SetAntiAliasPass(); - - // Finish any pending renderpass - scheduler.RequestOutsideRenderPassOperationContext(); - - scheduler.Wait(resource_ticks[image_index]); - SCOPE_EXIT({ resource_ticks[image_index] = scheduler.CurrentTick(); }); - - VkImage source_image = texture_info ? texture_info->image : *raw_images[image_index]; - VkImageView source_image_view = - texture_info ? texture_info->image_view : *raw_image_views[image_index]; - - const std::span mapped_span = buffer.Mapped(); - - if (!use_accelerated) { - const u64 image_offset = GetRawImageOffset(framebuffer); - - const DAddr framebuffer_addr = framebuffer.address + framebuffer.offset; - const u8* const host_ptr = device_memory.GetPointer(framebuffer_addr); - - // TODO(Rodrigo): Read this from HLE - constexpr u32 block_height_log2 = 4; - const u32 bytes_per_pixel = GetBytesPerPixel(framebuffer); - const u64 linear_size{GetSizeInBytes(framebuffer)}; - const u64 tiled_size{Tegra::Texture::CalculateSize(true, bytes_per_pixel, - framebuffer.stride, framebuffer.height, - 1, block_height_log2, 0)}; - Tegra::Texture::UnswizzleTexture( - mapped_span.subspan(image_offset, linear_size), std::span(host_ptr, tiled_size), - bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0); - - const VkBufferImageCopy copy{ - .bufferOffset = image_offset, - .bufferRowLength = 0, - .bufferImageHeight = 0, - .imageSubresource = - { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1, - }, - .imageOffset = {.x = 0, .y = 0, .z = 0}, - .imageExtent = - { - .width = framebuffer.width, - .height = framebuffer.height, - .depth = 1, - }, - }; - scheduler.Record([this, copy, index = image_index](vk::CommandBuffer cmdbuf) { - const VkImage image = *raw_images[index]; - const VkImageMemoryBarrier base_barrier{ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = 0, - .dstAccessMask = 0, - .oldLayout = VK_IMAGE_LAYOUT_GENERAL, - .newLayout = VK_IMAGE_LAYOUT_GENERAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image, - .subresourceRange{ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - VkImageMemoryBarrier read_barrier = base_barrier; - read_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - read_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - read_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkImageMemoryBarrier write_barrier = base_barrier; - write_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - write_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, - read_barrier); - cmdbuf.CopyBufferToImage(*buffer, image, VK_IMAGE_LAYOUT_GENERAL, copy); - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - 0, write_barrier); - }); - } - - anti_alias->Draw(scheduler, image_index, &source_image, &source_image_view); - - const auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height); - const VkExtent2D render_extent{ - .width = scaled_width, - .height = scaled_height, - }; - - if (fsr) { - const VkExtent2D adapt_size{ - .width = layout.screen.GetWidth(), - .height = layout.screen.GetHeight(), - }; - - source_image_view = fsr->Draw(scheduler, image_index, source_image, source_image_view, - render_extent, crop_rect); - - const Common::Rectangle output_crop{0, 0, 1, 1}; - window_adapt->Draw(scheduler, image_index, source_image_view, adapt_size, output_crop, - layout, dst); - } else { - window_adapt->Draw(scheduler, image_index, source_image_view, render_extent, crop_rect, - layout, dst); - } -} - void BlitScreen::DrawToFrame(RasterizerVulkan& rasterizer, Frame* frame, - const Tegra::FramebufferConfig& framebuffer, - const Layout::FramebufferLayout& layout, size_t swapchain_images, + std::span framebuffers, + const Layout::FramebufferLayout& layout, + size_t current_swapchain_image_count, VkFormat current_swapchain_view_format) { bool resource_update_required = false; bool presentation_recreate_required = false; @@ -272,11 +63,10 @@ void BlitScreen::DrawToFrame(RasterizerVulkan& rasterizer, Frame* frame, resource_update_required = true; } - // Recreate dynamic resources if the the image count or input format changed - const VkFormat old_framebuffer_format = - std::exchange(framebuffer_view_format, GetFormat(framebuffer)); - if (swapchain_images != image_count || old_framebuffer_format != framebuffer_view_format) { - image_count = swapchain_images; + // Recreate dynamic resources if the image count changed + const size_t old_swapchain_image_count = + std::exchange(image_count, current_swapchain_image_count); + if (old_swapchain_image_count != current_swapchain_image_count) { resource_update_required = true; } @@ -294,11 +84,8 @@ void BlitScreen::DrawToFrame(RasterizerVulkan& rasterizer, Frame* frame, // Wait for idle to ensure no resources are in use WaitIdle(); - // Set new number of resource ticks - resource_ticks.resize(swapchain_images); - // Update window adapt pass - SetWindowAdaptPass(layout); + SetWindowAdaptPass(); // Update frame format if needed if (presentation_recreate_required) { @@ -307,7 +94,21 @@ void BlitScreen::DrawToFrame(RasterizerVulkan& rasterizer, Frame* frame, } } - Draw(rasterizer, framebuffer, layout, frame); + // Add additional layers if needed + const VkExtent2D window_size{ + .width = layout.screen.GetWidth(), + .height = layout.screen.GetHeight(), + }; + + while (layers.size() < framebuffers.size()) { + layers.emplace_back(device, memory_allocator, scheduler, device_memory, image_count, + window_size, window_adapt->GetDescriptorSetLayout()); + } + + // Perform the draw + window_adapt->Draw(rasterizer, scheduler, image_index, layers, framebuffers, layout, frame); + + // Advance to next image if (++image_index >= image_count) { image_index = 0; } @@ -321,7 +122,7 @@ vk::Framebuffer BlitScreen::CreateFramebuffer(const Layout::FramebufferLayout& l if (!window_adapt || scaling_filter != Settings::values.scaling_filter.GetValue() || format_updated) { WaitIdle(); - SetWindowAdaptPass(layout); + SetWindowAdaptPass(); } const VkExtent2D extent{ .width = layout.width, @@ -345,115 +146,4 @@ vk::Framebuffer BlitScreen::CreateFramebuffer(const VkImageView& image_view, VkE }); } -void BlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { - if (framebuffer.width == raw_width && framebuffer.height == raw_height && - framebuffer.pixel_format == pixel_format && !raw_images.empty()) { - return; - } - - raw_width = framebuffer.width; - raw_height = framebuffer.height; - pixel_format = framebuffer.pixel_format; - anti_alias.reset(); - - ReleaseRawImages(); - CreateStagingBuffer(framebuffer); - CreateRawImages(framebuffer); -} - -void BlitScreen::ReleaseRawImages() { - for (const u64 tick : resource_ticks) { - scheduler.Wait(tick); - } - raw_images.clear(); - buffer.reset(); -} - -void BlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) { - const VkBufferCreateInfo ci{ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = CalculateBufferSize(framebuffer), - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0, - .pQueueFamilyIndices = nullptr, - }; - - buffer = memory_allocator.CreateBuffer(ci, MemoryUsage::Upload); -} - -void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { - raw_images.resize(image_count); - raw_image_views.resize(image_count); - - const auto create_image = [&](bool used_on_framebuffer = false, u32 up_scale = 1, - u32 down_shift = 0) { - u32 extra_usages = used_on_framebuffer ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - : VK_IMAGE_USAGE_TRANSFER_DST_BIT; - return memory_allocator.CreateImage(VkImageCreateInfo{ - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .imageType = VK_IMAGE_TYPE_2D, - .format = used_on_framebuffer ? VK_FORMAT_R16G16B16A16_SFLOAT : framebuffer_view_format, - .extent = - { - .width = (up_scale * framebuffer.width) >> down_shift, - .height = (up_scale * framebuffer.height) >> down_shift, - .depth = 1, - }, - .mipLevels = 1, - .arrayLayers = 1, - .samples = VK_SAMPLE_COUNT_1_BIT, - .tiling = used_on_framebuffer ? VK_IMAGE_TILING_OPTIMAL : VK_IMAGE_TILING_LINEAR, - .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | extra_usages, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0, - .pQueueFamilyIndices = nullptr, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - }); - }; - const auto create_image_view = [&](vk::Image& image, bool used_on_framebuffer = false) { - return device.GetLogical().CreateImageView(VkImageViewCreateInfo{ - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .image = *image, - .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = used_on_framebuffer ? VK_FORMAT_R16G16B16A16_SFLOAT : framebuffer_view_format, - .components = - { - .r = VK_COMPONENT_SWIZZLE_IDENTITY, - .g = VK_COMPONENT_SWIZZLE_IDENTITY, - .b = VK_COMPONENT_SWIZZLE_IDENTITY, - .a = VK_COMPONENT_SWIZZLE_IDENTITY, - }, - .subresourceRange = - { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }); - }; - - for (size_t i = 0; i < image_count; ++i) { - raw_images[i] = create_image(); - raw_image_views[i] = create_image_view(raw_images[i]); - } -} - -u64 BlitScreen::CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const { - return GetSizeInBytes(framebuffer) * image_count; -} - -u64 BlitScreen::GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer) const { - return GetSizeInBytes(framebuffer) * image_index; -} - } // namespace Vulkan -- cgit v1.2.3