Merge pull request #1015 from yuriks/vertex-caching
Videocore: Implement simple vertex caching
This commit is contained in:
		| @@ -206,18 +206,42 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||||||
|                 std::map<u32, u32> ranges; |                 std::map<u32, u32> ranges; | ||||||
|             } memory_accesses; |             } 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) |             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; |                 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) { |                 if (is_indexed) { | ||||||
|                     // TODO: Implement some sort of vertex cache! |  | ||||||
|                     if (g_debug_context && Pica::g_debug_context->recorder) { |                     if (g_debug_context && Pica::g_debug_context->recorder) { | ||||||
|                         int size = index_u16 ? 2 : 1; |                         int size = index_u16 ? 2 : 1; | ||||||
|                         memory_accesses.AddAccess(base_address + index_info.offset + size * index, size); |                         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 |                     // Initialize data for the current vertex | ||||||
|                     VertexShader::InputVertex input; |                     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][0].ToFloat32(), input.attr[i][1].ToFloat32(), | ||||||
|                                       input.attr[i][2].ToFloat32(), input.attr[i][3].ToFloat32()); |                                       input.attr[i][2].ToFloat32(), input.attr[i][3].ToFloat32()); | ||||||
|                         } else { |                         } else { | ||||||
|                         // TODO(yuriks): In this case, no data gets loaded and the vertex remains |                             // TODO(yuriks): In this case, no data gets loaded and the vertex | ||||||
|                         //              with the last value it had. This isn't currently maintained |                             // remains with the last value it had. This isn't currently maintained | ||||||
|                         //              as global state, however, and so won't work in Cita yet. |                             // as global state, however, and so won't work in Citra yet. | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
| @@ -284,10 +308,13 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|                     // Send to vertex shader |                     // 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) { |                     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) { |                 if (Settings::values.use_hw_renderer) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user