vcacheanalyzer.cpp 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
  2. #include "meshoptimizer.h"
  3. #include <assert.h>
  4. #include <string.h>
  5. meshopt_VertexCacheStatistics meshopt_analyzeVertexCache(const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size, unsigned int warp_size, unsigned int primgroup_size)
  6. {
  7. assert(index_count % 3 == 0);
  8. assert(cache_size >= 3);
  9. assert(warp_size == 0 || warp_size >= 3);
  10. meshopt_Allocator allocator;
  11. meshopt_VertexCacheStatistics result = {};
  12. unsigned int warp_offset = 0;
  13. unsigned int primgroup_offset = 0;
  14. unsigned int* cache_timestamps = allocator.allocate<unsigned int>(vertex_count);
  15. memset(cache_timestamps, 0, vertex_count * sizeof(unsigned int));
  16. unsigned int timestamp = cache_size + 1;
  17. for (size_t i = 0; i < index_count; i += 3)
  18. {
  19. unsigned int a = indices[i + 0], b = indices[i + 1], c = indices[i + 2];
  20. assert(a < vertex_count && b < vertex_count && c < vertex_count);
  21. bool ac = (timestamp - cache_timestamps[a]) > cache_size;
  22. bool bc = (timestamp - cache_timestamps[b]) > cache_size;
  23. bool cc = (timestamp - cache_timestamps[c]) > cache_size;
  24. // flush cache if triangle doesn't fit into warp or into the primitive buffer
  25. if ((primgroup_size && primgroup_offset == primgroup_size) || (warp_size && warp_offset + ac + bc + cc > warp_size))
  26. {
  27. result.warps_executed += warp_offset > 0;
  28. warp_offset = 0;
  29. primgroup_offset = 0;
  30. // reset cache
  31. timestamp += cache_size + 1;
  32. }
  33. // update cache and add vertices to warp
  34. for (int j = 0; j < 3; ++j)
  35. {
  36. unsigned int index = indices[i + j];
  37. if (timestamp - cache_timestamps[index] > cache_size)
  38. {
  39. cache_timestamps[index] = timestamp++;
  40. result.vertices_transformed++;
  41. warp_offset++;
  42. }
  43. }
  44. primgroup_offset++;
  45. }
  46. size_t unique_vertex_count = 0;
  47. for (size_t i = 0; i < vertex_count; ++i)
  48. unique_vertex_count += cache_timestamps[i] > 0;
  49. result.warps_executed += warp_offset > 0;
  50. result.acmr = index_count == 0 ? 0 : float(result.vertices_transformed) / float(index_count / 3);
  51. result.atvr = unique_vertex_count == 0 ? 0 : float(result.vertices_transformed) / float(unique_vertex_count);
  52. return result;
  53. }