[Mesa-dev] [PATCH demos 2/3] Perf: Add test to measure texture upload

Courtney Goeltzenleuchter courtney at lunarg.com
Thu Nov 7 13:16:18 PST 2013


Needed test to measure texture upload speed under a variety
of modes (mipmap, source format, internal format, size, etc.)
This new test has an interactive run mode like the other Mesa
Perf tests but also includes command line options to make
it automatable.
Fix up code formatting.

Signed-off-by: Courtney Goeltzenleuchter <courtney at LunarG.com>
---
 src/perf/CMakeLists.txt        |   1 +
 src/perf/Makefile.am           |   1 +
 src/perf/bench_glTexImage2D.sh |  13 ++
 src/perf/teximage_enh.README   |  10 ++
 src/perf/teximage_enh.c        | 391 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 416 insertions(+)
 create mode 100755 src/perf/bench_glTexImage2D.sh
 create mode 100644 src/perf/teximage_enh.README
 create mode 100644 src/perf/teximage_enh.c

diff --git a/src/perf/CMakeLists.txt b/src/perf/CMakeLists.txt
index 68b6875..ded6666 100644
--- a/src/perf/CMakeLists.txt
+++ b/src/perf/CMakeLists.txt
@@ -28,6 +28,7 @@ set (targets
 	readpixels
 	swapbuffers
 	teximage
+	teximage_enh
 	vbo
 	vertexrate
 )
diff --git a/src/perf/Makefile.am b/src/perf/Makefile.am
index 5363c58..1cc5c43 100644
--- a/src/perf/Makefile.am
+++ b/src/perf/Makefile.am
@@ -51,6 +51,7 @@ bin_PROGRAMS = \
 	readpixels \
 	swapbuffers \
 	teximage \
+	teximage_enh \
 	vbo \
 	vertexrate \
 	glslstateschange
