[Mesa-dev] [PATCH demos v2 2/3] perf: Update teximage to measure more formats

Brian Paul brianp at vmware.com
Tue Nov 12 09:33:42 PST 2013


Looks good, just some minor clean-up suggestions below.

For patch 3, the idea of using loops sounds good.

Otherwise, Reviewed-by: Brian Paul <brianp at vmware.com>

-Brian

On 11/11/2013 05:53 PM, Courtney Goeltzenleuchter wrote:
> 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.
> Integrate review feedback.
>
> This provides a quick way to get feedback on texture upload
> related performance tuning.
> Texture image data is initialized and aligned to 64 byte bounary.
> Uses Mesa demos Perf library to do the measurements.
>
> Signed-off-by: Courtney Goeltzenleuchter <courtney at LunarG.com>
> ---
>   src/perf/teximage.c | 720 ++++++++++++++++++++++++++++++++++++++++------------
>   1 file changed, 563 insertions(+), 157 deletions(-)
>
> diff --git a/src/perf/teximage.c b/src/perf/teximage.c
> index 88316f3..3ab33a5 100644
> --- a/src/perf/teximage.c
> +++ b/src/perf/teximage.c
> @@ -1,5 +1,6 @@
>   /*
>    * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
> + * Copyright (C) 2012-2013 LunarG, Inc.
>    *
>    * Permission is hereby granted, free of charge, to any person obtaining a
>    * copy of this software and associated documentation files (the "Software"),
> @@ -14,49 +15,64 @@
>    * 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
> + * THE AUTHORS 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 glTex[Sub]Image2D() and glGetTexImage() rate
> - *
> - * Brian Paul
> - * 16 Sep 2009
> + * 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>
> +#include <stdbool.h>
>
> +/**
> + * Align a value up to an alignment value
> + *
> + * If \c value is not already aligned to the requested alignment value, it
> + * will be rounded up.
> + *
> + * \param value  Value to be rounded
> + * \param alignment  Alignment value to be used.  This must be a power of two.
> + *
> + * \sa ROUND_DOWN_TO()
> + */
> +#define ALIGN_PTR(value, alignment)  (((uintptr_t)(value) + (alignment) - 1) & ~ (uintptr_t)((alignment) - 1))
>
>   int WinWidth = 100, WinHeight = 100;
>
> +/* for texture creation */
>   static GLuint VBO;
>   static GLuint TexObj = 0;
>   static GLubyte *TexImage = NULL;
> -static GLsizei TexSize;
> -static GLenum TexIntFormat, TexSrcFormat, TexSrcType;
> -
> -static const GLboolean DrawPoint = GL_TRUE;
> -static const GLboolean TexSubImage4 = GL_FALSE;
>
>   enum {
> -   MODE_CREATE_TEXIMAGE,
> -   MODE_TEXIMAGE,
> -   MODE_TEXSUBIMAGE,
> -   MODE_GETTEXIMAGE,
> -   MODE_COUNT
> +   TEST_CREATE_TEXIMAGE,
> +   TEST_TEXIMAGE,
> +   TEST_TEXIMAGE_MIPMAP,
> +   TEST_TEXSUBIMAGE,
> +   TEST_GETTEXIMAGE,
> +   TEST_COUNT
>   };
>
> -static const char *mode_name[MODE_COUNT] =
> -{
> +static const char *test_name[TEST_COUNT] = {
>      "Create_TexImage",
>      "TexImage",
> +   "TexImage_Mipmap",
>      "TexSubImage",
>      "GetTexImage"
>   };
>
> +GLboolean test_enable[TEST_COUNT];
>
>
>   struct vertex
> @@ -68,8 +84,322 @@ static const struct vertex vertices[1] = {
>      { 0.0, 0.0, 0.5, 0.5 },
>   };
>
> +
> +/** define some functions */
> +GLenum parseType(char *);
> +GLenum parseFormat(char *, int);
> +GLuint determineTexelSize(GLenum format, GLenum type);
> +void parseConfigFile(void);
> +GLuint GenerateMipmapImages(void);

I think these declarations could be removed it you just declare the 
functions static below.


> +
>   #define VOFFSET(F) ((void *) offsetof(struct vertex, F))
>
> +/** defaults; options can be provided to set these */
> +GLint g_level = 0;
> +GLsizei g_width = 256;
> +GLsizei g_height = 256;
> +GLuint g_texelsize = 4;
> +GLenum g_texsrctype = GL_UNSIGNED_BYTE;
> +GLenum g_texfmt = GL_RGBA;
> +GLenum g_texintfmt = 0;
> +GLboolean g_drawpoint = GL_TRUE;
> +GLboolean g_subtexquad = GL_FALSE;
> +char configName[2056];
> +int formattype = 1;
> +int intformattype = 2;
> +char typeName[256] = "GL_UNSIGNED_BYTE";
> +char formatName[256] = "GL_RGBA";
> +char internalformatName[256] = "GL_RGBA";

The g_ prefix indicates a global variable.  It might be nice if we were 
more consistent about that.


> +GLboolean g_verbose = GL_FALSE;
> +
> +/* used when mipmapping */
> +static GLsizei g_initialwidth;
> +static GLsizei g_initialheight;
> +int g_numLevel = 0;
> +GLubyte *g_mipmapimgs[64];
> +GLsizei g_mmwidths[64];
> +GLsizei g_mmheights[64];
> +
> +enum csvStyle {
> +   CSV_STYLE_OFF,
> +   CSV_STYLE_DATA,
> +   CSV_STYLE_FULL
> +};
> +enum csvStyle g_csvstyle = CSV_STYLE_OFF;
> +
> +struct gl_parse_type {
> +   char *name;
> +   GLenum type;
> +   bool fixed_size; /* true indicates texel size is component size */
> +   int component_size;
> +};
> +
> +struct gl_parse_type parse_type_table[] = {

Should the table be declared const?


> +   {"GL_UNSIGNED_BYTE", GL_UNSIGNED_BYTE, false, 1},
> +   {"GL_BYTE", GL_BYTE, false, 1},
> +   {"GL_UNSIGNED_SHORT", GL_UNSIGNED_SHORT, false, 2},
> +   {"GL_SHORT", GL_SHORT, false, 2},
> +   {"GL_UNSIGNED_INT", GL_UNSIGNED_INT, false, 4},
> +   {"GL_INT", GL_INT, false, 4},
> +   {"GL_FLOAT", GL_FLOAT, false, 4},
> +   {"GL_UNSIGNED_BYTE_3_3_2", GL_UNSIGNED_BYTE_3_3_2, true, 1},
> +   {"GL_UNSIGNED_BYTE_2_3_3_REV", GL_UNSIGNED_BYTE_2_3_3_REV, true, 1},
> +   {"GL_UNSIGNED_SHORT_5_6_5", GL_UNSIGNED_SHORT_5_6_5, true, 2},
> +   {"GL_UNSIGNED_SHORT_5_6_5_REV", GL_UNSIGNED_SHORT_5_6_5_REV, true, 2},
> +   {"GL_UNSIGNED_SHORT_4_4_4_4", GL_UNSIGNED_SHORT_4_4_4_4, true, 2},
> +   {"GL_UNSIGNED_SHORT_4_4_4_4_REV", GL_UNSIGNED_SHORT_4_4_4_4_REV, true, 2},
> +   {"GL_UNSIGNED_SHORT_5_5_5_1", GL_UNSIGNED_SHORT_5_5_5_1, true, 2},
> +   {"GL_UNSIGNED_SHORT_1_5_5_5_REV", GL_UNSIGNED_SHORT_1_5_5_5_REV, true, 2},
> +   {"GL_UNSIGNED_INT_8_8_8_8", GL_UNSIGNED_INT_8_8_8_8, true, 4},
> +   {"GL_UNSIGNED_INT_8_8_8_8_REV", GL_UNSIGNED_INT_8_8_8_8_REV, true, 4},
> +   {"GL_UNSIGNED_INT_10_10_10_2", GL_UNSIGNED_INT_10_10_10_2, true, 4},
> +   {"GL_UNSIGNED_INT_2_10_10_10_REV", GL_UNSIGNED_INT_2_10_10_10_REV, true, 4},
> +};
> +
> +/** parse the type string */
> +GLenum
> +parseType(char *typestr)
> +{
> +   GLenum ogltype;
> +   int i;
> +
> +   for (i=0; i<(sizeof(parse_type_table)/sizeof(struct gl_parse_type)); i++) {

You might want to defined a ARRAY_SIZE() macro to use there.


> +      if (strcmp(typestr, parse_type_table[i].name) == 0) {
> +         strcpy(typeName, typestr);
> +         return parse_type_table[i].type;
> +      }
> +   }
> +
> +   /* if we get here, type specified is invalid; use a default */
> +   perf_printf("\nwarning: 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("\nwarning: format %s unknown; using GL_RGBA\n", formatstr);
> +      oglformat = GL_RGB;
> +      if (ftype == formattype) {
> +         strcpy(formatName, "GL_RGBA");
> +      } else {
> +         strcpy(internalformatName, "GL_RGBA");
> +      }
> +   }
> +
> +   return oglformat;
> +}
> +
> +GLuint
> +determineTexelSize(GLenum format, GLenum type)
> +{
> +   int i, component_size = 1, num_components = 1;
> +
> +   for (i=0; i<(sizeof(parse_type_table)/sizeof(struct gl_parse_type)); i++) {
> +      if (type == parse_type_table[i].type) {
> +         if (parse_type_table[i].fixed_size)
> +            return parse_type_table[i].component_size;
> +
> +         component_size = parse_type_table[i].component_size;
> +         break;
> +      }
> +   }
> +
> +   switch (format)
> +   {
> +   case GL_RGBA:
> +   case GL_BGRA:
> +      num_components = 4;
> +      break;
> +
> +   case GL_RGB:
> +      num_components = 3;
> +      break;
> +
> +   case GL_LUMINANCE:
> +      num_components = 1;
> +      break;
> +
> +   default:
> +      num_components = 4;
> +   }
> +
> +   return component_size * num_components;
> +}
> +
> +/** parse the args in the teximage_enh.opts file */
> +static void
> +parseCommands(int argc, char *argv[])
> +{
> +   char *key, *value;
> +   int intval;
> +   int arg, i;
> +
> +   bzero(test_enable, sizeof (test_enable));
> +
> +   for (arg = 1; arg < argc; arg++) {
> +      /* parse the arguments and set options appropriately */
> +      key = argv[arg];
> +      if (arg < argc) {
> +         /* point at next arg as most options require one. */
> +         value = argv[arg + 1];
> +      } else {
> +         value = "0"; /* default arg */
> +      }
> +      if (strcmp(key, "--width") == 0) {
> +         arg++;
> +         if (arg < argc) {
> +            intval = atoi(value);
> +            if (intval != 0) {
> +               g_width = (GLsizei) intval;
> +            }
> +         }
> +      } else if (strcmp(key, "--height") == 0) {
> +         if (arg < argc) {
> +            arg++;
> +            intval = atoi(value);
> +            if (intval != 0) {
> +               g_height = (GLsizei) intval;
> +            }
> +         }
> +      } else if (strcmp(key, "--level") == 0) {
> +         arg++;
> +         if (arg < argc) {
> +            intval = atoi(value);
> +            g_level = (GLint) intval;
> +         }
> +      } else if (strcmp(key, "--drawpoint") == 0) {
> +         /* default is true, so check for false */
> +         if (arg < argc) {
> +            arg++;
> +            if (strcmp(value, "no") == 0) {
> +               g_drawpoint = GL_FALSE;
> +            } else if (strcmp(value, "yes") == 0) {
> +               g_drawpoint = GL_TRUE;
> +            }
> +         }
> +      } else if (strcmp(key, "--type") == 0) {
> +         if (arg < argc) {
> +            arg++;
> +            g_texsrctype = parseType(value);
> +         }
> +      } else if (strcmp(key, "--format") == 0) {
> +         if (arg < argc) {
> +            arg++;
> +            g_texfmt = parseFormat(value, formattype);
> +         }
> +      } else if (strcmp(key, "--internalformat") == 0) {
> +         if (arg < argc) {
> +            arg++;
> +            g_texintfmt = parseFormat(value, intformattype);
> +         }
> +      } else if (strcmp(key, "--test") == 0) {
> +         if (arg < argc) {
> +            arg++;
> +            for (i = 0; i < TEST_COUNT; i++) {
> +               if (strcmp(value, test_name[i]) == 0) {
> +                  test_enable[i] = GL_TRUE;
> +                  break;
> +               }
> +            }
> +            if (i == TEST_COUNT) {
> +               perf_printf("Invalid test specified: %s", value);
> +               exit(1);
> +            }
> +         }
> +      } else if (strcmp(key, "--verbose") == 0) {
> +         g_verbose = GL_TRUE;
> +      } else if (strcmp(key, "--csvstyle") == 0) {
> +         if (arg < argc) {
> +            arg++;
> +            if (strcmp(value, "off") == 0) {
> +               g_csvstyle = CSV_STYLE_OFF; /* Show standard output */
> +            } else if (strcmp(value, "data") == 0) {
> +               g_csvstyle = CSV_STYLE_DATA; /* Show only perf stats */
> +            } else if (strcmp(value, "full") == 0) {
> +               g_csvstyle = CSV_STYLE_FULL; /* show header and perf stats */
> +            }
> +         }
> +      } else if (strcmp(key, "--help") == 0) {
> +         perf_printf("run glTexImage2D benchmark\n");
> +         perf_printf("Usage: %s [--width <num>] [--height <num>] [--level <num>]\n", argv[0]);
> +         perf_printf("                [--type <glenum>] [--texelsize <num>] [--format <glenum>]\n");
> +         perf_printf("                [--internalformat <gltype>] [--drawpoint yes/no] [--verbose]\n");
> +         perf_printf("                [--csvstyle off|data|full] [--test ");
> +         for (i = 0; i < TEST_COUNT; i++) {
> +            perf_printf("%s", test_name[i]);
> +            /* print separator all but last one */
> +            if (i < (TEST_COUNT - 1)) perf_printf(" | ");

perf_print() call on next line.


> +         }
> +         perf_printf("]\n");
> +         exit(0);
> +      } else {
> +         perf_printf("Unrecognized argument: %s\n", key);
> +         exit(1);
> +      }
> +   }
> +
> +   g_texelsize = determineTexelSize(g_texfmt, g_texsrctype);
> +
> +   for (i = 0; i < TEST_COUNT; i++) {
> +      if (test_enable[i] == GL_TRUE)
> +         break;
> +   }
> +   if (i == TEST_COUNT) {
> +      /* No tests were enabled, so enable all of them */
> +      for (i = 0; i < TEST_COUNT; i++) {
> +         test_enable[i] = GL_TRUE;
> +      }
> +   }
> +
> +   /* 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);
> +   if (g_csvstyle == CSV_STYLE_OFF && g_verbose)
> +      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
> @@ -91,15 +421,20 @@ PerfInit(int argc, char *argv[])
>      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 */
> +   parseCommands(argc, argv);
> +}
>
>   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);
> @@ -109,68 +444,135 @@ CreateUploadTexImage2D(unsigned count)
>         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
>         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
>
> -      glTexImage2D(GL_TEXTURE_2D, 0, TexIntFormat,
> -                   TexSize, TexSize, 0,
> -                   TexSrcFormat, TexSrcType, TexImage);
> +      glTexImage2D(GL_TEXTURE_2D, g_level, g_texintfmt,
> +                   g_width, g_height, 0,
> +                   g_texfmt, g_texsrctype, TexImage);
>
> -      if (DrawPoint)
> +      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++) {
> -      /* XXX is this equivalent to a glTexSubImage call since we're
> -       * always specifying the same image size?  That case isn't optimized
> -       * in Mesa but may be optimized in other drivers.  Note sure how
> -       * much difference that might make.
> -       */
> -      glTexImage2D(GL_TEXTURE_2D, 0, TexIntFormat,
> -                   TexSize, TexSize, 0,
> -                   TexSrcFormat, TexSrcType, TexImage);
> -      if (DrawPoint)
> +      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();
>   }
>
> +GLuint
> +GenerateMipmapImages(void)
> +{
> +   GLuint w, h;
> +   GLint bytesPerImage, mallocSize, bytesPerLevel;
> +   GLubyte *levelPtr;
> +   w = g_width;
> +   h = g_height;
> +   bytesPerImage = 0;
> +   mallocSize = 0;
> +
> +   /* compute totals first */
> +   while ((w > 1) || (h > 1)) {
> +      bytesPerLevel = w * h * g_texelsize;
> +      bytesPerImage += bytesPerLevel;
> +      /* Add 64 so that we can align the data to 64 byte boundary */
> +      mallocSize += bytesPerLevel + 0x40;
> +
> +      if (w > 1) {
> +         w = w / 2;
> +      }
> +      if (h > 1) {
> +         h = h / 2;
> +      }
> +   }
> +
> +   TexImage = malloc(mallocSize);
> +   levelPtr = TexImage;
> +
> +   w = g_width;
> +   h = g_height;
> +   /* generate the mipmap images */
> +   while ((w > 1) || (h > 1)) {
> +      bytesPerLevel = w * h * g_texelsize;
> +
> +      /* Round to the next higher 64byte boundary.
> +       * That is generally better for today's HW and
> +       * easy for an app to do if they care.
> +       */
> +      levelPtr = (GLubyte *) ALIGN_PTR(levelPtr, 64);
> +
> +      /* set memory to "simulate" loading an image */
> +      memset(levelPtr, g_numLevel, bytesPerLevel);
> +
> +      g_mipmapimgs[g_numLevel] = levelPtr;
> +      g_mmwidths[g_numLevel] = w;
> +      g_mmheights[g_numLevel] = h;
> +      g_numLevel = g_numLevel + 1;
> +
> +      /* Advance pointer to next free area */
> +      levelPtr += bytesPerLevel;
> +
> +      if (w > 1) {
> +         w = w / 2;
> +      }
> +      if (h > 1) {
> +         h = h / 2;
> +      }
> +   }
> +   if (g_verbose) {
> +      perf_printf("GenerateMipmapImages: generated %d mipmaps\n", g_numLevel);
> +   }
> +
> +   return bytesPerImage;
> +
> +}
>
>   static void
>   UploadTexSubImage2D(unsigned count)
>   {
>      unsigned i;
>      for (i = 0; i < count; i++) {
> -      if (TexSubImage4) {
> -         GLsizei halfSize = (TexSize == 1) ? 1 : TexSize / 2;
> -         GLsizei halfPos = TexSize - halfSize;
> +      if (g_subtexquad) {
> +         GLsizei halfSizeW = (g_width == 1) ? 1 : g_width / 2;
> +         GLsizei halfPosX = g_width - halfSizeW;
> +         GLsizei halfSizeH = (g_height == 1) ? 1 : g_height / 2;
> +         GLsizei halfPosY = g_height - halfSizeH;
>            /* do glTexSubImage2D in four pieces */
>            /* lower-left */
> -         glPixelStorei(GL_UNPACK_ROW_LENGTH, TexSize);
> +         glPixelStorei(GL_UNPACK_ROW_LENGTH, g_width);
>            glTexSubImage2D(GL_TEXTURE_2D, 0,
> -                         0, 0, halfSize, halfSize,
> -                         TexSrcFormat, TexSrcType, TexImage);
> +                         0, 0, halfSizeW, halfSizeH,
> +                         g_texfmt, g_texsrctype, TexImage);
>            /* lower-right */
> -         glPixelStorei(GL_UNPACK_SKIP_PIXELS, halfPos);
> +         glPixelStorei(GL_UNPACK_SKIP_PIXELS, halfPosX);
>            glTexSubImage2D(GL_TEXTURE_2D, 0,
> -                         halfPos, 0, halfSize, halfSize,
> -                         TexSrcFormat, TexSrcType, TexImage);
> +                         halfPosX, 0, halfSizeW, halfSizeH,
> +                         g_texfmt, g_texsrctype, TexImage);
>            /* upper-left */
>            glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
> -         glPixelStorei(GL_UNPACK_SKIP_ROWS, halfPos);
> +         glPixelStorei(GL_UNPACK_SKIP_ROWS, halfPosY);
>            glTexSubImage2D(GL_TEXTURE_2D, 0,
> -                         0, halfPos, halfSize, halfSize,
> -                         TexSrcFormat, TexSrcType, TexImage);
> +                         0, halfPosY, halfSizeW, halfSizeH,
> +                         g_texfmt, g_texsrctype, TexImage);
>            /* upper-right */
> -         glPixelStorei(GL_UNPACK_SKIP_PIXELS, halfPos);
> -         glPixelStorei(GL_UNPACK_SKIP_ROWS, halfPos);
> +         glPixelStorei(GL_UNPACK_SKIP_PIXELS, halfPosX);
> +         glPixelStorei(GL_UNPACK_SKIP_ROWS, halfPosY);
>            glTexSubImage2D(GL_TEXTURE_2D, 0,
> -                         halfPos, halfPos, halfSize, halfSize,
> -                         TexSrcFormat, TexSrcType, TexImage);
> +                         halfPosX, halfPosY, halfSizeW, halfSizeH,
> +                         g_texfmt, g_texsrctype, TexImage);
>            /* reset the unpacking state */
>            glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
>            glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
> @@ -179,46 +581,52 @@ UploadTexSubImage2D(unsigned count)
>         else {
>            /* replace whole texture image at once */
>            glTexSubImage2D(GL_TEXTURE_2D, 0,
> -                         0, 0, TexSize, TexSize,
> -                         TexSrcFormat, TexSrcType, TexImage);
> +                         0, 0, g_width, g_height,
> +                         g_texfmt, g_texsrctype, TexImage);
>         }
> -      if (DrawPoint)
> +      if (g_drawpoint)
>            glDrawArrays(GL_POINTS, 0, 1);
>      }
>      glFinish();
>   }
>
> -
>   static void
>   GetTexImage2D(unsigned count)
>   {
>      unsigned i;
> -   GLubyte *buf = (GLubyte *) malloc(TexSize * TexSize * 4);
> +   GLubyte *buf = (GLubyte *) malloc(g_width * g_height * g_texelsize);
>      for (i = 0; i < count; i++) {
>         glGetTexImage(GL_TEXTURE_2D, 0,
> -                    TexSrcFormat, TexSrcType, buf);
> +                    g_texfmt, g_texsrctype, buf);
>      }
>      glFinish();
>      free(buf);
>   }
>
> +static void
> +UploadTexImage2DMipmap(unsigned count)
> +{
> +   unsigned i, j;
>
> -/* XXX any other formats to measure? */
> -static const struct {
> -   GLenum format, type;
> -   GLenum internal_format;
> -   const char *name;
> -   GLuint texel_size;
> -   GLboolean full_test;
> -} SrcFormats[] = {
> -   { GL_RGBA, GL_UNSIGNED_BYTE,       GL_RGBA, "RGBA/ubyte", 4,   GL_TRUE },
> -   { GL_RGB, GL_UNSIGNED_BYTE,        GL_RGB, "RGB/ubyte", 3,     GL_FALSE },
> -   { GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB, "RGB/565", 2,       GL_FALSE },
> -   { GL_BGRA, GL_UNSIGNED_BYTE,       GL_RGBA, "BGRA/ubyte", 4,   GL_FALSE },
> -   { GL_LUMINANCE, GL_UNSIGNED_BYTE,  GL_LUMINANCE, "L/ubyte", 1, GL_FALSE },
> -   { 0, 0, 0, NULL, 0, 0 }
> -};
>
> +   /* ?? make this configurable ?? */
> +   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
> +   /* mipmaps previously generated, call glTexImage2D for all levels */
> +   for (i = 0; i < count; i++) {
> +      for (j = 0; j < g_numLevel; j++) {
> +         if (g_verbose) {
> +            perf_printf("mipmap glTexImage2D - level: %d, width: %d, height: %d\n",
> +                        j, g_mmwidths[j], g_mmheights[j]);
> +         }
> +         glTexImage2D(GL_TEXTURE_2D, j, g_texintfmt, g_mmwidths[j],
> +                      g_mmheights[j], 0, g_texfmt, g_texsrctype, g_mipmapimgs[j]);
> +         if (g_drawpoint)
> +            glDrawArrays(GL_POINTS, 0, 1);
> +      }
> +   }
> +   glFinish();
> +
> +}
>
>   /** Called from test harness/main */
>   void
> @@ -226,104 +634,102 @@ PerfNextRound(void)
>   {
>   }
>
> -
>   /** Called from test harness/main */
>   void
>   PerfDraw(void)
>   {
>      GLint maxSize;
>      double rate;
> -   GLint fmt, mode;
> +   GLint test;
> +   double mbPerSec; // Megabytes per second
> +   double mTPerSec; // MegaTexels per second
> +   GLint bytesPerImage;
> +
> +   if (g_csvstyle == CSV_STYLE_FULL) {
> +      perf_printf("%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s\n",
> +                  "ID", "Test", "width", "height", "level", "type",
> +                  "texelsize", "format", "internalformat",
> +                  "images/sec", "MB/sec", "MT/sec");
> +   }
>
>      glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
> +   /* TODO - check for max size exceeded?? */
> +
> +   /* loop over glTexImage */
> +   for (test = 0; test < TEST_COUNT; test++) {
> +
> +      if (test_enable[test] == GL_FALSE) continue;
> +
> +      switch (test) {
> +      case TEST_TEXIMAGE:
> +         bytesPerImage = g_width * g_height * g_texelsize;
> +         TexImage = malloc(bytesPerImage);
> +         rate = PerfMeasureRate(UploadTexImage2D);
> +         break;
> +
> +      case TEST_CREATE_TEXIMAGE:
> +         bytesPerImage = g_width * g_height * g_texelsize;
> +         TexImage = malloc(bytesPerImage);
> +         rate = PerfMeasureRate(CreateUploadTexImage2D);
> +         break;
> +
> +      case TEST_TEXIMAGE_MIPMAP:
> +         g_initialwidth = g_width;
> +         g_initialheight = g_height;
> +         bytesPerImage = GenerateMipmapImages();
> +         rate = PerfMeasureRate(UploadTexImage2DMipmap);
> +         /* ?? each mipmap has a different bytes per image, is mb/s and mt/s
> +            calculation below correct?  ?? */
> +         break;
> +
> +      case TEST_TEXSUBIMAGE:
> +         /* create initial, empty texture */
> +         bytesPerImage = g_width * g_height * g_texelsize;
> +         TexImage = malloc(bytesPerImage);
> +         glTexImage2D(GL_TEXTURE_2D, 0, g_texintfmt,
> +                      g_width, g_height, 0,
> +                      g_texfmt, g_texsrctype, NULL);
> +         rate = PerfMeasureRate(UploadTexSubImage2D);
> +         break;
> +
> +      case TEST_GETTEXIMAGE:
> +         bytesPerImage = g_width * g_height * g_texelsize;
> +         TexImage = malloc(bytesPerImage);
> +         glTexImage2D(GL_TEXTURE_2D, 0, g_texintfmt,
> +                      g_width, g_height, 0,
> +                      g_texfmt, g_texsrctype, TexImage);
> +         rate = PerfMeasureRate(GetTexImage2D);
> +         break;
> +
> +      default:
> +         exit(1);
> +      }
>
> -   /* loop over source data formats */
> -   for (fmt = 0; SrcFormats[fmt].format; fmt++) {
> -      TexIntFormat = SrcFormats[fmt].internal_format;
> -      TexSrcFormat = SrcFormats[fmt].format;
> -      TexSrcType = SrcFormats[fmt].type;
> -
> -      /* loop over glTexImage, glTexSubImage */
> -      for (mode = 0; mode < MODE_COUNT; mode++) {
> -         GLuint minsz, maxsz;
> -
> -         if (SrcFormats[fmt].full_test) {
> -            minsz = 16;
> -            maxsz = 4096;
> -         }
> -         else {
> -            minsz = maxsz = 256;
> -            if (mode == MODE_CREATE_TEXIMAGE)
> -               continue;
> -         }
> -
> -         /* loop over a defined range of texture sizes, test only the
> -          * ones which are legal for this driver.
> -          */
> -         for (TexSize = minsz; TexSize <= maxsz; TexSize *= 4) {
> -            double mbPerSec;
> -
> -            if (TexSize <= maxSize) {
> -               GLint bytesPerImage;
> -
> -               bytesPerImage = TexSize * TexSize * SrcFormats[fmt].texel_size;
> -               TexImage = malloc(bytesPerImage);
> -
> -               switch (mode) {
> -               case MODE_TEXIMAGE:
> -                  rate = PerfMeasureRate(UploadTexImage2D);
> -                  break;
> -
> -               case MODE_CREATE_TEXIMAGE:
> -                  rate = PerfMeasureRate(CreateUploadTexImage2D);
> -                  break;
> -
> -               case MODE_TEXSUBIMAGE:
> -                  /* create initial, empty texture */
> -                  glTexImage2D(GL_TEXTURE_2D, 0, TexIntFormat,
> -                               TexSize, TexSize, 0,
> -                               TexSrcFormat, TexSrcType, NULL);
> -                  rate = PerfMeasureRate(UploadTexSubImage2D);
> -                  break;
> -
> -               case MODE_GETTEXIMAGE:
> -                  glTexImage2D(GL_TEXTURE_2D, 0, TexIntFormat,
> -                               TexSize, TexSize, 0,
> -                               TexSrcFormat, TexSrcType, TexImage);
> -                  rate = PerfMeasureRate(GetTexImage2D);
> -                  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);
> -                  }
> -               }
> -
> -            }
> -            else {
> -               rate = 0;
> -               mbPerSec = 0;
> -            }
> +      mbPerSec = (rate * bytesPerImage) / (1024.0 * 1024.0);
> +      mTPerSec = (rate * g_width * g_height) / (1024.0 * 1024.0);
> +      free(TexImage);
>
> -            perf_printf("  %s(%s %d x %d): "
> -                        "%.1f images/sec, %.1f MB/sec\n",
> -                        mode_name[mode],
> -                        SrcFormats[fmt].name, TexSize, TexSize, rate, mbPerSec);
> +      {
> +         unsigned err;
> +         err = glGetError();
> +         if (err) {
> +            perf_printf("non-zero glGetError() %d\n", err);
> +            exit(1);
>            }
> +      }
>
> -         if (SrcFormats[fmt].full_test)
> -            perf_printf("\n");
> +      if (g_csvstyle == CSV_STYLE_DATA || g_csvstyle == CSV_STYLE_FULL) {
> +         /* print a unique name to add in spreadsheet computations */
> +         perf_printf("%s-%d-%d-%d-%s-%d-%s-%s, ",
> +                     test_name[test], g_width, g_height, g_level,
> +                     typeName, g_texelsize, formatName, internalformatName);
> +         perf_printf("%s, %d, %d, %d, %s, %d, %s, %s, %.1f, %.1f, %.1f\n",
> +                     test_name[test], g_width, g_height, g_level, typeName, g_texelsize, formatName,
> +                     internalformatName, rate, mbPerSec, mTPerSec);
> +      } else {
> +         perf_printf("%s(%s %dx%d): " "%.1f images/sec, %.1f MB/sec\n",
> +                     test_name[test],
> +                     configName, g_width, g_height, rate, mbPerSec);
>         }
>      }
>
>



More information about the mesa-dev mailing list