From c091457984a25cb97ba5b75fa83d2731994e9020 Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Fri, 10 Nov 2023 17:55:28 -0800 Subject: [PATCH] rasterizer: Add multi-sampled surfaces Vulkan implementation only --- .../rasterizer_cache/rasterizer_cache.h | 4 + .../rasterizer_cache/surface_params.h | 5 ++ .../renderer_vulkan/vk_texture_runtime.cpp | 75 ++++++++++++------- .../renderer_vulkan/vk_texture_runtime.h | 4 +- 4 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.h b/src/video_core/rasterizer_cache/rasterizer_cache.h index b935ed0f4..e3216a07b 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.h +++ b/src/video_core/rasterizer_cache/rasterizer_cache.h @@ -273,6 +273,7 @@ bool RasterizerCache::AccelerateDisplayTransfer(const Pica::DisplayTransferCo src_params.height = config.output_height; src_params.is_tiled = !config.input_linear; src_params.pixel_format = PixelFormatFromGPUPixelFormat(config.input_format); + src_params.sample_count = sample_count; src_params.UpdateParams(); SurfaceParams dst_params; @@ -283,6 +284,7 @@ bool RasterizerCache::AccelerateDisplayTransfer(const Pica::DisplayTransferCo : config.output_height.Value(); dst_params.is_tiled = config.input_linear != config.dont_swizzle; dst_params.pixel_format = PixelFormatFromGPUPixelFormat(config.output_format); + dst_params.sample_count = sample_count; dst_params.UpdateParams(); // Using flip_vertically alongside crop_input_lines produces skewed output on hardware. @@ -556,6 +558,7 @@ SurfaceId RasterizerCache::GetTextureSurface(const Pica::Texture::TextureInfo params.is_tiled = true; params.pixel_format = PixelFormatFromTextureFormat(info.format); params.res_scale = filter != Settings::TextureFilter::None ? resolution_scale_factor : 1; + params.sample_count = max_level == 0 ? sample_count : 1; params.UpdateParams(); const u32 min_width = info.width >> max_level; @@ -683,6 +686,7 @@ FramebufferHelper RasterizerCache::GetFramebufferSurfaces(bool using_color SurfaceParams color_params; color_params.is_tiled = true; color_params.res_scale = resolution_scale_factor; + color_params.sample_count = sample_count; color_params.width = config.GetWidth(); color_params.height = config.GetHeight(); SurfaceParams depth_params = color_params; diff --git a/src/video_core/rasterizer_cache/surface_params.h b/src/video_core/rasterizer_cache/surface_params.h index 23e4db7e2..c05cb3c5e 100644 --- a/src/video_core/rasterizer_cache/surface_params.h +++ b/src/video_core/rasterizer_cache/surface_params.h @@ -71,6 +71,10 @@ public: return height * res_scale; } + [[nodiscard]] u8 GetSampleCount() const noexcept { + return sample_count; + } + [[nodiscard]] Common::Rectangle GetRect(u32 level = 0) const noexcept { return {0, height >> level, width >> level, 0}; } @@ -104,6 +108,7 @@ public: u32 stride = 0; u32 levels = 1; u32 res_scale = 1; + u8 sample_count = 1; bool is_tiled = false; TextureType texture_type = TextureType::Texture2D; diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp index 11ae2e9f2..41b873afe 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp @@ -144,8 +144,8 @@ boost::container::small_vector MakeInitBarriers( } Handle MakeHandle(const Instance* instance, u32 width, u32 height, u32 levels, TextureType type, - vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags flags, - vk::ImageAspectFlags aspect, bool need_format_list, + vk::Format format, vk::SampleCountFlagBits samples, vk::ImageUsageFlags usage, + vk::ImageCreateFlags flags, vk::ImageAspectFlags aspect, bool need_format_list, std::string_view debug_name = {}) { const u32 layers = type == TextureType::CubeMap ? 6 : 1; @@ -166,7 +166,7 @@ Handle MakeHandle(const Instance* instance, u32 width, u32 height, u32 levels, T .extent = {width, height, 1}, .mipLevels = levels, .arrayLayers = layers, - .samples = vk::SampleCountFlagBits::e1, + .samples = samples, .usage = usage, }; @@ -311,7 +311,7 @@ bool TextureRuntime::ClearTexture(Surface& surface, const VideoCore::TextureClea .aspect = surface.Aspect(), .pipeline_flags = surface.PipelineStageFlags(), .src_access = surface.AccessFlags(), - .src_image = surface.Image(), + .src_image = surface.GetSampleCount() > 1 ? surface.Image(3) : surface.Image(), }; if (clear.texture_rect == surface.GetScaledRect()) { @@ -377,7 +377,8 @@ void TextureRuntime::ClearTextureWithRenderpass(Surface& surface, const auto color_format = is_color ? surface.pixel_format : PixelFormat::Invalid; const auto depth_format = is_color ? PixelFormat::Invalid : surface.pixel_format; - const auto render_pass = renderpass_cache.GetRenderpass(color_format, depth_format, true); + const auto render_pass = + renderpass_cache.GetRenderpass(color_format, depth_format, true, surface.GetSampleCount()); const RecordParams params = { .aspect = surface.Aspect(), @@ -432,13 +433,14 @@ void TextureRuntime::ClearTextureWithRenderpass(Surface& surface, }; const auto clear_value = MakeClearValue(clear.value); + std::array clear_values = {clear_value, clear_value}; const vk::RenderPassBeginInfo renderpass_begin_info = { .renderPass = render_pass, .framebuffer = framebuffer, .renderArea = render_area, - .clearValueCount = 1, - .pClearValues = &clear_value, + .clearValueCount = 2, + .pClearValues = clear_values.data(), }; cmdbuf.pipelineBarrier(params.pipeline_flags, pipeline_flags, @@ -725,18 +727,29 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceParams& param flags |= vk::ImageCreateFlagBits::eMutableFormat; } + // Native image const bool need_format_list = is_mutable && instance->IsImageFormatListSupported(); - handles[0] = MakeHandle(instance, width, height, levels, texture_type, format, traits.usage, - flags, traits.aspect, need_format_list, DebugName(false)); + handles[0] = MakeHandle(instance, width, height, levels, texture_type, format, + vk::SampleCountFlagBits::e1, traits.usage, flags, traits.aspect, + need_format_list, DebugName(false)); raw_images.emplace_back(handles[0].image); + // Upscaled image if (res_scale != 1) { - handles[1] = - MakeHandle(instance, GetScaledWidth(), GetScaledHeight(), levels, texture_type, format, - traits.usage, flags, traits.aspect, need_format_list, DebugName(true)); + handles[1] = MakeHandle(instance, GetScaledWidth(), GetScaledHeight(), levels, texture_type, + format, vk::SampleCountFlagBits::e1, traits.usage, flags, + traits.aspect, need_format_list, DebugName(true)); raw_images.emplace_back(handles[1].image); } + // Upscales+MSAA image + if (vk::SampleCountFlagBits(sample_count) > vk::SampleCountFlagBits::e1) { + handles[3] = MakeHandle(instance, GetScaledWidth(), GetScaledHeight(), levels, texture_type, + format, vk::SampleCountFlagBits(sample_count), traits.usage, flags, + traits.aspect, need_format_list, DebugName(true)); + raw_images.emplace_back(handles[3].image); + } + runtime->renderpass_cache.EndRendering(); scheduler->Record([raw_images, aspect = traits.aspect](vk::CommandBuffer cmdbuf) { const auto barriers = MakeInitBarriers(aspect, raw_images); @@ -757,7 +770,7 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceBase& surface const bool has_normal = mat && mat->Map(MapType::Normal); const vk::Format format = traits.native; - boost::container::static_vector raw_images; + boost::container::static_vector raw_images; vk::ImageCreateFlags flags{}; if (texture_type == VideoCore::TextureType::CubeMap) { @@ -766,18 +779,26 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceBase& surface const std::string debug_name = DebugName(false, true); handles[0] = MakeHandle(instance, mat->width, mat->height, levels, texture_type, format, - traits.usage, flags, traits.aspect, false, debug_name); + vk::SampleCountFlagBits::e1, traits.usage, flags, traits.aspect, false, + debug_name); raw_images.emplace_back(handles[0].image); if (res_scale != 1) { handles[1] = MakeHandle(instance, mat->width, mat->height, levels, texture_type, - vk::Format::eR8G8B8A8Unorm, traits.usage, flags, traits.aspect, - false, debug_name); + vk::Format::eR8G8B8A8Unorm, vk::SampleCountFlagBits::e1, + traits.usage, flags, traits.aspect, false, debug_name); raw_images.emplace_back(handles[1].image); } + if (vk::SampleCountFlagBits(sample_count) > vk::SampleCountFlagBits::e1) { + handles[3] = MakeHandle(instance, GetScaledWidth(), GetScaledHeight(), levels, texture_type, + format, vk::SampleCountFlagBits(sample_count), traits.usage, flags, + traits.aspect, false, debug_name); + raw_images.emplace_back(handles[3].image); + } if (has_normal) { handles[2] = MakeHandle(instance, mat->width, mat->height, levels, texture_type, format, - traits.usage, flags, traits.aspect, false, debug_name); + vk::SampleCountFlagBits::e1, traits.usage, flags, traits.aspect, + false, debug_name); raw_images.emplace_back(handles[2].image); } @@ -1076,9 +1097,9 @@ void Surface::ScaleUp(u32 new_scale) { flags |= vk::ImageCreateFlagBits::eMutableFormat; } - handles[1] = - MakeHandle(instance, GetScaledWidth(), GetScaledHeight(), levels, texture_type, - traits.native, traits.usage, flags, traits.aspect, false, DebugName(true)); + handles[1] = MakeHandle(instance, GetScaledWidth(), GetScaledHeight(), levels, texture_type, + traits.native, vk::SampleCountFlagBits::e1, traits.usage, flags, + traits.aspect, false, DebugName(true)); runtime->renderpass_cache.EndRendering(); scheduler->Record( @@ -1152,9 +1173,9 @@ vk::ImageView Surface::CopyImageView() noexcept { if (texture_type == VideoCore::TextureType::CubeMap) { flags |= vk::ImageCreateFlagBits::eCubeCompatible; } - copy_handle = - MakeHandle(instance, GetScaledWidth(), GetScaledHeight(), levels, texture_type, - traits.native, traits.usage, flags, traits.aspect, false); + copy_handle = MakeHandle(instance, GetScaledWidth(), GetScaledHeight(), levels, + texture_type, traits.native, vk::SampleCountFlagBits::e1, + traits.usage, flags, traits.aspect, false); copy_layout = vk::ImageLayout::eUndefined; } @@ -1346,8 +1367,12 @@ vk::Framebuffer Surface::Framebuffer() noexcept { const auto color_format = is_depth ? PixelFormat::Invalid : pixel_format; const auto depth_format = is_depth ? pixel_format : PixelFormat::Invalid; const auto render_pass = - runtime->renderpass_cache.GetRenderpass(color_format, depth_format, false); - const auto attachments = std::array{ImageView()}; + runtime->renderpass_cache.GetRenderpass(color_format, depth_format, false, sample_count); + boost::container::static_vector attachments; + attachments.emplace_back(ImageView()); + if (sample_count > 1) { + attachments.emplace_back(ImageView(3)); + } framebuffers[index] = MakeFramebuffer(instance->GetDevice(), render_pass, GetScaledWidth(), GetScaledHeight(), attachments); return framebuffers[index].get(); diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.h b/src/video_core/renderer_vulkan/vk_texture_runtime.h index eeede2f0a..c00bf6853 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.h +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.h @@ -181,8 +181,8 @@ public: const Instance* instance; Scheduler* scheduler; FormatTraits traits; - std::array handles{}; - std::array framebuffers{}; + std::array handles{}; + std::array framebuffers{}; Handle copy_handle; vk::UniqueImageView depth_view; vk::UniqueImageView stencil_view;