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 | 369 ++++++++++++++++++++++++++ src/mesa/main/ubo.h | 39 +++ src/mesa/sources.mak | 1 + src/mesa/state_tracker/st_cb_bufferobjects.c | 6 +- 6 files changed, 427 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..f8f6445 --- /dev/null +++ b/src/mesa/main/ubo.cpp @@ -0,0 +1,369 @@ +/* + * 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, bool& pname_is_valid) +{ + pname_is_valid = true; + + struct gl_uniform_buffer_object current_ubo = + shProg->UniformBufferObject[ubo_index]; + + switch (query) { + case GL_UNIFORM_BLOCK_BINDING: + *data = current_ubo.BindingPoint; // TODO : find a nice way to get buffer id + break; + case GL_UNIFORM_BLOCK_DATA_SIZE: + *data = current_ubo.Size; + printf("%s size is %d\n",current_ubo.Name,*data); + 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: + pname_is_valid = false; + 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; +} + +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]; + + _mesa_copy_string(buffer,bufsize,length,current_ubo.Name); + + return; +} + +static void +get_uniform_variable_name(struct gl_context *ctx, + struct gl_shader_program *sh, GLuint index, + GLsizei bufsize, GLsizei * length, + char *uniformName) +{ + + _mesa_copy_string(uniformName,bufsize,length,sh->IndexedUBOVariables[index].Name); + return; +} + +static GLint +get_uniform_variable_info(struct gl_shader_program *sh, GLuint index, + GLenum pname, bool& pname_is_valid) +{ + pname_is_valid = true; + uint starting_index = sh->NumUserUniformStorage; + if (index >= starting_index) { + const struct gl_indexed_ubo_variable& var = + sh->IndexedUBOVariables[index - starting_index]; + switch (pname) { + case GL_UNIFORM_TYPE: + return var.Type; + case GL_UNIFORM_SIZE: + if (var.Stride > 0) + return var.Size; + else + 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; + default: + pname_is_valid = false; + } + } + + return GL_INVALID_VALUE; +} + +static void +bind_uniform(struct gl_context *ctx, struct gl_shader_program *sh, GLuint index, GLuint binding) +{ + if (index > sh->UBOCount || index < 0) + _mesa_error(ctx, GL_INVALID_VALUE, + "UniformBlockBinding(uniformIndex)"); + + ctx->UniformBufferObject.UBOIndexes[binding] = sh->UniformBufferObject[index].Index + 1; +} + +/** Note : the following functions should be able to run even if program has failed to build + * (BUT ! a link attempt must have occured for this program before) : + * - GetUniformBlockIndex + * - GetActiveUniformBlockName + * - GetActiveUniformBlockiv + * - GetUniformIndices + * - GetActiveUniformName + * - GetActiveUniform + * - GetActiveUniformsiv + * + * The spec is not clear what is the behaviour in failed link case. + */ + +void GLAPIENTRY +_mesa_GetActiveUniformBlockiv(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"); + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, "GetActiveUniformBlockiv(program not linked)"); + return; + } + if (ubo_index >= shProg->UBOCount) { + _mesa_error(ctx, GL_INVALID_VALUE, "GetActiveUniformBlockiv(uniformBlockIndex)"); + return; + } + bool pname_status; + get_ubo_info(ctx, shProg, ubo_index, pname, params, pname_status); + if (!pname) { + _mesa_error(ctx, GL_INVALID_ENUM, "GetActiveUniformBlockiv(pname)"); + return; + } +} + +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"); + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, "GetActiveUniformBlockName(program not linked)"); + return; + } + if (bufsize < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "GetActiveUniformBlockName(bufSize)"); + } + if (ubo_index >= shProg->UBOCount) { + _mesa_error(ctx, GL_INVALID_VALUE, "GetActiveUniformBlockName(uniformBlockIndex)"); + return; + } + + 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"); + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, "GetUniformIndices(program not linked)"); + return; + } + if (number_of_variables < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "GetUniformIndices(uniformCount)"); + return; + } + + 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"); + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, "GetActiveUniformName(program not linked)"); + return; + } + if (bufsize < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "GetActiveUniformName(bufSize)"); + return; + } + if (index > (shProg->NumUserUniformStorage + shProg->IndexedVariableCount)) { + _mesa_error(ctx, GL_INVALID_VALUE, "GetActiveUniformName(uniformIndex)"); + return; + } + + 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"); + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, "GetActiveUniformsiv(program not linked)"); + return; + } + if (uniformCount < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "GetActiveUniformiv(uniformCount)"); + return; + } + const unsigned active_uniforms = shProg->NumUserUniformStorage + shProg->IndexedVariableCount; + for (k = 0; k < uniformCount; k++) { + if (uniformIndices[k] > active_uniforms) { + _mesa_error(ctx, GL_INVALID_VALUE, "GetActiveUniformsiv(uniformIndices)"); + return; + } + } + + bool pname_status; + param[0] = get_uniform_variable_info(shProg, uniformIndices[0], pname,pname_status); + if (!pname) { + _mesa_error(ctx, GL_INVALID_ENUM, "GetActiveUniformsiv(pname)"); + return; + } + for (k = 1; k < uniformCount; k++) { + param[k] = get_uniform_variable_info(shProg, uniformIndices[k], pname,pname_status); + } +} + +void GLAPIENTRY +_mesa_UniformBlockBinding(GLuint prog, GLuint uboIndex, GLuint uboBinding) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, prog, "UniformBlockBinding(program)"); + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, "UniformBlockBinding(program not linked)"); + return; + } + if (uboIndex >= shProg->UBOCount) { + _mesa_error(ctx, GL_INVALID_VALUE, "GetActiveUniformBlockName(uniformBlockIndex)"); + return; + } + + bind_uniform(ctx,shProg,uboIndex,uboBinding); +} + +GLuint GLAPIENTRY +_mesa_GetActiveUniformBlockIndex(GLuint prog, const char* uniformBlockName) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, prog, "UniformBlockBinding(program)"); + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, "GetActiveUnifromBlockIndex(program not linked)"); + return GL_INVALID_VALUE; + } + for (unsigned i = 0; i < shProg->UBOCount; i++) + { + if (strcmp(uniformBlockName,shProg->UniformBufferObject[i].Name)==0) + return i; + } + return GL_INVALID_VALUE; +} + +void +_mesa_init_shader_uniform_buffer_objects(struct _glapi_table *exec) +{ +/* GL_ARB_Uniform_Buffer_Object */ + SET_GetUniformBlockIndex(exec,_mesa_GetActiveUniformBlockIndex); + SET_GetActiveUniformBlockiv(exec, _mesa_GetActiveUniformBlockiv); + SET_GetActiveUniformBlockName(exec, _mesa_GetActiveUniformBlockName); + SET_GetUniformIndices(exec, _mesa_GetUniformIndices); + SET_GetActiveUniformName(exec, _mesa_GetActiveUniformName); + SET_GetActiveUniformsiv(exec, _mesa_GetActiveUniformsiv); + SET_UniformBlockBinding(exec,_mesa_UniformBlockBinding); +} diff --git a/src/mesa/main/ubo.h b/src/mesa/main/ubo.h new file mode 100644 index 0000000..99862fa --- /dev/null +++ b/src/mesa/main/ubo.h @@ -0,0 +1,39 @@ +#ifndef UBO_H +#define UBO_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "glheader.h" +struct _glapi_table; + +void GLAPIENTRY +_mesa_GetActiveUniformBlockiv (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); + +void GLAPIENTRY +_mesa_UniformBlockBinding(GLuint prog, GLuint uboIndex, GLuint uboBinding); + +GLuint GLAPIENTRY +_mesa_GetActiveUniformBlockIndex(GLuint prog, const char* uniformBlockName); + +#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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev