[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