mirror of https://github.com/PCSX2/pcsx2.git
GS: Add secondary vertex buffer for copy/modifying vertices.
Currently only used in HW renderer to fix vertices for provoking-first-vertex APIs.
This commit is contained in:
parent
14c7f959f5
commit
08ede10204
|
@ -125,6 +125,8 @@ GSState::~GSState()
|
|||
{
|
||||
if (m_vertex.buff)
|
||||
_aligned_free(m_vertex.buff);
|
||||
if (m_vertex.buff_copy)
|
||||
_aligned_free(m_vertex.buff_copy);
|
||||
if (m_index.buff)
|
||||
_aligned_free(m_index.buff);
|
||||
if (m_draw_vertex.buff)
|
||||
|
@ -2859,56 +2861,53 @@ void GSState::UpdateVertexKick()
|
|||
void GSState::GrowVertexBuffer()
|
||||
{
|
||||
const u32 maxcount = std::max<u32>(m_vertex.maxcount * 3 / 2, 10000);
|
||||
const u32 old_vertex_size = sizeof(GSVertex) * m_vertex.tail;
|
||||
const u32 new_vertex_size = sizeof(GSVertex) * maxcount;
|
||||
const u32 old_index_size = sizeof(u16) * m_index.tail;
|
||||
const u32 new_index_size = sizeof(u16) * maxcount * 6; // Worst case index list is a list of points with vs expansion, 6 indices per point
|
||||
|
||||
GSVertex* vertex = static_cast<GSVertex*>(_aligned_malloc(sizeof(GSVertex) * maxcount, 32));
|
||||
GSVertex* draw_vertex = static_cast<GSVertex*>(_aligned_malloc(sizeof(GSVertex) * maxcount, 32));
|
||||
// Worst case index list is a list of points with vs expansion, 6 indices per point
|
||||
u16* index = static_cast<u16*>(_aligned_malloc(sizeof(u16) * maxcount * 6, 32));
|
||||
u16* draw_index = static_cast<u16*>(_aligned_malloc(sizeof(u16) * maxcount * 6, 32));
|
||||
|
||||
if (!vertex || !index)
|
||||
// Structure describing buffers to reallocate
|
||||
struct AllocDesc
|
||||
{
|
||||
const u32 vert_byte_count = sizeof(GSVertex) * maxcount;
|
||||
const u32 idx_byte_count = sizeof(u16) * maxcount * 3;
|
||||
void** pbuff;
|
||||
u32 old_size;
|
||||
u32 new_size;
|
||||
};
|
||||
std::vector<AllocDesc> alloc_desc = {
|
||||
{reinterpret_cast<void**>(&m_vertex.buff), old_vertex_size, new_vertex_size},
|
||||
// discard contents of buff_copy by setting old_size = 0
|
||||
{reinterpret_cast<void**>(&m_vertex.buff_copy), 0, new_vertex_size},
|
||||
{reinterpret_cast<void**>(&m_draw_vertex.buff), old_vertex_size, new_vertex_size},
|
||||
{reinterpret_cast<void**>(&m_index.buff), old_index_size, new_index_size},
|
||||
{reinterpret_cast<void**>(&m_draw_index.buff), old_index_size, new_index_size}
|
||||
};
|
||||
|
||||
Console.Error("GS: failed to allocate %zu bytes for vertices and %zu for indices.",
|
||||
vert_byte_count, idx_byte_count);
|
||||
pxFailRel("Memory allocation failed");
|
||||
// For logging
|
||||
u32 total_size = 0;
|
||||
for (const auto& desc : alloc_desc)
|
||||
total_size += desc.new_size;
|
||||
|
||||
// Reallocate each of the needed buffers
|
||||
for (const auto [pbuff, old_size, new_size] : alloc_desc)
|
||||
{
|
||||
void* new_buff = _aligned_malloc(new_size, 32);
|
||||
if (!new_buff)
|
||||
{
|
||||
Console.Error("GS: failed to allocate %zu bytes for vertices and indices.", total_size);
|
||||
pxFailRel("Memory allocation failed");
|
||||
}
|
||||
if (*pbuff)
|
||||
{
|
||||
if (old_size)
|
||||
{
|
||||
std::memcpy(new_buff, *pbuff, old_size);
|
||||
}
|
||||
_aligned_free(*pbuff);
|
||||
}
|
||||
*pbuff = new_buff;
|
||||
}
|
||||
|
||||
if (m_vertex.buff)
|
||||
{
|
||||
std::memcpy(vertex, m_vertex.buff, sizeof(GSVertex) * m_vertex.tail);
|
||||
|
||||
_aligned_free(m_vertex.buff);
|
||||
}
|
||||
|
||||
if (m_index.buff)
|
||||
{
|
||||
std::memcpy(index, m_index.buff, sizeof(u16) * m_index.tail);
|
||||
|
||||
_aligned_free(m_index.buff);
|
||||
}
|
||||
|
||||
if (m_draw_vertex.buff)
|
||||
{
|
||||
std::memcpy(draw_vertex, m_draw_vertex.buff, sizeof(GSVertex) * m_vertex.tail);
|
||||
|
||||
_aligned_free(m_draw_vertex.buff);
|
||||
}
|
||||
|
||||
if (m_draw_index.buff)
|
||||
{
|
||||
std::memcpy(draw_index, m_draw_index.buff, sizeof(u16) * m_index.tail);
|
||||
|
||||
_aligned_free(m_draw_index.buff);
|
||||
}
|
||||
|
||||
m_draw_vertex.buff = draw_vertex;
|
||||
m_draw_index.buff = draw_index;
|
||||
m_vertex.buff = vertex;
|
||||
m_vertex.maxcount = maxcount - 3; // -3 to have some space at the end of the buffer before DrawingKick can grow it
|
||||
m_index.buff = index;
|
||||
}
|
||||
|
||||
bool GSState::TrianglesAreQuads(bool shuffle_check)
|
||||
|
|
|
@ -136,6 +136,7 @@ protected:
|
|||
struct
|
||||
{
|
||||
GSVertex* buff;
|
||||
GSVertex* buff_copy; // same size buffer to copy/modify the original buffer
|
||||
u32 head, tail, next, maxcount; // head: first vertex, tail: last vertex + 1, next: last indexed + 1
|
||||
u32 xy_tail;
|
||||
GSVector4i xy[4];
|
||||
|
|
|
@ -4834,34 +4834,15 @@ void GSRendererHW::HandleProvokingVertexFirst()
|
|||
if (first_eq_last)
|
||||
return;
|
||||
|
||||
// De-index the vertices either in place or by reallocating the vertex buffer.
|
||||
if (m_vertex.next <= m_index.tail && m_index.tail <= m_vertex.maxcount)
|
||||
// De-index the vertices using the copy buffer
|
||||
while (m_vertex.maxcount < m_index.tail)
|
||||
GrowVertexBuffer();
|
||||
for (int i = static_cast<int>(m_index.tail) - 1; i >= 0; i--)
|
||||
{
|
||||
// De-index in place
|
||||
for (int i = static_cast<int>(m_index.tail) - 1; i >= 0; i--)
|
||||
{
|
||||
// FIXME: This might not hold with a large triangle fan with gaps (since gaps are not
|
||||
// yet removed)!
|
||||
pxAssert(m_index.buff[i] <= i); // At any point, there can never be more vertices than indices
|
||||
m_vertex.buff[i] = m_vertex.buff[m_index.buff[i]];
|
||||
m_index.buff[i] = static_cast<u16>(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reallocate the vertex buffer
|
||||
m_vertex.maxcount = std::max(m_vertex.maxcount, m_index.tail);
|
||||
GSVertex* vert_buff = static_cast<GSVertex*>(_aligned_malloc(sizeof(GSVertex) * m_vertex.maxcount, 32));
|
||||
|
||||
// De-index and copy the vertices
|
||||
for (u32 i = 0; i < m_index.tail; i++)
|
||||
{
|
||||
vert_buff[i] = m_vertex.buff[m_index.buff[i]];
|
||||
m_index.buff[i] = static_cast<u16>(i);
|
||||
}
|
||||
std::swap(vert_buff, m_vertex.buff);
|
||||
_aligned_free(vert_buff);
|
||||
m_vertex.buff_copy[i] = m_vertex.buff[m_index.buff[i]];
|
||||
m_index.buff[i] = static_cast<u16>(i);
|
||||
}
|
||||
std::swap(m_vertex.buff, m_vertex.buff_copy);
|
||||
m_vertex.head = m_vertex.next = m_vertex.tail = m_index.tail;
|
||||
|
||||
// Put correct color in the first vertex
|
||||
|
|
Loading…
Reference in New Issue