From 2b5983844d7d4426e15b18e45915978a3ee9b965 Mon Sep 17 00:00:00 2001 From: psucien Date: Wed, 26 Jun 2024 12:22:41 +0200 Subject: [PATCH] renderer_vulkan: initial CMask support --- .../renderer_vulkan/liverpool_to_vk.cpp | 60 +++++++++++++++++++ .../renderer_vulkan/liverpool_to_vk.h | 4 ++ .../renderer_vulkan/vk_compute_pipeline.cpp | 9 +++ .../renderer_vulkan/vk_rasterizer.cpp | 11 +++- 4 files changed, 81 insertions(+), 3 deletions(-) diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index 8e3f92074..f95d8f111 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/assert.h" +#include "video_core/amdgpu/pixel_format.h" #include "video_core/renderer_vulkan/liverpool_to_vk.h" namespace Vulkan::LiverpoolToVK { @@ -381,6 +382,13 @@ vk::Format AdjustColorBufferFormat(vk::Format base_format, case vk::Format::eB8G8R8A8Srgb: return is_vo_surface ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb; } + } else { + if (is_vo_surface && base_format == vk::Format::eR8G8B8A8Srgb) { + return vk::Format::eR8G8B8A8Unorm; + } + if (is_vo_surface && base_format == vk::Format::eB8G8R8A8Srgb) { + return vk::Format::eB8G8R8A8Unorm; + } } return base_format; } @@ -422,4 +430,56 @@ void EmitQuadToTriangleListIndices(u8* out_ptr, u32 num_vertices) { } } +static constexpr float U8ToUnorm(u8 v) { + static constexpr auto c = 1.0f / 255.0f; + return float(v * c); +} + +vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color_buffer) { + const auto comp_swap = color_buffer.info.comp_swap.Value(); + ASSERT_MSG(comp_swap == Liverpool::ColorBuffer::SwapMode::Standard || + comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate, + "Unsupported component swap mode {}", static_cast(comp_swap)); + + const bool comp_swap_alt = comp_swap == Liverpool::ColorBuffer::SwapMode::Alternate; + + const auto& c0 = color_buffer.clear_word0; + const auto& c1 = color_buffer.clear_word1; + const auto num_bits = AmdGpu::NumBits(color_buffer.info.format); + + vk::ClearColorValue color{}; + switch (color_buffer.info.number_type) { + case AmdGpu::NumberFormat::Snorm: + [[fallthrough]]; + case AmdGpu::NumberFormat::SnormNz: + [[fallthrough]]; + case AmdGpu::NumberFormat::Unorm: + [[fallthrough]]; + case AmdGpu::NumberFormat::Srgb: { + switch (num_bits) { + case 32: { + color.float32 = std::array{ + U8ToUnorm((c0 >> (comp_swap_alt ? 16 : 0)) & 0xff), + U8ToUnorm((c0 >> 8) & 0xff), + U8ToUnorm((c0 >> (comp_swap_alt ? 0 : 16)) & 0xff), + U8ToUnorm((c0 >> 24) & 0xff), + }; + break; + } + default: { + LOG_ERROR(Render_Vulkan, "Missing clear color conversion for bits {}", num_bits); + break; + } + } + break; + } + default: { + LOG_ERROR(Render_Vulkan, "Missing clear color conversion for type {}", + color_buffer.info.number_type.Value()); + break; + } + } + return {.color = color}; +} + } // namespace Vulkan::LiverpoolToVK diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.h b/src/video_core/renderer_vulkan/liverpool_to_vk.h index 59df89b4d..a61d68bdf 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.h +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.h @@ -46,6 +46,10 @@ vk::Format AdjustColorBufferFormat(vk::Format base_format, vk::Format DepthFormat(Liverpool::DepthBuffer::ZFormat z_format, Liverpool::DepthBuffer::StencilFormat stencil_format); +vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color_buffer); + +vk::ClearValue DepthClearValue(); + void EmitQuadToTriangleListIndices(u8* out_indices, u32 num_vertices); } // namespace Vulkan::LiverpoolToVK diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 0d59d13fc..73417c558 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -109,6 +109,15 @@ void ComputePipeline::BindResources(Core::MemoryManager* memory, StreamBuffer& s : vk::DescriptorType::eUniformBuffer, .pBufferInfo = &buffer_infos.back(), }); + + if (buffer.is_storage) { + // In most of the cases we can skip the whole dispatch when meta is written + texture_cache.TouchMeta(addr, true); + } else { + if (texture_cache.IsMeta(addr)) { + LOG_WARNING(Render_Vulkan, "Unexpected meta data read by a CS shader"); + } + } } for (const auto& image : info.images) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 85a051f8a..70c574366 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -44,8 +44,6 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) { boost::container::static_vector color_attachments{}; - vk::RenderingAttachmentInfo depth_attachment{}; - u32 num_depth_attachments{}; for (auto col_buf_id = 0u; col_buf_id < Liverpool::NumColorBuffers; ++col_buf_id) { const auto& col_buf = regs.color_buffers[col_buf_id]; if (!col_buf) { @@ -55,13 +53,20 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) { const auto& hint = liverpool->last_cb_extent[col_buf_id]; const auto& image_view = texture_cache.RenderTarget(col_buf, hint); + const bool is_clear = texture_cache.IsMetaCleared(col_buf.CmaskAddress()); color_attachments.push_back({ .imageView = *image_view.image_view, .imageLayout = vk::ImageLayout::eGeneral, - .loadOp = vk::AttachmentLoadOp::eLoad, + .loadOp = is_clear ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad, .storeOp = vk::AttachmentStoreOp::eStore, + .clearValue = + is_clear ? LiverpoolToVK::ColorBufferClearValue(col_buf) : vk::ClearValue{}, }); + texture_cache.TouchMeta(col_buf.CmaskAddress(), false); } + + vk::RenderingAttachmentInfo depth_attachment{}; + u32 num_depth_attachments{}; if (pipeline->IsDepthEnabled() && regs.depth_buffer.Address() != 0) { const bool is_clear = regs.depth_render_control.depth_clear_enable; const auto& image_view =