mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-01-15 11:25:13 +00:00
renderer_vulkan: Render polygons using triangle fans. (#1969)
This commit is contained in:
parent
1bc27135e3
commit
38f1cc2652
|
@ -234,46 +234,22 @@ bool BufferCache::BindVertexBuffers(
|
|||
return has_step_rate;
|
||||
}
|
||||
|
||||
u32 BufferCache::BindIndexBuffer(bool& is_indexed, u32 index_offset) {
|
||||
// Emulate QuadList and Polygon primitive types with CPU made index buffer.
|
||||
void BufferCache::BindIndexBuffer(u32 index_offset) {
|
||||
const auto& regs = liverpool->regs;
|
||||
if (!is_indexed) {
|
||||
if (regs.primitive_type != AmdGpu::PrimitiveType::Polygon) {
|
||||
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::EmitPolygonToTriangleListIndices(data, regs.num_indices);
|
||||
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);
|
||||
}
|
||||
|
||||
// Figure out index type and size.
|
||||
const bool is_index16 =
|
||||
regs.index_buffer_type.index_type == AmdGpu::Liverpool::IndexType::Index16;
|
||||
const vk::IndexType index_type = is_index16 ? vk::IndexType::eUint16 : vk::IndexType::eUint32;
|
||||
const u32 index_size = is_index16 ? sizeof(u16) : sizeof(u32);
|
||||
VAddr index_address = regs.index_base_address.Address<VAddr>();
|
||||
index_address += index_offset * index_size;
|
||||
|
||||
if (regs.primitive_type == AmdGpu::PrimitiveType::Polygon) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
const VAddr index_address =
|
||||
regs.index_base_address.Address<VAddr>() + index_offset * 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);
|
||||
const auto cmdbuf = scheduler.CommandBuffer();
|
||||
cmdbuf.bindIndexBuffer(vk_buffer->Handle(), offset, index_type);
|
||||
return regs.num_indices;
|
||||
}
|
||||
|
||||
void BufferCache::InlineData(VAddr address, const void* value, u32 num_bytes, bool is_gds) {
|
||||
|
|
|
@ -83,7 +83,7 @@ public:
|
|||
const std::optional<Shader::Gcn::FetchShaderData>& fetch_shader);
|
||||
|
||||
/// Bind host index buffer for the current draw.
|
||||
u32 BindIndexBuffer(bool& is_indexed, u32 index_offset);
|
||||
void BindIndexBuffer(u32 index_offset);
|
||||
|
||||
/// Writes a value to GPU buffer.
|
||||
void InlineData(VAddr address, const void* value, u32 num_bytes, bool is_gds);
|
||||
|
|
|
@ -103,6 +103,7 @@ vk::PrimitiveTopology PrimitiveType(AmdGpu::PrimitiveType type) {
|
|||
case AmdGpu::PrimitiveType::TriangleList:
|
||||
return vk::PrimitiveTopology::eTriangleList;
|
||||
case AmdGpu::PrimitiveType::TriangleFan:
|
||||
case AmdGpu::PrimitiveType::Polygon:
|
||||
return vk::PrimitiveTopology::eTriangleFan;
|
||||
case AmdGpu::PrimitiveType::TriangleStrip:
|
||||
return vk::PrimitiveTopology::eTriangleStrip;
|
||||
|
@ -116,9 +117,6 @@ vk::PrimitiveTopology PrimitiveType(AmdGpu::PrimitiveType type) {
|
|||
return vk::PrimitiveTopology::eTriangleStripWithAdjacency;
|
||||
case AmdGpu::PrimitiveType::PatchPrimitive:
|
||||
return vk::PrimitiveTopology::ePatchList;
|
||||
case AmdGpu::PrimitiveType::Polygon:
|
||||
// Needs to generate index buffer on the fly.
|
||||
return vk::PrimitiveTopology::eTriangleList;
|
||||
case AmdGpu::PrimitiveType::QuadList:
|
||||
case AmdGpu::PrimitiveType::RectList:
|
||||
return vk::PrimitiveTopology::ePatchList;
|
||||
|
|
|
@ -70,15 +70,6 @@ vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color
|
|||
|
||||
vk::SampleCountFlagBits NumSamples(u32 num_samples, vk::SampleCountFlags supported_flags);
|
||||
|
||||
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;
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "video_core/renderer_vulkan/vk_shader_hle.h"
|
||||
#include "video_core/texture_cache/image_view.h"
|
||||
#include "video_core/texture_cache/texture_cache.h"
|
||||
#include "vk_rasterizer.h"
|
||||
|
||||
#ifdef MemoryBarrier
|
||||
#undef MemoryBarrier
|
||||
|
@ -252,7 +251,9 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
|
|||
const auto& vs_info = pipeline->GetStage(Shader::LogicalStage::Vertex);
|
||||
const auto& fetch_shader = pipeline->GetFetchShader();
|
||||
buffer_cache.BindVertexBuffers(vs_info, fetch_shader);
|
||||
const u32 num_indices = buffer_cache.BindIndexBuffer(is_indexed, index_offset);
|
||||
if (is_indexed) {
|
||||
buffer_cache.BindIndexBuffer(index_offset);
|
||||
}
|
||||
|
||||
BeginRendering(*pipeline, state);
|
||||
UpdateDynamicState(*pipeline);
|
||||
|
@ -263,10 +264,11 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
|
|||
cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline->Handle());
|
||||
|
||||
if (is_indexed) {
|
||||
cmdbuf.drawIndexed(num_indices, regs.num_instances.NumInstances(), 0, s32(vertex_offset),
|
||||
instance_offset);
|
||||
cmdbuf.drawIndexed(regs.num_indices, regs.num_instances.NumInstances(), 0,
|
||||
s32(vertex_offset), instance_offset);
|
||||
} else {
|
||||
cmdbuf.draw(num_indices, regs.num_instances.NumInstances(), vertex_offset, instance_offset);
|
||||
cmdbuf.draw(regs.num_indices, regs.num_instances.NumInstances(), vertex_offset,
|
||||
instance_offset);
|
||||
}
|
||||
|
||||
ResetBindings();
|
||||
|
@ -280,22 +282,12 @@ void Rasterizer::DrawIndirect(bool is_indexed, VAddr arg_address, u32 offset, u3
|
|||
return;
|
||||
}
|
||||
|
||||
const auto& regs = liverpool->regs;
|
||||
if (regs.primitive_type == AmdGpu::PrimitiveType::Polygon) {
|
||||
// We use a generated index buffer to convert 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, "Primitive type is not supported for indirect draw");
|
||||
return;
|
||||
}
|
||||
|
||||
const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline();
|
||||
if (!pipeline) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto state = PrepareRenderState(pipeline->GetMrtMask());
|
||||
|
||||
if (!BindResources(pipeline)) {
|
||||
return;
|
||||
}
|
||||
|
@ -303,7 +295,9 @@ void Rasterizer::DrawIndirect(bool is_indexed, VAddr arg_address, u32 offset, u3
|
|||
const auto& vs_info = pipeline->GetStage(Shader::LogicalStage::Vertex);
|
||||
const auto& fetch_shader = pipeline->GetFetchShader();
|
||||
buffer_cache.BindVertexBuffers(vs_info, fetch_shader);
|
||||
buffer_cache.BindIndexBuffer(is_indexed, 0);
|
||||
if (is_indexed) {
|
||||
buffer_cache.BindIndexBuffer(0);
|
||||
}
|
||||
|
||||
const auto& [buffer, base] =
|
||||
buffer_cache.ObtainBuffer(arg_address + offset, stride * max_count, false);
|
||||
|
|
Loading…
Reference in a new issue