Skip to content

Commit

Permalink
renderer_vulkan: add support for Polygon draws (shadps4-emu#1798)
Browse files Browse the repository at this point in the history
  • Loading branch information
polybiusproxy authored Dec 21, 2024
1 parent 39fed1f commit 8d8bb05
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 10 deletions.
36 changes: 29 additions & 7 deletions src/video_core/buffer_cache/buffer_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/video_core/renderer_vulkan/liverpool_to_vk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
9 changes: 9 additions & 0 deletions src/video_core/renderer_vulkan/liverpool_to_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<u16*>(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;
Expand Down
7 changes: 4 additions & 3 deletions src/video_core/renderer_vulkan/vk_rasterizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down

0 comments on commit 8d8bb05

Please sign in to comment.