vbo: allow specifying different formats

Submitted by Ilia Mirkin on Oct. 13, 2015, 11:09 p.m.

Details

Message ID 1444777756-21450-1-git-send-email-imirkin@alum.mit.edu
State New
Headers show

Not browsing as part of any series.

Commit Message

Ilia Mirkin Oct. 13, 2015, 11:09 p.m.
The only thing this doesn't allow is double + glVertexAttribPointer.
Could be added if there were demand for it.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
---
 tests/util/piglit-vbo.cpp | 167 +++++++++++++++++++++++++++++++---------------
 1 file changed, 114 insertions(+), 53 deletions(-)

Patch hide | download patch | download mbox

diff --git a/tests/util/piglit-vbo.cpp b/tests/util/piglit-vbo.cpp
index 6453d40..b175256 100644
--- a/tests/util/piglit-vbo.cpp
+++ b/tests/util/piglit-vbo.cpp
@@ -102,41 +102,13 @@  const int ATTRIBUTE_SIZE = 4;
 
 
 /**
- * Convert a type name string to a GLenum.
- */
-GLenum
-decode_type(const char *type)
-{
-	static struct type_table_entry {
-		const char *type; /* NULL means end of table */
-		GLenum enum_value;
-	} const type_table[] = {
-		{ "int",     GL_INT            },
-		{ "uint",    GL_UNSIGNED_INT   },
-		{ "float",   GL_FLOAT          },
-		{ "double",  GL_DOUBLE         },
-		{ NULL,      0                 }
-	};
-
-
-	for (int i = 0; type_table[i].type; ++i) {
-		if (0 == strcmp(type, type_table[i].type))
-			return type_table[i].enum_value;
-	}
-
-	printf("Unrecognized type: %s\n", type);
-	piglit_report_result(PIGLIT_FAIL);
-	return 0;
-}
-
-
-/**
  * Description of a vertex attribute, built from its column header
  */
 class vertex_attrib_description
 {
 public:
 	vertex_attrib_description(GLuint prog, const char *text);
+	void decode_type(const char *type);
 	bool parse_datum(const char **text, void *data) const;
 	void setup(size_t *offset, size_t stride) const;
 
@@ -146,6 +118,16 @@  public:
 	GLenum data_type;
 
 	/**
+	 * Whether this attribute is normalized.
+	 */
+	GLboolean normalized;
+
+	/**
+	 * Whether this attribute is integer
+	 */
+	GLboolean is_integer;
+
+	/**
 	 * Vector length of this attribute.
 	 */
 	size_t count;
@@ -158,6 +140,54 @@  public:
 
 
 /**
+ * Convert a type name string to a GLenum.
+ */
+void
+vertex_attrib_description::decode_type(const char *type)
+{
+	static struct type_table_entry {
+		const char *type; /* NULL means end of table */
+		GLenum enum_value;
+		GLboolean normalized;
+		GLboolean is_integer;
+	} const type_table[] = {
+		{ "byte",     GL_BYTE          , GL_FALSE, GL_TRUE  },
+		{ "ubyte",    GL_UNSIGNED_BYTE , GL_FALSE, GL_TRUE  },
+		{ "short",    GL_SHORT         , GL_FALSE, GL_TRUE  },
+		{ "ushort",   GL_UNSIGNED_SHORT, GL_FALSE, GL_TRUE  },
+		{ "int",      GL_INT           , GL_FALSE, GL_TRUE  },
+		{ "uint",     GL_UNSIGNED_INT  , GL_FALSE, GL_TRUE  },
+		{ "snorm8",   GL_BYTE          , GL_TRUE,  GL_FALSE },
+		{ "unorm8",   GL_UNSIGNED_BYTE , GL_TRUE,  GL_FALSE },
+		{ "snorm16",  GL_SHORT         , GL_TRUE,  GL_FALSE },
+		{ "unorm16",  GL_UNSIGNED_SHORT, GL_TRUE,  GL_FALSE },
+		{ "snorm32",  GL_INT           , GL_TRUE,  GL_FALSE },
+		{ "unorm32",  GL_UNSIGNED_INT  , GL_TRUE,  GL_FALSE },
+		{ "sfixed8",  GL_BYTE          , GL_FALSE, GL_FALSE },
+		{ "ufixed8",  GL_UNSIGNED_BYTE , GL_FALSE, GL_FALSE },
+		{ "sfixed16", GL_SHORT         , GL_FALSE, GL_FALSE },
+		{ "ufixed16", GL_UNSIGNED_SHORT, GL_FALSE, GL_FALSE },
+		{ "sfixed32", GL_INT           , GL_FALSE, GL_FALSE },
+		{ "ufixed32", GL_UNSIGNED_INT  , GL_FALSE, GL_FALSE },
+		{ "float",    GL_FLOAT         , GL_FALSE, GL_FALSE },
+		{ "double",   GL_DOUBLE        , GL_FALSE, GL_FALSE },
+		{ NULL,      0                 }
+	};
+
+
+	for (int i = 0; type_table[i].type; ++i) {
+		if (!strcmp(type, type_table[i].type)) {
+			this->data_type = type_table[i].enum_value;
+			this->normalized = type_table[i].normalized;
+			this->is_integer = type_table[i].is_integer;
+		}
+	}
+
+	printf("Unrecognized type: %s\n", type);
+	piglit_report_result(PIGLIT_FAIL);
+}
+
+/**
  * Build a vertex_attrib_description from a column header, by looking
  * up the vertex attribute in the linked program and interpreting the
  * type and count parts of the header.
@@ -185,7 +215,7 @@  vertex_attrib_description::vertex_attrib_description(GLuint prog,
 		piglit_report_result(PIGLIT_FAIL);
 	}
 	std::string type_str(first_slash + 1, second_slash);
-	this->data_type = decode_type(type_str.c_str());
+	decode_type(type_str.c_str());
 	char *endptr;
 	this->count = strtoul(second_slash + 1, &endptr, 10);
 	if (*endptr != '\0') {
@@ -208,7 +238,7 @@  vertex_attrib_description::vertex_attrib_description(GLuint prog,
 	 * (b) skip itself if integer vertex attribute support is not
 	 * present.
 	 */
-	if (this->data_type != GL_FLOAT &&
+	if (this->is_integer &&
 	    (piglit_is_gles() ||
 	    (piglit_get_gl_version() < 30 &&
 		!piglit_is_extension_supported("GL_EXT_gpu_shader4")))) {
@@ -217,6 +247,12 @@  vertex_attrib_description::vertex_attrib_description(GLuint prog,
 		piglit_report_result(PIGLIT_FAIL);
 	}
 
+	if (this->data_type == GL_DOUBLE &&
+	    !piglit_is_extension_supported("GL_ARB_vertex_attrib_64bit")) {
+		printf("vertex_attrib_description fail. no 64-bit float support\n");
+		piglit_report_result(PIGLIT_FAIL);
+	}
+
 	if (this->count < 1 || this->count > 4) {
 		printf("Count must be between 1 and 4.  Got: %lu\n", (unsigned long) count);
 		piglit_report_result(PIGLIT_FAIL);
@@ -274,6 +310,42 @@  vertex_attrib_description::parse_datum(const char **text, void *data) const
 		*((GLuint *) data) = (GLuint) value;
 		break;
 	}
+	case GL_SHORT: {
+		long value = strtol(*text, &endptr, 0);
+		if (errno == ERANGE) {
+			printf("Could not parse as signed integer\n");
+			return false;
+		}
+		*((GLshort *) data) = (GLshort) value;
+		break;
+	}
+	case GL_UNSIGNED_SHORT: {
+		unsigned long value = strtoul(*text, &endptr, 0);
+		if (errno == ERANGE) {
+			printf("Could not parse as unsigned integer\n");
+			return false;
+		}
+		*((GLushort *) data) = (GLushort) value;
+		break;
+	}
+	case GL_BYTE: {
+		long value = strtol(*text, &endptr, 0);
+		if (errno == ERANGE) {
+			printf("Could not parse as signed integer\n");
+			return false;
+		}
+		*((GLbyte *) data) = (GLbyte) value;
+		break;
+	}
+	case GL_UNSIGNED_BYTE: {
+		unsigned long value = strtoul(*text, &endptr, 0);
+		if (errno == ERANGE) {
+			printf("Could not parse as unsigned integer\n");
+			return false;
+		}
+		*((GLubyte *) data) = (GLubyte) value;
+		break;
+	}
 	default:
 		assert(!"Unexpected data type");
 		endptr = NULL;
@@ -291,32 +363,21 @@  void
 vertex_attrib_description::setup(size_t *offset, size_t stride) const
 {
 	int attribute_size = ATTRIBUTE_SIZE;
-	switch (this->data_type) {
-	case GL_FLOAT:
-		glVertexAttribPointer(this->index, this->count,
-				      this->data_type, GL_FALSE, stride,
-				      (void *) *offset);
-		break;
-	case GL_DOUBLE:
-		if (!piglit_is_extension_supported("GL_ARB_vertex_attrib_64bit")) {
-			fprintf(stderr,"vertex_attrib_description fail. no 64-bit float support\n");
-			return;
-		}
-		glVertexAttribLPointer(this->index, this->count,
-				      this->data_type, stride,
-				      (void *) *offset);
-		attribute_size *= 2;
-		break;
-	default:
-		if (piglit_is_gles() && piglit_get_gl_version() < 30) {
-			fprintf(stderr,"vertex_attrib_description fail. no int support\n");
-			return;
-		}
+	if (this->is_integer) {
 		glVertexAttribIPointer(this->index, this->count,
 				       this->data_type, stride,
 				       (void *) *offset);
-		break;
+	} else if (this->data_type == GL_DOUBLE) {
+		glVertexAttribLPointer(this->index, this->count,
+				       this->data_type, stride,
+				       (void *) *offset);
+		attribute_size *= 2;
+	} else {
+		glVertexAttribPointer(this->index, this->count,
+				      this->data_type, this->normalized, stride,
+				      (void *) *offset);
 	}
+
 	glEnableVertexAttribArray(index);
 	*offset += attribute_size * this->count;
 }