[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