From bec59756d407dcb1e0054b334d240d6dca49426d Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sun, 9 Jul 2017 20:15:03 -0700 Subject: [PATCH] Refactor vertex fetch optimizer and add more assertions We now range check indices in most algorithms and do some other sanity checks. Also analyzers now correctly handle empty meshes. --- src/overdrawoptimizer.cpp | 1 + src/vcacheanalyzer.cpp | 10 ++++++---- src/vcacheoptimizer.cpp | 6 +++++- src/vfetchanalyzer.cpp | 3 ++- src/vfetchoptimizer.cpp | 18 +++++++++++------- 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/overdrawoptimizer.cpp b/src/overdrawoptimizer.cpp index a3981cd9..96f83c40 100644 --- a/src/overdrawoptimizer.cpp +++ b/src/overdrawoptimizer.cpp @@ -168,6 +168,7 @@ static void generateSoftBoundaries(std::vector& destination, const { size_t start = clusters[it]; size_t end = (it + 1 < cluster_count) ? clusters[it + 1] : index_count / 3; + assert(start <= end); while (start != end) { diff --git a/src/vcacheanalyzer.cpp b/src/vcacheanalyzer.cpp index 26f0a487..9cd75461 100644 --- a/src/vcacheanalyzer.cpp +++ b/src/vcacheanalyzer.cpp @@ -1,6 +1,7 @@ // This file is part of meshoptimizer library; see meshoptimizer.hpp for version/license details #include "meshoptimizer.hpp" +#include #include namespace meshopt @@ -14,9 +15,10 @@ static VertexCacheStatistics analyzeVertexCacheImpl(const T* indices, size_t ind std::vector cache_time_stamps(vertex_count, 0); unsigned int time_stamp = cache_size + 1; - for (const T* indices_end = indices + index_count; indices != indices_end; ++indices) + for (size_t i = 0; i < index_count; ++i) { - T index = *indices; + T index = indices[i]; + assert(index < vertex_count); if (time_stamp - cache_time_stamps[index] > cache_size) { @@ -26,8 +28,8 @@ static VertexCacheStatistics analyzeVertexCacheImpl(const T* indices, size_t ind } } - result.acmr = float(result.vertices_transformed) / float(index_count / 3); - result.atvr = float(result.vertices_transformed) / float(vertex_count); + result.acmr = index_count == 0 ? 0 : float(result.vertices_transformed) / float(index_count / 3); + result.atvr = vertex_count == 0 ? 0 : float(result.vertices_transformed) / float(vertex_count); return result; } diff --git a/src/vcacheoptimizer.cpp b/src/vcacheoptimizer.cpp index b49e14c5..d610f05e 100644 --- a/src/vcacheoptimizer.cpp +++ b/src/vcacheoptimizer.cpp @@ -22,6 +22,8 @@ static void buildAdjacency(Adjacency& adjacency, const T* indices, size_t index_ for (size_t i = 0; i < index_count; ++i) { + assert(indices[i] < vertex_count); + adjacency.triangle_counts[indices[i]]++; } @@ -41,7 +43,9 @@ static void buildAdjacency(Adjacency& adjacency, const T* indices, size_t index_ std::vector filled_triangle_counts(vertex_count, 0); - for (size_t i = 0; i < index_count / 3; ++i) + size_t face_count = index_count / 3; + + for (size_t i = 0; i < face_count; ++i) { unsigned int a = indices[i * 3 + 0], b = indices[i * 3 + 1], c = indices[i * 3 + 2]; diff --git a/src/vfetchanalyzer.cpp b/src/vfetchanalyzer.cpp index 781dff43..ca215b96 100644 --- a/src/vfetchanalyzer.cpp +++ b/src/vfetchanalyzer.cpp @@ -21,6 +21,7 @@ static VertexFetchStatistics analyzeVertexFetchImpl(const T* indices, size_t ind for (size_t i = 0; i < index_count; ++i) { T index = indices[i]; + assert(index < vertex_count); size_t start_address = index * vertex_size; size_t end_address = start_address + vertex_size; @@ -40,7 +41,7 @@ static VertexFetchStatistics analyzeVertexFetchImpl(const T* indices, size_t ind } } - result.overfetch = float(result.bytes_fetched) / float(vertex_count * vertex_size); + result.overfetch = vertex_count == 0 ? 0 : float(result.bytes_fetched) / float(vertex_count * vertex_size); return result; } diff --git a/src/vfetchoptimizer.cpp b/src/vfetchoptimizer.cpp index 840a8b6c..cb4ac7a1 100644 --- a/src/vfetchoptimizer.cpp +++ b/src/vfetchoptimizer.cpp @@ -16,21 +16,25 @@ static void optimizeVertexFetchImpl(void* destination, const void* vertices, T* // build vertex remap table std::vector vertex_remap(vertex_count, static_cast(-1)); - size_t vertex = 0; + unsigned int vertex = 0; - for (T* indices_end = indices + index_count; indices != indices_end; ++indices) + for (size_t i = 0; i < index_count; ++i) { - unsigned int& index = vertex_remap[*indices]; + T index = indices[i]; + assert(index < vertex_count); - if (index == static_cast(-1)) // vertex was not added to destination VB + unsigned int& remap = vertex_remap[index]; + + if (remap == static_cast(-1)) // vertex was not added to destination VB { // add vertex - memcpy(static_cast(destination) + vertex * vertex_size, static_cast(vertices) + *indices * vertex_size, vertex_size); + memcpy(static_cast(destination) + vertex * vertex_size, static_cast(vertices) + index * vertex_size, vertex_size); - index = static_cast(vertex++); + remap = vertex++; } - *indices = static_cast(index); + // modify indices in place + indices[i] = static_cast(remap); } }