@ -206,18 +206,42 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
std : : map < u32 , u32 > ranges ;
} memory_accesses ;
// Simple circular-replacement vertex cache
// The size has been tuned for optimal balance between hit-rate and the cost of lookup
const size_t VERTEX_CACHE_SIZE = 32 ;
std : : array < u16 , VERTEX_CACHE_SIZE > vertex_cache_ids ;
std : : array < VertexShader : : OutputVertex , VERTEX_CACHE_SIZE > vertex_cache ;
unsigned int vertex_cache_pos = 0 ;
vertex_cache_ids . fill ( - 1 ) ;
for ( unsigned int index = 0 ; index < regs . num_vertices ; + + index )
{
unsigned int vertex = is_indexed ? ( index_u16 ? index_address_16 [ index ] : index_address_8 [ index ] ) : index ;
// -1 is a common special value used for primitive restart. Since it's unknown if
// the PICA supports it, and it would mess up the caching, guard against it here.
ASSERT ( vertex ! = - 1 ) ;
bool vertex_cache_hit = false ;
VertexShader : : OutputVertex output ;
if ( is_indexed ) {
// TODO: Implement some sort of vertex cache!
if ( g_debug_context & & Pica : : g_debug_context - > recorder ) {
int size = index_u16 ? 2 : 1 ;
memory_accesses . AddAccess ( base_address + index_info . offset + size * index , size ) ;
}
for ( unsigned int i = 0 ; i < VERTEX_CACHE_SIZE ; + + i ) {
if ( vertex = = vertex_cache_ids [ i ] ) {
output = vertex_cache [ i ] ;
vertex_cache_hit = true ;
break ;
}
}
}
if ( ! vertex_cache_hit ) {
// Initialize data for the current vertex
VertexShader : : InputVertex input ;
@ -262,9 +286,9 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
input . attr [ i ] [ 0 ] . ToFloat32 ( ) , input . attr [ i ] [ 1 ] . ToFloat32 ( ) ,
input . attr [ i ] [ 2 ] . ToFloat32 ( ) , input . attr [ i ] [ 3 ] . ToFloat32 ( ) ) ;
} else {
// TODO(yuriks): In this case, no data gets loaded and the vertex remains
// with the last value it had. This isn't currently maintained
// as global state, however, and so won't work in Cita yet.
// TODO(yuriks): In this case, no data gets loaded and the vertex
// remains with the last value it had. This isn't currently maintained
// as global state, however, and so won't work in Citr a yet.
}
}
@ -284,10 +308,13 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
# endif
// Send to vertex shader
VertexShader : : OutputVertex output = VertexShader : : RunShader ( input , attribute_config . GetNumTotalAttributes ( ) , g_state . regs . vs , g_state . vs ) ;
output = VertexShader : : RunShader ( input , attribute_config . GetNumTotalAttributes ( ) , g_state . regs . vs , g_state . vs ) ;
if ( is_indexed ) {
// TODO: Add processed vertex to vertex cache!
vertex_cache [ vertex_cache_pos ] = output ;
vertex_cache_ids [ vertex_cache_pos ] = vertex ;
vertex_cache_pos = ( vertex_cache_pos + 1 ) % VERTEX_CACHE_SIZE ;
}
}
if ( Settings : : values . use_hw_renderer ) {