diff --git a/src/perf/bench_glTexImage2D.sh b/src/perf/bench_glTexImage2D.sh
new file mode 100755
index 0000000..c63a251
--- /dev/null
+++ b/src/perf/bench_glTexImage2D.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+./teximage_enh --width 1024 --height 1024 --type GL_UNSIGNED_BYTE --format GL_RGBA --texelsize 4 --internalformat GL_RGBA --csvstyle full --test TexImage
+./teximage_enh --width 1024 --height 1024 --type GL_UNSIGNED_BYTE --format GL_RGBA --texelsize 4 --internalformat GL_RGB --csvstyle data --test TexImage
+./teximage_enh --width  512 --height  512 --type GL_UNSIGNED_BYTE --format GL_RGBA --texelsize 4 --internalformat GL_RGBA --csvstyle data --test TexImage
+./teximage_enh --width  512 --height  512 --type GL_UNSIGNED_BYTE --format GL_RGBA --texelsize 4 --internalformat GL_RGB --csvstyle data --test TexImage
+./teximage_enh --width  256 --height  256 --type GL_UNSIGNED_BYTE --format GL_RGBA --texelsize 4 --internalformat GL_RGBA --csvstyle data --test TexImage
+./teximage_enh --width  256 --height  256 --type GL_UNSIGNED_BYTE --format GL_RGBA --texelsize 4 --internalformat GL_RGB --csvstyle data --test TexImage
+./teximage_enh --width 1024 --height 1024 --type GL_UNSIGNED_BYTE --format GL_RGBA --texelsize 4 --internalformat GL_RGBA --csvstyle data --test TexImage_Mipmap
+./teximage_enh --width 1024 --height 1024 --type GL_UNSIGNED_BYTE --format GL_RGBA --texelsize 4 --internalformat GL_RGB --csvstyle data --test TexImage_Mipmap
+./teximage_enh --width  512 --height  512 --type GL_UNSIGNED_BYTE --format GL_RGBA --texelsize 4 --internalformat GL_RGBA --csvstyle data --test TexImage_Mipmap
+./teximage_enh --width  512 --height  512 --type GL_UNSIGNED_BYTE --format GL_RGBA --texelsize 4 --internalformat GL_RGB --csvstyle data --test TexImage_Mipmap
+./teximage_enh --width  256 --height  256 --type GL_UNSIGNED_BYTE --format GL_RGBA --texelsize 4 --internalformat GL_RGBA --csvstyle data --test TexImage_Mipmap
+./teximage_enh --width  256 --height  256 --type GL_UNSIGNED_BYTE --format GL_RGBA --texelsize 4 --internalformat GL_RGB --csvstyle data --test TexImage_Mipmap
diff --git a/src/perf/teximage_enh.README b/src/perf/teximage_enh.README
new file mode 100644
index 0000000..44e8aea
--- /dev/null
+++ b/src/perf/teximage_enh.README
@@ -0,0 +1,10 @@
+glTexImage2D benchmark
+  - executable name:  teximage_enh
+  - modified files:  CMakeLists.txt  Makefile.am
+  - new files:
+     teximage_enh.c - code
+     bench_glTexImage2D.sh
+direct run command:  ./teximage_enh
+
+script usage:        ./test_glTexImage2D.sh
+
diff --git a/src/perf/teximage_enh.c b/src/perf/teximage_enh.c
new file mode 100644
index 0000000..9bb3944
--- /dev/null
+++ b/src/perf/teximage_enh.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Measure glTexImage2D() rate
+ *   enhanced from teximage.c by Brian Paul, 16 Sep 2009
+ *      2013 - Lisa Owens (lisa at lunarg.com)
+ *           - Courtney Goeltzenleuchter (courtney at lunarg.com)
+ */
+
+#include "glmain.h"
+#include "common.h"
+#include <stdio.h>
+#include <string.h>
+
+int WinWidth = 100, WinHeight = 100;
+
+/* for texture creation */
+static GLuint VBO;
+static GLuint TexObj = 0;
+static GLubyte *TexImage = NULL;
+
+enum {
+   MODE_CREATE_TEXIMAGE,
+   MODE_TEXIMAGE,
+   MODE_COUNT
+};
+
+static const char *mode_name[MODE_COUNT] ={
+   "Create_TexImage",
+   "TexImage",
+};
+
+struct vertex {
+   GLfloat x, y, s, t;
+};
+
+static const struct vertex vertices[1] = {
+   { 0.0, 0.0, 0.5, 0.5},
+};
+
+
+/** define some functions */
+GLenum parseType(char *);
+GLenum parseFormat(char *, int);
+void parseConfigFile(void);
+
+#define VOFFSET(F) ((void *) offsetof(struct vertex, F))
+
+/** defaults; config file options can be provided to set these */
+static const char *configFile = "teximage_enh.opts";
+GLint g_level = 1;
+GLsizei g_width = 256;
+GLsizei g_height = 256;
+GLuint g_texelsize = 4;
+GLenum g_texsrctype = GL_UNSIGNED_BYTE;
+GLenum g_texfmt = GL_RGB;
+GLenum g_texintfmt = 0;
+GLboolean g_drawpoint = GL_TRUE;
+char configName[2056];
+int formattype = 1;
+int intformattype = 2;
+char typeName[256] = "GL_UNSIGNED_BYTE";
+char formatName[256] = "GL_RGB";
+char internalformatName[256] = "GL_RGB";
+GLboolean g_verbose = GL_FALSE;
+GLboolean g_csvstyle = GL_FALSE;
+
+/** parse the type string */
+GLenum
+parseType(char *typestr)
+{
+   GLenum ogltype;
+
+   strcpy(typeName, typestr);
+   if (strcmp(typestr, "GL_UNSIGNED_BYTE") == 0) {
+      ogltype = GL_UNSIGNED_BYTE;
+   } else if (strcmp(typestr, "GL_BYTE") == 0) {
+      ogltype = GL_BYTE;
+   } else if (strcmp(typestr, "GL_BITMAP") == 0) {
+      ogltype = GL_BITMAP;
+   } else if (strcmp(typestr, "GL_UNSIGNED_SHORT") == 0) {
+      ogltype = GL_UNSIGNED_SHORT;
+   } else if (strcmp(typestr, "GL_SHORT") == 0) {
+      ogltype = GL_SHORT;
+   } else if (strcmp(typestr, "GL_UNSIGNED_INT") == 0) {
+      ogltype = GL_UNSIGNED_INT;
+   } else if (strcmp(typestr, "GL_INT") == 0) {
+      ogltype = GL_INT;
+   } else if (strcmp(typestr, "GL_FLOAT") == 0) {
+      ogltype = GL_FLOAT;
+   } else {
+      /* if we get here, type specified is invalid; use a default */
+      perf_printf("\n");
+      perf_printf("warning: type %s unknown; using GL_UNSIGNED_BYTE\n", typestr);
+      ogltype = GL_UNSIGNED_BYTE;
+      strcpy(typeName, "GL_UNSIGNED_BYTE");
+   }
+
+   return ogltype;
+}
+
+/** parse the format string */
+GLenum
+parseFormat(char *formatstr, int ftype)
+{
+   GLenum oglformat;
+
+   if (ftype == formattype) {
+      strcpy(formatName, formatstr);
+   } else {
+      strcpy(internalformatName, formatstr);
+   }
+
+   if (strcmp(formatstr, "GL_RGB") == 0) {
+      oglformat = GL_RGB;
+   } else if (strcmp(formatstr, "GL_RGBA") == 0) {
+      oglformat = GL_RGBA;
+   } else if (strcmp(formatstr, "GL_BGRA") == 0) {
+      oglformat = GL_BGRA;
+   } else if (strcmp(formatstr, "GL_LUMINANCE") == 0) {
+      oglformat = GL_LUMINANCE;
+   } else {
+      /* if we get here, format specified is invalid; use a default */
+      perf_printf("\n");
+      perf_printf("warning: format %s unknown; using GL_RGB\n", formatstr);
+      oglformat = GL_RGB;
+      if (ftype == formattype) {
+         strcpy(formatName, "GL_RGB");
+      } else {
+         strcpy(internalformatName, "GL_RGB");
+      }
+   }
+
+   return oglformat;
+}
+
+/** parse the args in the teximage_enh.opts file */
+void
+parseConfigFile(void)
+{
+   FILE *fp;
+   char *key, *value;
+   char *equal = "=";
+   char line[ 128];
+   int len;
+   int intval;
+
+   //perf_printf("parsing configuration file %s\n", configFile);
+   fp = fopen(configFile, "r");
+   if (!fp) {
+      perf_printf("%s file does not exist, using defaults\n", configFile);
+   } else {
+      while (fgets(line, sizeof line, fp) != NULL) {
+         //perf_printf("config file line read: %s\n", line);
+         /* TODO - better check for blank line */
+         if ((strncmp(line, "#", 1) == 0) || (line[0] == '\n')) {
+            /* comment or blank line, continue */
+            //perf_printf("found comment or blank line; continuing\n");
+            continue;
+         }
+
+         /* get the key and value */
+         key = strtok(line, equal);
+         value = strtok(NULL, equal);
+         intval = atoi(value);
+
+         /* remove line feed */
+         len = strlen(value);
+         if (value[len - 1] == '\n') {
+            value[len - 1] = 0;
+         }
+
+         /* parse the arguments and set options appropriately */
+         if (strcmp(key, "width") == 0) {
+            if (intval != 0) {
+               g_width = (GLsizei) intval;
+            }
+         } else if (strcmp(key, "height") == 0) {
+            if (intval != 0) {
+               g_height = (GLsizei) intval;
+            }
+         } else if (strcmp(key, "level") == 0) {
+            g_level = (GLint) intval;
+         } else if (strcmp(key, "drawpoint") == 0) {
+            /* default is true, so check for false */
+            if (strcmp(value, "false") == 0) {
+               g_drawpoint = GL_FALSE;
+            }
+         } else if (strcmp(key, "texelsize") == 0) {
+            if (intval != 0) {
+               g_texelsize = (GLuint) intval;
+            }
+         } else if (strcmp(key, "type") == 0) {
+            g_texsrctype = parseType(value);
+         } else if (strcmp(key, "format") == 0) {
+            g_texfmt = parseFormat(value, formattype);
+         } else if (strcmp(key, "internalformat") == 0) {
+            g_texintfmt = parseFormat(value, intformattype);
+         } else if (strcmp(key, "verbose") == 0) {
+            g_verbose = GL_TRUE;
+         } else if (strcmp(key, "csvstyle") == 0) {
+            g_csvstyle = GL_TRUE;
+         }
+      }
+      fclose(fp);
+   }
+
+   /* if internal format not provided, set to source format */
+   if (g_texintfmt == 0) {
+      g_texintfmt = g_texfmt;
+   }
+
+   /* generate config name for output */
+   sprintf(configName, "%s/%s/%s", formatName, internalformatName, typeName);
+   perf_printf("config name (fmt/intfmt/type): %s\n", configName);
+
+   /* print out values using for this test run */
+   if (g_verbose) {
+      perf_printf("running benchmark with the following options:\n");
+      perf_printf("   type: %s:%d\n", typeName, g_texsrctype);
+      perf_printf("   format: %s:%d\n", formatName, g_texfmt);
+      perf_printf("   internalformat: %s:%d\n", internalformatName, g_texintfmt);
+      perf_printf("   level: %d\n", g_level);
+      perf_printf("   width: %d\n", g_width);
+      perf_printf("   height: %d\n", g_height);
+      perf_printf("   texel size: %d\n", g_texelsize);
+      perf_printf("   draw point?: %d\n", g_drawpoint);
+   }
+
+   return;
+
+}
+
+/** Called from test harness/main */
+void
+PerfInit(void)
+{
+   /* setup VBO w/ vertex data */
+   glGenBuffersARB(1, &VBO);
+   glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
+   glBufferDataARB(GL_ARRAY_BUFFER_ARB,
+                   sizeof (vertices), vertices, GL_STATIC_DRAW_ARB);
+   glVertexPointer(2, GL_FLOAT, sizeof (struct vertex), VOFFSET(x));
+   glTexCoordPointer(2, GL_FLOAT, sizeof (struct vertex), VOFFSET(s));
+   glEnableClientState(GL_VERTEX_ARRAY);
+   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+   /* texture */
+   glGenTextures(1, &TexObj);
+   glBindTexture(GL_TEXTURE_2D, TexObj);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+   glEnable(GL_TEXTURE_2D);
+
+   /* parse config file */
+   parseConfigFile();
+}
+
+static void
+CreateUploadTexImage2D(unsigned count)
+{
+   unsigned i;
+
+   if (g_verbose) {
+      perf_printf("CreateUploadTexImage2D count: %d\n", count);
+   }
+
+   for (i = 0; i < count; i++) {
+      if (TexObj)
+         glDeleteTextures(1, &TexObj);
+
+      glGenTextures(1, &TexObj);
+      glBindTexture(GL_TEXTURE_2D, TexObj);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+      glTexImage2D(GL_TEXTURE_2D, g_level, g_texintfmt,
+                   g_width, g_height, 0,
+                   g_texfmt, g_texsrctype, TexImage);
+
+      if (g_drawpoint)
+         glDrawArrays(GL_POINTS, 0, 1);
+   }
+   glFinish();
+}
+
+static void
+UploadTexImage2D(unsigned count)
+{
+   unsigned i;
+
+   if (g_verbose) {
+      perf_printf("UploadTexImage2D count: %d\n", count);
+   }
+
+   for (i = 0; i < count; i++) {
+      glTexImage2D(GL_TEXTURE_2D, g_level, g_texintfmt,
+                   g_width, g_height, 0,
+                   g_texfmt, g_texsrctype, TexImage);
+      if (g_drawpoint)
+         glDrawArrays(GL_POINTS, 0, 1);
+   }
+   glFinish();
+}
+
+/** Called from test harness/main */
+void
+PerfNextRound(void)
+{
+}
+
+/** Called from test harness/main */
+void
+PerfDraw(void)
+{
+   GLint maxSize;
+   double rate;
+   GLint mode;
+   double mbPerSec;
+   GLint bytesPerImage;
+
+   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
+   /* TODO - check for max size exceeded?? */
+
+   /* loop over glTexImage */
+   perf_printf("\n");
+   for (mode = 0; mode < MODE_COUNT; mode++) {
+
+      bytesPerImage = g_width * g_height * g_texelsize;
+      TexImage = malloc(bytesPerImage);
+
+      switch (mode) {
+      case MODE_TEXIMAGE:
+         rate = PerfMeasureRate(UploadTexImage2D);
+         break;
+
+      case MODE_CREATE_TEXIMAGE:
+         rate = PerfMeasureRate(CreateUploadTexImage2D);
+         break;
+
+      default:
+         exit(1);
+      }
+
+      mbPerSec = rate * bytesPerImage / (1024.0 * 1024.0);
+      free(TexImage);
+
+      {
+         unsigned err;
+         err = glGetError();
+         if (err) {
+            perf_printf("non-zero glGetError() %d\n", err);
+            exit(1);
+         }
+      }
+
+      if (g_csvstyle) {
+         perf_printf("%s, %s, %s, %s, %s, %s, %s, %s, %s, %s\n",
+                     "width", "height", "level", "type", "texelsize", "format",
+                     "internalformat", "images/sec", "MB/sec", "MT/sec");
+         perf_printf("%d, %d, %d, %s, %d, %s, %s, %.1f, %.1f\n",
+                     g_width, g_height, g_level, typeName, g_texelsize, formatName,
+                     internalformatName, rate, mbPerSec);
+      } else {
+         perf_printf("%s(%s %dx%d): " "%.1f images/sec, %.1f MB/sec\n",
+                     mode_name[mode],
+                     configName, g_width, g_height, rate, mbPerSec);
+      }
+   }
+
+   exit(0);
+}
-- 
1.8.1.2



More information about the mesa-dev mailing list