From 09e2357d023de513d9e69b04a8476383972ad4a4 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Mon, 15 Mar 2021 01:03:45 -0700 Subject: [PATCH] nv2a: Cache inline elements in LRU --- hw/xbox/nv2a/debug.h | 1 + hw/xbox/nv2a/nv2a_int.h | 4 ++-- hw/xbox/nv2a/pgraph.c | 39 ++++++++++++++++++++++++++++++++++----- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/hw/xbox/nv2a/debug.h b/hw/xbox/nv2a/debug.h index 7b62d1816a..fde05ab2b8 100644 --- a/hw/xbox/nv2a/debug.h +++ b/hw/xbox/nv2a/debug.h @@ -113,6 +113,7 @@ void gl_debug_frame_terminator(void); _X(NV2A_PROF_GEOM_BUFFER_UPDATE_2) \ _X(NV2A_PROF_GEOM_BUFFER_UPDATE_3) \ _X(NV2A_PROF_GEOM_BUFFER_UPDATE_4) \ + _X(NV2A_PROF_GEOM_BUFFER_UPDATE_5) \ _X(NV2A_PROF_SURF_DOWNLOAD) \ _X(NV2A_PROF_SURF_UPLOAD) \ _X(NV2A_PROF_SURF_TO_TEX) \ diff --git a/hw/xbox/nv2a/nv2a_int.h b/hw/xbox/nv2a/nv2a_int.h index 33f3ebac51..ce106346a8 100644 --- a/hw/xbox/nv2a/nv2a_int.h +++ b/hw/xbox/nv2a/nv2a_int.h @@ -327,8 +327,9 @@ typedef struct PGRAPHState { VertexAttribute vertex_attributes[NV2A_VERTEXSHADER_ATTRIBUTES]; uint8_t *converted_buffer; - Lru vertex_cache; + Lru vertex_cache, element_cache; struct VertexLruNode *vertex_cache_entries; + struct VertexLruNode *element_cache_entries; unsigned int inline_array_length; uint32_t inline_array[NV2A_MAX_BATCH_LENGTH]; @@ -336,7 +337,6 @@ typedef struct PGRAPHState { unsigned int inline_elements_length; uint32_t inline_elements[NV2A_MAX_BATCH_LENGTH]; - GLuint gl_inline_elements_buffer; unsigned int inline_buffer_length; diff --git a/hw/xbox/nv2a/pgraph.c b/hw/xbox/nv2a/pgraph.c index 71e8445794..30d1368280 100644 --- a/hw/xbox/nv2a/pgraph.c +++ b/hw/xbox/nv2a/pgraph.c @@ -2381,10 +2381,25 @@ DEF_METHOD(NV097, SET_BEGIN_END) pgraph_bind_vertex_attributes(d, min_element, max_element, false, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pg->gl_inline_elements_buffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, - pg->inline_elements_length * sizeof(uint32_t), - pg->inline_elements, GL_STREAM_DRAW); + VertexKey k; + memset(&k, 0, sizeof(VertexKey)); + k.count = pg->inline_elements_length; + k.gl_type = GL_UNSIGNED_INT; + k.gl_normalize = GL_FALSE; + k.stride = sizeof(uint32_t); + uint64_t h = fast_hash((uint8_t*)pg->inline_elements, + pg->inline_elements_length * 4); + + LruNode *node = lru_lookup(&pg->element_cache, h, &k); + VertexLruNode *found = container_of(node, VertexLruNode, node); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, found->gl_buffer); + if (!found->initialized) { + nv2a_profile_inc_counter(NV2A_PROF_GEOM_BUFFER_UPDATE_5); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, + pg->inline_elements_length * 4, + pg->inline_elements, GL_STATIC_DRAW); + found->initialized = true; + } glDrawElements(pg->shader_binding->gl_primitive_mode, pg->inline_elements_length, GL_UNSIGNED_INT, (void *)0); @@ -3373,6 +3388,21 @@ void pgraph_init(NV2AState *d) pg->vertex_cache.init_node = vertex_cache_entry_init; pg->vertex_cache.compare_nodes = vertex_cache_entry_compare; + // Initialize element cache + const size_t element_cache_size = 50*1024; + lru_init(&pg->element_cache); + pg->element_cache_entries = malloc(element_cache_size * sizeof(VertexLruNode)); + assert(pg->element_cache_entries != NULL); + GLuint element_cache_buffers[element_cache_size]; + glGenBuffers(element_cache_size, element_cache_buffers); + for (i = 0; i < element_cache_size; i++) { + pg->element_cache_entries[i].gl_buffer = element_cache_buffers[i]; + lru_add_free(&pg->element_cache, &pg->element_cache_entries[i].node); + } + + pg->element_cache.init_node = vertex_cache_entry_init; + pg->element_cache.compare_nodes = vertex_cache_entry_compare; + pg->shader_cache = g_hash_table_new(shader_hash, shader_equal); for (i=0; iinline_buffer_populated = false; } glGenBuffers(1, &pg->gl_inline_array_buffer); - glGenBuffers(1, &pg->gl_inline_elements_buffer); glGenBuffers(1, &pg->gl_memory_buffer); glBindBuffer(GL_ARRAY_BUFFER, pg->gl_memory_buffer);