test glReadPixels speed w/ various formats/types, PBOs
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 14 Apr 2006 16:20:55 +0000 (16:20 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 14 Apr 2006 16:20:55 +0000 (16:20 +0000)
progs/tests/Makefile
progs/tests/readrate.c [new file with mode: 0644]

index 0800c5794d0d4431f846b5da32f87861e77c4f0b..47740c5485c8793ff0332e6b51601da450156837 100644 (file)
@@ -34,6 +34,7 @@ SOURCES = \
        dinoshade.c \
        floattex.c \
        fbotest1.c \
+       fbotest2.c \
        fbotexture.c \
        fog.c \
        fogcoord.c \
@@ -49,6 +50,7 @@ SOURCES = \
        packedpixels.c \
        pbo.c \
        projtex.c \
+       readrate.c \
        seccolor.c \
        sharedtex.c \
        stencilwrap.c \
diff --git a/progs/tests/readrate.c b/progs/tests/readrate.c
new file mode 100644 (file)
index 0000000..42ae62d
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * Test glReadPixels speed
+ * Brian Paul
+ * 9 April 2004
+ *
+ * Compile:
+ * gcc readrate.c -L/usr/X11R6/lib -lglut -lGLU -lGL -lX11 -o readrate
+ */
+
+#define GL_GLEXT_PROTOTYPES
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <GL/glut.h>
+
+/* Hack, to test drawing instead of reading */
+#define DRAW 0
+
+#define MAX_WIDTH 1280
+#define MAX_HEIGHT 1024
+
+#define NUM_WIDTHS 4
+#define NUM_HEIGHTS 4
+static const GLint Widths[] = {256, 512, 1024, 1280};
+static const GLint Heights[] = {4, 32, 256, 512, 768, 1024};
+static int WidthIndex = 1, HeightIndex = 3;
+static GLubyte *Buffer = NULL;
+static GLboolean Benchmark = GL_TRUE;
+
+#define NUM_PBO 2
+
+static GLuint PBObjects[4];
+
+static GLboolean HavePBO = GL_FALSE;
+
+
+struct format_type {
+   const char *Name;
+   GLuint Bytes;
+   GLenum Format;
+   GLenum Type;
+};
+
+static struct format_type Formats[] = {
+   { "GL_RGB, GLubyte", 3, GL_RGB, GL_UNSIGNED_BYTE },
+   { "GL_BGR, GLubyte", 3, GL_BGR, GL_UNSIGNED_BYTE },
+   { "GL_RGBA, GLubyte", 4, GL_RGBA, GL_UNSIGNED_BYTE },
+   { "GL_BGRA, GLubyte", 4, GL_BGRA, GL_UNSIGNED_BYTE },
+   { "GL_ABGR, GLubyte", 4, GL_ABGR_EXT, GL_UNSIGNED_BYTE },
+   { "GL_RGBA, GLuint_8_8_8_8", 4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8 },
+   { "GL_BGRA, GLuint_8_8_8_8", 4, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8 },
+   { "GL_BGRA, GLuint_8_8_8_8_rev", 4, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV },
+#ifdef GL_EXT_packed_depth_stencil
+   { "GL_DEPTH_STENCIL_EXT, GLuint24+8", 4, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT },
+#endif
+   { "GL_DEPTH_COMPONENT, GLfloat", 4, GL_DEPTH_COMPONENT, GL_FLOAT },
+   { "GL_DEPTH_COMPONENT, GLuint", 4, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }
+};
+
+#define NUM_FORMATS (sizeof(Formats) / sizeof(struct format_type))
+
+
+static void
+PrintString(const char *s)
+{
+   while (*s) {
+      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
+      s++;
+   }
+}
+
+
+static void
+MeasureFormat(struct format_type *fmt, GLint width, GLint height, GLuint pbo)
+{
+   double t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
+   double t1;
+   int j;
+
+   for (j = 0; ; j++) {
+
+      glBegin(GL_POINTS);
+      glVertex2f(1,1);
+      glEnd();
+
+#if DRAW
+      glWindowPos2iARB(0,0);
+      glDrawPixels(width, height,
+                   fmt->Format, fmt->Type, Buffer);
+      glFinish();
+#else
+      if (pbo) {
+         glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, PBObjects[j % NUM_PBO]);
+         glReadPixels(0, 0, width, height,
+                      fmt->Format, fmt->Type, 0);
+      }
+      else {
+         glReadPixels(0, 0, width, height,
+                      fmt->Format, fmt->Type, Buffer);
+      }
+#endif
+
+      t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
+      if (t1 - t0 > 2.0) {
+         GLdouble rate = width * height / (1024.0 * 1024.0) * j / (t1 - t0);
+#if DRAW
+         printf("%-32s  %.2f draws/sec %.2f MPixels/sec  %.2f MBytes/sec\n",
+                fmt->Name, j / (t1-t0), rate, rate * fmt->Bytes);
+#else
+         printf("%-32s  %.2f reads/sec %.2f MPixels/sec  %.2f MBytes/sec\n",
+                fmt->Name, j / (t1-t0), rate, rate * fmt->Bytes);
+#endif
+         break;
+      }
+
+      if (j == 0) {
+         /* check for error */
+         GLenum err = glGetError();
+         if (err) {
+            printf("GL Error 0x%x for %s\n", err, fmt->Name);
+            return;
+         }
+      }
+   }
+}
+
+
+
+static void
+Draw(void)
+{
+   char str[1000];
+   int width = Widths[WidthIndex];
+   int height = Heights[HeightIndex];
+   int y = MAX_HEIGHT - 50;
+
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glWindowPos2iARB(10, y);
+   sprintf(str, "ReadPixels size: %d x %d", width, height);
+   PrintString(str);
+   y -= 14;
+
+   glWindowPos2iARB(10, y);
+   PrintString("Press up/down/left/right to change image size.");
+   y -= 14;
+
+   glWindowPos2iARB(10, y);
+   PrintString("Press 'b' to run benchmark test.");
+   y -= 14;
+
+   if (Benchmark) {
+      glWindowPos2iARB(10, y);
+      PrintString("Testing...");
+   }
+
+   glutSwapBuffers();
+
+   if (Benchmark) {
+      GLuint i, pbo;
+#if DRAW
+      printf("Draw size: Width=%d Height=%d\n", width, height);
+#else
+      printf("Read size: Width=%d Height=%d\n", width, height);
+#endif
+      for (pbo = 0; pbo <= HavePBO; pbo++) {
+         printf("Pixel Buffer Object: %d\n", pbo);
+
+         if (pbo == 0) {
+            glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0);
+         }
+
+         for (i = 0; i < NUM_FORMATS; i++) {
+            MeasureFormat(Formats + i, width, height, pbo);
+         }
+      }
+
+      Benchmark = GL_FALSE;
+
+      /* redraw window text */
+      glutPostRedisplay();
+   }
+
+}
+
+
+static void
+Reshape(int width, int height)
+{
+   glViewport(0, 0, width, height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(-1, 1, -1, 1, -1, 1);
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+}
+
+
+static void
+Key(unsigned char key, int x, int y)
+{
+   (void) x;
+   (void) y;
+   switch (key) {
+      case 'b':
+         Benchmark = 1;
+         break;
+      case 27:
+         exit(0);
+         break;
+   }
+   glutPostRedisplay();
+}
+
+
+static void
+SpecialKey(int key, int x, int y)
+{
+   (void) x;
+   (void) y;
+   switch (key) {
+      case GLUT_KEY_UP:
+         if (HeightIndex + 1 < NUM_WIDTHS)
+            HeightIndex++;
+         break;
+      case GLUT_KEY_DOWN:
+         if (HeightIndex > 0)
+            HeightIndex--;
+         break;
+      case GLUT_KEY_LEFT:
+         if (WidthIndex > 0)
+            WidthIndex--;
+         break;
+      case GLUT_KEY_RIGHT:
+         if (WidthIndex + 1 < NUM_HEIGHTS)
+            WidthIndex++;
+         break;
+   }
+   glutPostRedisplay();
+}
+
+
+static void
+Init(void)
+{
+   Buffer = malloc(MAX_WIDTH * MAX_HEIGHT * 4);
+   assert(Buffer);
+#if DRAW
+   printf("glDrawPixels test report:\n");
+#else
+   printf("glReadPixels test report:\n");
+#endif
+   printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
+   printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
+
+   if (glutExtensionSupported("GL_ARB_pixel_buffer_object")) {
+      int i;
+      HavePBO = 1;
+      glGenBuffersARB(NUM_PBO, PBObjects);
+      for (i = 0; i < NUM_PBO; i++) {
+         glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, PBObjects[i]);
+         glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT,
+                         MAX_WIDTH * MAX_HEIGHT * 4, NULL, GL_STREAM_READ);
+      }
+   }
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   glutInit(&argc, argv);
+   glutInitWindowPosition(0, 0);
+   glutInitWindowSize(MAX_WIDTH, MAX_HEIGHT);
+   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
+   glutCreateWindow(argv[0]);
+   glutReshapeFunc(Reshape);
+   glutKeyboardFunc(Key);
+   glutSpecialFunc(SpecialKey);
+   glutDisplayFunc(Draw);
+   Init();
+   glutMainLoop();
+   return 0;
+}