diff --git a/rpcs3/Emu/RSX/Common/BufferUtils.cpp b/rpcs3/Emu/RSX/Common/BufferUtils.cpp index df77c36aa6..dd91475a5b 100644 --- a/rpcs3/Emu/RSX/Common/BufferUtils.cpp +++ b/rpcs3/Emu/RSX/Common/BufferUtils.cpp @@ -62,11 +62,13 @@ void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_ namespace { template -void uploadAsIt(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 &min_index, u32 &max_index) noexcept +void uploadAsIt(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 primitive_restart_index, u32 &min_index, u32 &max_index) noexcept { for (u32 i = 0; i < indexCount; ++i) { IndexType index = vm::ps3::_ref(address + i * sizeof(IndexType)); + if (is_primitive_restart_enabled && index == (IndexType)primitive_restart_index) + index = (IndexType)-1; (IndexType&)dst[i * sizeof(IndexType)] = index; if (is_primitive_restart_enabled && index == (IndexType)-1) // Cut continue; @@ -75,16 +77,25 @@ void uploadAsIt(char *dst, u32 address, size_t indexCount, bool is_primitive_res } } +// FIXME: expanded primitive type may not support primitive restart correctly + template -void expandIndexedTriangleFan(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 &min_index, u32 &max_index) noexcept +void expandIndexedTriangleFan(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 primitive_restart_index, u32 &min_index, u32 &max_index) noexcept { for (unsigned i = 0; i < indexCount - 2; i++) { IndexType index0 = vm::ps3::_ref(address); - (IndexType&)dst[(3 * i) * sizeof(IndexType)] = index0; + if (index0 == (IndexType)primitive_restart_index) + index0 = (IndexType)-1; IndexType index1 = vm::ps3::_ref(address + (i + 2 - 1) * sizeof(IndexType)); - (IndexType&)dst[(3 * i + 1) * sizeof(IndexType)] = index1; + if (index1 == (IndexType)primitive_restart_index) + index1 = (IndexType)-1; IndexType index2 = vm::ps3::_ref(address + (i + 2) * sizeof(IndexType)); + if (index2 == (IndexType)primitive_restart_index) + index2 = (IndexType)-1; + + (IndexType&)dst[(3 * i) * sizeof(IndexType)] = index0; + (IndexType&)dst[(3 * i + 1) * sizeof(IndexType)] = index1; (IndexType&)dst[(3 * i + 2) * sizeof(IndexType)] = index2; if (!is_primitive_restart_enabled || index0 != (IndexType)-1) // Cut @@ -106,20 +117,29 @@ void expandIndexedTriangleFan(char *dst, u32 address, size_t indexCount, bool is } template -void expandIndexedQuads(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 &min_index, u32 &max_index) noexcept +void expandIndexedQuads(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 primitive_restart_index, u32 &min_index, u32 &max_index) noexcept { for (unsigned i = 0; i < indexCount / 4; i++) { - // First triangle IndexType index0 = vm::ps3::_ref(address + 4 * i * sizeof(IndexType)); - (IndexType&)dst[(6 * i) * sizeof(IndexType)] = index0; + if (is_primitive_restart_enabled && index0 == (IndexType)primitive_restart_index) + index0 = (IndexType)-1; IndexType index1 = vm::ps3::_ref(address + (4 * i + 1) * sizeof(IndexType)); - (IndexType&)dst[(6 * i + 1) * sizeof(IndexType)] = index1; + if (is_primitive_restart_enabled && index1 == (IndexType)primitive_restart_index) + index1 = (IndexType)-1; IndexType index2 = vm::ps3::_ref(address + (4 * i + 2) * sizeof(IndexType)); + if (is_primitive_restart_enabled && index2 == (IndexType)primitive_restart_index) + index2 = (IndexType)-1; + IndexType index3 = vm::ps3::_ref(address + (4 * i + 3) * sizeof(IndexType)); + if (is_primitive_restart_enabled &&index3 == (IndexType)primitive_restart_index) + index3 = (IndexType)-1; + + // First triangle + (IndexType&)dst[(6 * i) * sizeof(IndexType)] = index0; + (IndexType&)dst[(6 * i + 1) * sizeof(IndexType)] = index1; (IndexType&)dst[(6 * i + 2) * sizeof(IndexType)] = index2; // Second triangle (IndexType&)dst[(6 * i + 3) * sizeof(IndexType)] = index2; - IndexType index3 = vm::ps3::_ref(address + (4 * i + 3) * sizeof(IndexType)); (IndexType&)dst[(6 * i + 4) * sizeof(IndexType)] = index3; (IndexType&)dst[(6 * i + 5) * sizeof(IndexType)] = index0; @@ -234,6 +254,7 @@ void write_index_array_data_to_buffer(char* dst, unsigned m_draw_mode, unsigned u32 base_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET]; u32 base_index = 0;//rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX]; bool is_primitive_restart_enabled = !!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE]; + u32 primitive_restart_index = rsx::method_registers[NV4097_SET_RESTART_INDEX]; switch (m_draw_mode) { @@ -248,10 +269,10 @@ void write_index_array_data_to_buffer(char* dst, unsigned m_draw_mode, unsigned switch (type) { case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: - uploadAsIt(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, min_index, max_index); + uploadAsIt(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index); return; case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: - uploadAsIt(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, min_index, max_index); + uploadAsIt(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index); return; } return; @@ -259,20 +280,20 @@ void write_index_array_data_to_buffer(char* dst, unsigned m_draw_mode, unsigned switch (type) { case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: - expandIndexedTriangleFan(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, min_index, max_index); + expandIndexedTriangleFan(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index); return; case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: - expandIndexedTriangleFan(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, min_index, max_index); + expandIndexedTriangleFan(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index); return; } case CELL_GCM_PRIMITIVE_QUADS: switch (type) { case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: - expandIndexedQuads(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, min_index, max_index); + expandIndexedQuads(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index); return; case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: - expandIndexedQuads(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, min_index, max_index); + expandIndexedQuads(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index); return; } }