From 8d8bb050554b6c95042dd9462e744055dd35cf8c Mon Sep 17 00:00:00 2001 From: "Daniel R." <47796739+polybiusproxy@users.noreply.github.com> Date: Sat, 21 Dec 2024 10:20:24 +0100 Subject: [PATCH] renderer_vulkan: add support for Polygon draws (#1798) --- src/video_core/buffer_cache/buffer_cache.cpp | 36 +++++++++++++++---- .../renderer_vulkan/liverpool_to_vk.cpp | 1 + .../renderer_vulkan/liverpool_to_vk.h | 9 +++++ .../renderer_vulkan/vk_rasterizer.cpp | 7 ++-- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index e9fc0649..f265fb68 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -235,25 +235,44 @@ bool BufferCache::BindVertexBuffers( } u32 BufferCache::BindIndexBuffer(bool& is_indexed, u32 index_offset) { - // Emulate QuadList primitive type with CPU made index buffer. + // Emulate QuadList and Polygon primitive types with CPU made index buffer. const auto& regs = liverpool->regs; - if (regs.primitive_type == AmdGpu::PrimitiveType::QuadList && !is_indexed) { - is_indexed = true; + if (!is_indexed) { + bool needs_index_buffer = false; + if (regs.primitive_type == AmdGpu::PrimitiveType::QuadList || + regs.primitive_type == AmdGpu::PrimitiveType::Polygon) { + needs_index_buffer = true; + } + + if (!needs_index_buffer) { + return regs.num_indices; + } // Emit indices. const u32 index_size = 3 * regs.num_indices; const auto [data, offset] = stream_buffer.Map(index_size); - Vulkan::LiverpoolToVK::EmitQuadToTriangleListIndices(data, regs.num_indices); + + switch (regs.primitive_type) { + case AmdGpu::PrimitiveType::QuadList: + Vulkan::LiverpoolToVK::EmitQuadToTriangleListIndices(data, regs.num_indices); + break; + case AmdGpu::PrimitiveType::Polygon: + Vulkan::LiverpoolToVK::EmitPolygonToTriangleListIndices(data, regs.num_indices); + break; + default: + UNREACHABLE(); + break; + } + stream_buffer.Commit(); // Bind index buffer. + is_indexed = true; + const auto cmdbuf = scheduler.CommandBuffer(); cmdbuf.bindIndexBuffer(stream_buffer.Handle(), offset, vk::IndexType::eUint16); return index_size / sizeof(u16); } - if (!is_indexed) { - return regs.num_indices; - } // Figure out index type and size. const bool is_index16 = @@ -288,6 +307,9 @@ u32 BufferCache::BindIndexBuffer(bool& is_indexed, u32 index_offset) { cmdbuf.bindIndexBuffer(stream_buffer.Handle(), offset, index_type); return new_index_size / index_size; } + if (regs.primitive_type == AmdGpu::PrimitiveType::Polygon) { + UNREACHABLE(); + } // Bind index buffer. const u32 index_buffer_size = regs.num_indices * index_size; diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index ec0bb3bb..6df89dba 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -117,6 +117,7 @@ vk::PrimitiveTopology PrimitiveType(AmdGpu::PrimitiveType type) { case AmdGpu::PrimitiveType::PatchPrimitive: return vk::PrimitiveTopology::ePatchList; case AmdGpu::PrimitiveType::QuadList: + case AmdGpu::PrimitiveType::Polygon: // Needs to generate index buffer on the fly. return vk::PrimitiveTopology::eTriangleList; case AmdGpu::PrimitiveType::RectList: diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.h b/src/video_core/renderer_vulkan/liverpool_to_vk.h index ebd09f0e..72bddc6b 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.h +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.h @@ -98,6 +98,15 @@ void ConvertQuadToTriangleListIndices(u8* out_ptr, const u8* in_ptr, u32 num_ver } } +inline void EmitPolygonToTriangleListIndices(u8* out_ptr, u32 num_vertices) { + u16* out_data = reinterpret_cast(out_ptr); + for (u16 i = 1; i < num_vertices - 1; i++) { + *out_data++ = 0; + *out_data++ = i; + *out_data++ = i + 1; + } +} + static inline vk::Format PromoteFormatToDepth(vk::Format fmt) { if (fmt == vk::Format::eR32Sfloat) { return vk::Format::eD32Sfloat; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index bd8906f8..df05b73a 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -246,11 +246,12 @@ void Rasterizer::DrawIndirect(bool is_indexed, VAddr arg_address, u32 offset, u3 } const auto& regs = liverpool->regs; - if (regs.primitive_type == AmdGpu::PrimitiveType::QuadList) { - // For QuadList we use generated index buffer to convert quads to triangles. Since it + if (regs.primitive_type == AmdGpu::PrimitiveType::QuadList || + regs.primitive_type == AmdGpu::PrimitiveType::Polygon) { + // We use a generated index buffer to convert quad lists and polygons to triangles. Since it // changes type of the draw, arguments are not valid for this case. We need to run a // conversion pass to repack the indirect arguments buffer first. - LOG_WARNING(Render_Vulkan, "QuadList primitive type is not supported for indirect draw"); + LOG_WARNING(Render_Vulkan, "Primitive type is not supported for indirect draw"); return; }