You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
4.2KB

  1. #include "perf.h"
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #ifdef NANOVG_GLEW
  6. # include <GL/glew.h>
  7. #endif
  8. #include <GLFW/glfw3.h>
  9. #include "nanovg.h"
  10. #ifdef _MSC_VER
  11. #define snprintf _snprintf
  12. #else
  13. #include <iconv.h>
  14. #endif
  15. // timer query support
  16. #ifndef GL_ARB_timer_query
  17. #define GL_TIME_ELAPSED 0x88BF
  18. typedef void (APIENTRY *pfnGLGETQUERYOBJECTUI64V)(GLuint id, GLenum pname, GLuint64* params);
  19. pfnGLGETQUERYOBJECTUI64V glGetQueryObjectui64v = 0;
  20. #endif
  21. void initGPUTimer(struct GPUtimer* timer)
  22. {
  23. memset(timer, 0, sizeof(*timer));
  24. timer->supported = glfwExtensionSupported("GL_ARB_timer_query");
  25. if (timer->supported) {
  26. #ifndef GL_ARB_timer_query
  27. glGetQueryObjectui64v = (pfnGLGETQUERYOBJECTUI64V)glfwGetProcAddress("glGetQueryObjectui64v");
  28. if (!glGetQueryObjectui64v) {
  29. timer->supported = GL_FALSE;
  30. return;
  31. }
  32. #endif
  33. glGenQueries(GPU_QUERY_COUNT, timer->queries);
  34. }
  35. }
  36. void startGPUTimer(struct GPUtimer* timer)
  37. {
  38. if (!timer->supported)
  39. return;
  40. glBeginQuery(GL_TIME_ELAPSED, timer->queries[timer->cur % GPU_QUERY_COUNT] );
  41. timer->cur++;
  42. }
  43. int stopGPUTimer(struct GPUtimer* timer, float* times, int maxTimes)
  44. {
  45. GLint available = 1;
  46. int n = 0;
  47. if (!timer->supported)
  48. return 0;
  49. glEndQuery(GL_TIME_ELAPSED);
  50. while (available && timer->ret <= timer->cur) {
  51. // check for results if there are any
  52. glGetQueryObjectiv(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT_AVAILABLE, &available);
  53. if (available) {
  54. GLuint64 timeElapsed = 0;
  55. glGetQueryObjectui64v(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT, &timeElapsed);
  56. timer->ret++;
  57. if (n < maxTimes) {
  58. times[n] = (float)((double)timeElapsed * 1e-9);
  59. n++;
  60. }
  61. }
  62. }
  63. return n;
  64. }
  65. void initFPS(struct FPScounter* fps, int style, const char* name)
  66. {
  67. memset(fps, 0, sizeof(struct FPScounter));
  68. fps->style = style;
  69. strncpy(fps->name, name, sizeof(fps->name));
  70. fps->name[sizeof(fps->name)-1] = '\0';
  71. }
  72. void updateFPS(struct FPScounter* fps, float frameTime)
  73. {
  74. fps->head = (fps->head+1) % FPS_HISTORY_COUNT;
  75. fps->values[fps->head] = frameTime;
  76. }
  77. #define AVG_SIZE 20
  78. static float getAvg(struct FPScounter* fps)
  79. {
  80. int i, head = fps->head;
  81. float avg = 0;
  82. for (i = 0; i < AVG_SIZE; i++) {
  83. avg += fps->values[head];
  84. head = (head+FPS_HISTORY_COUNT-1) % FPS_HISTORY_COUNT;
  85. }
  86. return avg / (float)AVG_SIZE;
  87. }
  88. void renderFPS(struct NVGcontext* vg, float x, float y, struct FPScounter* fps)
  89. {
  90. int i;
  91. float avg, w, h;
  92. char str[64];
  93. avg = getAvg(fps);
  94. w = 200;
  95. h = 35;
  96. nvgBeginPath(vg);
  97. nvgRect(vg, x,y, w,h);
  98. nvgFillColor(vg, nvgRGBA(0,0,0,128));
  99. nvgFill(vg);
  100. nvgBeginPath(vg);
  101. nvgMoveTo(vg, x, y+h);
  102. if (fps->style == FPS_RENDER_FPS) {
  103. for (i = 0; i < FPS_HISTORY_COUNT; i++) {
  104. float v = 1.0f / (0.00001f + fps->values[(fps->head+i) % FPS_HISTORY_COUNT]);
  105. if (v > 80.0f) v = 80.0f;
  106. float vx = x + ((float)i/(FPS_HISTORY_COUNT-1)) * w;
  107. float vy = y + h - ((v / 80.0f) * h);
  108. nvgLineTo(vg, vx, vy);
  109. }
  110. } else {
  111. for (i = 0; i < FPS_HISTORY_COUNT; i++) {
  112. float v = fps->values[(fps->head+i) % FPS_HISTORY_COUNT] * 1000.0f;
  113. if (v > 20.0f) v = 20.0f;
  114. float vx = x + ((float)i/(FPS_HISTORY_COUNT-1)) * w;
  115. float vy = y + h - ((v / 20.0f) * h);
  116. nvgLineTo(vg, vx, vy);
  117. }
  118. }
  119. nvgLineTo(vg, x+w, y+h);
  120. nvgFillColor(vg, nvgRGBA(255,192,0,128));
  121. nvgFill(vg);
  122. nvgFontFace(vg, "sans");
  123. if (fps->name[0] != '\0') {
  124. nvgFontSize(vg, 14.0f);
  125. nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP);
  126. nvgFillColor(vg, nvgRGBA(240,240,240,192));
  127. nvgText(vg, x+3,y+1, fps->name, NULL);
  128. }
  129. if (fps->style == FPS_RENDER_FPS) {
  130. nvgFontSize(vg, 18.0f);
  131. nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP);
  132. nvgFillColor(vg, nvgRGBA(240,240,240,255));
  133. sprintf(str, "%.2f FPS", 1.0f / avg);
  134. nvgText(vg, x+w-3,y+1, str, NULL);
  135. nvgFontSize(vg, 15.0f);
  136. nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_BOTTOM);
  137. nvgFillColor(vg, nvgRGBA(240,240,240,160));
  138. sprintf(str, "%.2f ms", avg * 1000.0f);
  139. nvgText(vg, x+w-3,y+h-1, str, NULL);
  140. } else {
  141. nvgFontSize(vg, 18.0f);
  142. nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP);
  143. nvgFillColor(vg, nvgRGBA(240,240,240,255));
  144. sprintf(str, "%.2f ms", avg * 1000.0f);
  145. nvgText(vg, x+w-3,y+1, str, NULL);
  146. }
  147. }