diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 77b353c2..1f05b16c 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -236,7 +236,7 @@ bool BufferCache::BindVertexBuffers(const Shader::Info& vs_info) { u32 BufferCache::BindIndexBuffer(bool& is_indexed, u32 index_offset) { // Emulate QuadList primitive type with CPU made index buffer. const auto& regs = liverpool->regs; - if (regs.primitive_type == AmdGpu::PrimitiveType::QuadList) { + if (regs.primitive_type == AmdGpu::PrimitiveType::QuadList && !is_indexed) { is_indexed = true; // Emit indices. @@ -262,6 +262,32 @@ u32 BufferCache::BindIndexBuffer(bool& is_indexed, u32 index_offset) { VAddr index_address = regs.index_base_address.Address<VAddr>(); index_address += index_offset * index_size; + if (regs.primitive_type == AmdGpu::PrimitiveType::QuadList) { + // Convert indices. + const u32 new_index_size = regs.num_indices * index_size * 6 / 4; + const auto [data, offset] = stream_buffer.Map(new_index_size); + const auto index_ptr = reinterpret_cast<u8*>(index_address); + switch (index_type) { + case vk::IndexType::eUint16: + Vulkan::LiverpoolToVK::ConvertQuadToTriangleListIndices<u16>(data, index_ptr, + regs.num_indices); + break; + case vk::IndexType::eUint32: + Vulkan::LiverpoolToVK::ConvertQuadToTriangleListIndices<u32>(data, index_ptr, + regs.num_indices); + break; + default: + UNREACHABLE_MSG("Unsupported QuadList index type {}", vk::to_string(index_type)); + break; + } + stream_buffer.Commit(); + + // Bind index buffer. + const auto cmdbuf = scheduler.CommandBuffer(); + cmdbuf.bindIndexBuffer(stream_buffer.Handle(), offset, index_type); + return new_index_size / index_size; + } + // Bind index buffer. const u32 index_buffer_size = regs.num_indices * index_size; const auto [vk_buffer, offset] = ObtainBuffer(index_address, index_buffer_size, false); diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index 258e7f39..2262a429 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -726,19 +726,6 @@ vk::Format DepthFormat(DepthBuffer::ZFormat z_format, DepthBuffer::StencilFormat return format->vk_format; } -void EmitQuadToTriangleListIndices(u8* out_ptr, u32 num_vertices) { - static constexpr u16 NumVerticesPerQuad = 4; - u16* out_data = reinterpret_cast<u16*>(out_ptr); - for (u16 i = 0; i < num_vertices; i += NumVerticesPerQuad) { - *out_data++ = i; - *out_data++ = i + 1; - *out_data++ = i + 2; - *out_data++ = i; - *out_data++ = i + 2; - *out_data++ = i + 3; - } -} - vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color_buffer) { const auto comp_swap = color_buffer.info.comp_swap.Value(); const auto format = color_buffer.info.format.Value(); diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.h b/src/video_core/renderer_vulkan/liverpool_to_vk.h index 70e707fa..287ba691 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.h +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.h @@ -68,7 +68,33 @@ vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color vk::SampleCountFlagBits NumSamples(u32 num_samples, vk::SampleCountFlags supported_flags); -void EmitQuadToTriangleListIndices(u8* out_indices, u32 num_vertices); +static constexpr u16 NumVerticesPerQuad = 4; + +inline void EmitQuadToTriangleListIndices(u8* out_ptr, u32 num_vertices) { + u16* out_data = reinterpret_cast<u16*>(out_ptr); + for (u16 i = 0; i < num_vertices; i += NumVerticesPerQuad) { + *out_data++ = i; + *out_data++ = i + 1; + *out_data++ = i + 2; + *out_data++ = i; + *out_data++ = i + 2; + *out_data++ = i + 3; + } +} + +template <typename T> +void ConvertQuadToTriangleListIndices(u8* out_ptr, const u8* in_ptr, u32 num_vertices) { + T* out_data = reinterpret_cast<T*>(out_ptr); + const T* in_data = reinterpret_cast<const T*>(in_ptr); + for (u16 i = 0; i < num_vertices; i += NumVerticesPerQuad) { + *out_data++ = in_data[i]; + *out_data++ = in_data[i + 1]; + *out_data++ = in_data[i + 2]; + *out_data++ = in_data[i]; + *out_data++ = in_data[i + 2]; + *out_data++ = in_data[i + 3]; + } +} static inline vk::Format PromoteFormatToDepth(vk::Format fmt) { if (fmt == vk::Format::eR32Sfloat) {