[Mesa-dev] [PATCH 1/2] mesa: add Uniform Buffer Object API implementation
Vincent Lejeune
vljn at ovi.com
Fri Dec 2 05:22:34 PST 2011
v2:Move implementation to ubo.cpp and ubo.h as suggested by
Brian Paul
---
src/mesa/main/api_exec.c | 2 +
src/mesa/main/bufferobj.c | 11 +
src/mesa/main/ubo.cpp | 263 ++++++++++++++++++++++++++
src/mesa/main/ubo.h | 33 ++++
src/mesa/sources.mak | 1 +
src/mesa/state_tracker/st_cb_bufferobjects.c | 6 +-
6 files changed, 315 insertions(+), 1 deletions(-)
create mode 100644 src/mesa/main/ubo.cpp
create mode 100644 src/mesa/main/ubo.h
diff --git a/src/mesa/main/api_exec.c b/src/mesa/main/api_exec.c
index e0bf90d..c908719 100644
--- a/src/mesa/main/api_exec.c
+++ b/src/mesa/main/api_exec.c
@@ -102,6 +102,7 @@
#if FEATURE_ARB_shader_objects
#include "shaderapi.h"
#include "uniforms.h"
+#include "ubo.h"
#endif
#include "syncobj.h"
#include "main/dispatch.h"
@@ -307,6 +308,7 @@ _mesa_create_exec_table(void)
#if FEATURE_ARB_shader_objects
_mesa_init_shader_dispatch(exec);
_mesa_init_shader_uniform_dispatch(exec);
+ _mesa_init_shader_uniform_buffer_objects(exec);
#endif
/* 2. GL_EXT_blend_color */
diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
index b7e59e8..d74b78c 100644
--- a/src/mesa/main/bufferobj.c
+++ b/src/mesa/main/bufferobj.c
@@ -98,6 +98,8 @@ get_buffer_target(struct gl_context *ctx, GLenum target)
return &ctx->Texture.BufferObject;
}
break;
+ case GL_UNIFORM_BUFFER:
+ return &ctx->UniformBufferObject.UniformObj;
default:
return NULL;
}
@@ -734,6 +736,10 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
break;
#endif
+#if FEATURE_ARB_uniform_buffer_object
+ case GL_UNIFORM_BUFFER:
+ break;
+#endif
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)");
break;
@@ -756,6 +762,11 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
_mesa_bind_buffer_range_for_transform_feedback(ctx, index, bufObj, 0, size);
break;
#endif
+#if FEATURE_ARB_uniform_buffer_object
+ case GL_UNIFORM_BUFFER:
+ ctx->UniformBufferObject.BindingPoint[index] = bufObj;
+ break;
+#endif
default: /* should not go here */
break;
}
diff --git a/src/mesa/main/ubo.cpp b/src/mesa/main/ubo.cpp
new file mode 100644
index 0000000..77f7edd
--- /dev/null
+++ b/src/mesa/main/ubo.cpp
@@ -0,0 +1,263 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2004-2011 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009-2011 VMware, Inc. All Rights Reserved.
+ * Copyright © 2010-2011 Intel Corporation
+ * Copyright (C) 2011 Vincent Lejeune.
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+/**
+ * API implementation of GL_ARB_uniform_buffer_object.
+ *
+ * Every uniform (in an UBO or not) is given an index that identifies it when
+ * calling one of these functions. Strictly speaking, such an index doesn't
+ * need to match location for classic uniform ; others drivers however use this
+ * approach so we're also matching them for compatibility purpose.
+ */
+
+#include <stdint.h>
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/dispatch.h"
+#include "main/image.h"
+#include "main/mfeatures.h"
+#include "main/mtypes.h"
+#include "main/shaderapi.h"
+#include "main/shaderobj.h"
+#include "main/uniforms.h"
+#include "program/hash_table.h"
+#include "program/prog_parameter.h"
+#include "program/prog_statevars.h"
+#include "program/prog_instruction.h"
+#include "main/ubo.h"
+#include "main/bufferobj.h"
+
+static void
+get_ubo_info(struct gl_context *ctx,
+ struct gl_shader_program *shProg, GLint ubo_index,
+ GLenum query, int *data)
+{
+ if (ubo_index > shProg->UBOCount || ubo_index < 0)
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetActiveUniformBlock(uniformBlockIndex)");
+
+ struct gl_uniform_buffer_object current_ubo =
+ shProg->UniformBufferObject[ubo_index];
+
+ switch (query) {
+ case GL_UNIFORM_BLOCK_BINDING:
+ data = 0; // TODO : find a nice way to get buffer id
+ break;
+ case GL_UNIFORM_BLOCK_DATA_SIZE:
+ *data = current_ubo.Size;
+ break;
+ case GL_UNIFORM_BLOCK_NAME_LENGTH:
+ *data = strlen(current_ubo.Name) + 1;
+ break;
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ *data = current_ubo.NumberOfVariables;
+ break;
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ *data = current_ubo.ReferencedByVS;
+ break;
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER:
+ *data = current_ubo.ReferencedByGS;
+ break;
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ *data = current_ubo.ReferencedByFS;
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+static GLuint
+get_indice(const struct gl_shader_program *prog, const char *name)
+{
+ unsigned index;
+ if (prog->NamedAccessUBOVariables->get(index, name)) {
+ return index;
+ }
+
+ return GL_INVALID_INDEX;
+}
+
+/**
+ * This function checks if it can copy source into dest.
+ * If it cannot, it returns 1, otherwise it returns 0 and
+ * write size to *length if non NULL
+ */
+static int
+copy_char_buffer(const char *source, char *dest, unsigned destsize,
+ int *length)
+{
+ unsigned sourcesize = strlen(source);
+ if (sourcesize > destsize + 1) {
+ return -1;
+ }
+ memcpy(dest, source, sourcesize);
+ dest[sourcesize] = '0';
+ if (length)
+ *length = sourcesize;
+ return 0;
+}
+
+static void
+get_ubo_name(struct gl_context *ctx, struct gl_shader_program *shProg,
+ GLint index, GLsizei bufsize, GLsizei * length, char *buffer)
+{
+ if (index >= shProg->UBOCount || index < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "GetActiveUniformBlockName(uniformBlockIndex)");
+ return;
+ }
+
+ struct gl_uniform_buffer_object current_ubo =
+ shProg->UniformBufferObject[index];
+
+ if (copy_char_buffer(current_ubo.Name, buffer, bufsize, length)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "GetActiveUniformBlockName(bufSize)");
+ return;
+ }
+ return;
+}
+
+static void
+get_uniform_variable_name(struct gl_context *ctx,
+ struct gl_shader_program *sh, GLuint index,
+ GLsizei bufsize, GLsizei * length,
+ char *uniformName)
+{
+ const char *name = 0; // sh->Uniforms->Uniforms[index].Name;
+ if (copy_char_buffer(name, uniformName, bufsize, length)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "GetActiveUniformName(bufSize)");
+ return;
+ }
+ return;
+}
+
+static GLint
+get_uniform_variable_info(struct gl_shader_program *sh, GLuint index,
+ GLenum pname)
+{
+ uint starting_index = sh->NumUserUniformStorage;
+ if (index >= starting_index) {
+ struct gl_program_ubo_variable *var =
+ sh->IndexedUBOVariables[index - starting_index];
+ switch (pname) {
+ case GL_UNIFORM_TYPE:
+ return var->Type;
+ case GL_UNIFORM_SIZE:
+ return 1;
+ case GL_UNIFORM_NAME_LENGTH:
+ return strlen(var->Name) + 1;
+ case GL_UNIFORM_BLOCK_INDEX:
+ return var->UBO->Index;
+ case GL_UNIFORM_OFFSET:
+ return var->Offset;
+ case GL_UNIFORM_ARRAY_STRIDE:
+ case GL_UNIFORM_MATRIX_STRIDE:
+ return var->Stride;
+ case GL_UNIFORM_IS_ROW_MAJOR:
+ return sh->UniformBufferObject[var->UBO->Index].MatrixLayout ==
+ UBO_MATRIX_LAYOUT_ROW_MAJOR;
+ }
+ }
+
+ return GL_INVALID_VALUE;
+}
+
+void GLAPIENTRY
+_mesa_GetActiveUniformBlockInfo(GLuint program, GLuint ubo_index,
+ GLenum pname, GLint * params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program,
+ "GetActiveUniformBlockiv");
+ get_ubo_info(ctx, shProg, ubo_index, pname, params);
+}
+
+void GLAPIENTRY
+_mesa_GetActiveUniformBlockName(GLuint program, GLuint ubo_index,
+ GLsizei bufsize, GLint * length, char *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program,
+ "GetActiveUniformBlockName");
+ get_ubo_name(ctx, shProg, ubo_index, bufsize, length, name);
+}
+
+void GLAPIENTRY
+_mesa_GetUniformIndices(GLuint program, GLsizei number_of_variables,
+ const char **names, GLuint * indices)
+{
+ unsigned i;
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program, "GetUniformIndices");
+ for (i = 0; i < number_of_variables; i++) {
+ indices[i] = get_indice(shProg, names[i]);
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetActiveUniformName(GLuint program, GLuint index, GLsizei bufsize,
+ GLsizei * length, char *uniformName)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program, "GetActiveUniformName");
+ get_uniform_variable_name(ctx, shProg, index, bufsize, length,
+ uniformName);
+
+}
+
+void GLAPIENTRY
+_mesa_GetActiveUniformsiv(GLuint program, GLsizei uniformCount,
+ const GLuint * uniformIndices, GLenum pname,
+ GLint * param)
+{
+ unsigned k;
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program, "GetActiveUniformsiv");
+
+
+ for (k = 0; k < uniformCount; k++) {
+ param[k] = get_uniform_variable_info(shProg, uniformIndices[k], pname);
+ }
+}
+
+void
+_mesa_init_shader_uniform_buffer_objects(struct _glapi_table *exec)
+{
+/* GL_ARB_Uniform_Buffer_Object */
+ SET_GetActiveUniformBlockiv(exec, _mesa_GetActiveUniformBlockInfo);
+ SET_GetActiveUniformBlockName(exec, _mesa_GetActiveUniformBlockName);
+ SET_GetUniformIndices(exec, _mesa_GetUniformIndices);
+ SET_GetActiveUniformName(exec, _mesa_GetActiveUniformName);
+ SET_GetActiveUniformsiv(exec, _mesa_GetActiveUniformsiv);
+}
diff --git a/src/mesa/main/ubo.h b/src/mesa/main/ubo.h
new file mode 100644
index 0000000..32ea8f9
--- /dev/null
+++ b/src/mesa/main/ubo.h
@@ -0,0 +1,33 @@
+#ifndef UBO_H
+#define UBO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include "glheader.h"
+struct _glapi_table;
+
+void GLAPIENTRY
+_mesa_GetActiveUniformBlockInfo (GLuint, GLuint, GLenum, GLint *);
+
+extern void GLAPIENTRY
+_mesa_GetActiveUniformBlockName (GLuint, GLuint, GLsizei, GLint *, char *);
+
+extern void GLAPIENTRY
+_mesa_GetUniformIndices (GLuint, GLsizei, const char **, GLuint *);
+
+extern void GLAPIENTRY
+_mesa_GetActiveUniformName (GLuint, GLuint, GLsizei, GLsizei *, char *);
+
+void GLAPIENTRY
+_mesa_GetActiveUniformsiv (GLuint, GLsizei, const GLuint *, GLenum, GLint *);
+
+void _mesa_init_shader_uniform_buffer_objects (struct _glapi_table *exec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // UBO_H
diff --git a/src/mesa/sources.mak b/src/mesa/sources.mak
index e72a1ce..c87b4be 100644
--- a/src/mesa/sources.mak
+++ b/src/mesa/sources.mak
@@ -106,6 +106,7 @@ MAIN_SOURCES = \
MAIN_CXX_SOURCES = \
main/ff_fragment_shader.cpp \
main/shader_query.cpp \
+ main/ubo.cpp \
main/uniform_query.cpp
MATH_SOURCES = \
diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c
index adac92f..c8ee6d7 100644
--- a/src/mesa/state_tracker/st_cb_bufferobjects.c
+++ b/src/mesa/state_tracker/st_cb_bufferobjects.c
@@ -128,7 +128,8 @@ st_bufferobj_subdata(struct gl_context *ctx,
*/
pipe_buffer_write(st_context(ctx)->pipe,
st_obj->buffer,
- offset, size, data);
+ offset, size, data);
+
}
@@ -195,6 +196,9 @@ st_bufferobj_data(struct gl_context *ctx,
case GL_ELEMENT_ARRAY_BUFFER_ARB:
bind = PIPE_BIND_INDEX_BUFFER;
break;
+ case GL_UNIFORM_BUFFER:
+ bind = PIPE_BIND_CONSTANT_BUFFER;
+ break;
default:
bind = 0;
}
--
1.7.7
More information about the mesa-dev
mailing list