diff options
-rw-r--r-- | src/mesa/Makefile.sources | 1 | ||||
-rw-r--r-- | src/mesa/main/glthread_bufferobj.c | 301 | ||||
-rw-r--r-- | src/mesa/main/marshal.c | 277 | ||||
-rw-r--r-- | src/mesa/meson.build | 1 |
4 files changed, 303 insertions, 277 deletions
diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources index b09c019546b..d14c8d1a03d 100644 --- a/src/mesa/Makefile.sources +++ b/src/mesa/Makefile.sources @@ -125,6 +125,7 @@ MAIN_FILES = \ main/glspirv.h \ main/glthread.c \ main/glthread.h \ + main/glthread_bufferobj.c \ main/glthread_varray.c \ main/glheader.h \ main/hash.c \ diff --git a/src/mesa/main/glthread_bufferobj.c b/src/mesa/main/glthread_bufferobj.c new file mode 100644 index 00000000000..c7bafc44220 --- /dev/null +++ b/src/mesa/main/glthread_bufferobj.c @@ -0,0 +1,301 @@ +/* + * Copyright © 2012 Intel Corporation + * + * 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 (including the next + * paragraph) 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 + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +#include "marshal.h" +#include "dispatch.h" + +/** Tracks the current bindings for the vertex array and index array buffers. + * + * This is part of what we need to enable glthread on compat-GL contexts that + * happen to use VBOs, without also supporting the full tracking of VBO vs + * user vertex array bindings per attribute on each vertex array for + * determining what to upload at draw call time. + * + * Note that GL core makes it so that a buffer binding with an invalid handle + * in the "buffer" parameter will throw an error, and then a + * glVertexAttribPointer() that followsmight not end up pointing at a VBO. + * However, in GL core the draw call would throw an error as well, so we don't + * really care if our tracking is wrong for this case -- we never need to + * marshal user data for draw calls, and the unmarshal will just generate an + * error or not as appropriate. + * + * For compatibility GL, we do need to accurately know whether the draw call + * on the unmarshal side will dereference a user pointer or load data from a + * VBO per vertex. That would make it seem like we need to track whether a + * "buffer" is valid, so that we can know when an error will be generated + * instead of updating the binding. However, compat GL has the ridiculous + * feature that if you pass a bad name, it just gens a buffer object for you, + * so we escape without having to know if things are valid or not. + */ +void +_mesa_glthread_BindBuffer(struct gl_context *ctx, GLenum target, GLuint buffer) +{ + struct glthread_state *glthread = ctx->GLThread; + + switch (target) { + case GL_ARRAY_BUFFER: + glthread->vertex_array_is_vbo = (buffer != 0); + break; + case GL_ELEMENT_ARRAY_BUFFER: + /* The current element array buffer binding is actually tracked in the + * vertex array object instead of the context, so this would need to + * change on vertex array object updates. + */ + glthread->CurrentVAO->IndexBufferIsUserPointer = buffer != 0; + break; + case GL_DRAW_INDIRECT_BUFFER: + glthread->draw_indirect_buffer_is_vbo = buffer != 0; + break; + } +} + + +/* BufferData: marshalled asynchronously */ +struct marshal_cmd_BufferData +{ + struct marshal_cmd_base cmd_base; + GLuint target_or_name; + GLsizeiptr size; + GLenum usage; + const GLvoid *data_external_mem; + bool data_null; /* If set, no data follows for "data" */ + bool named; + bool ext_dsa; + /* Next size bytes are GLubyte data[size] */ +}; + +void +_mesa_unmarshal_BufferData(struct gl_context *ctx, + const struct marshal_cmd_BufferData *cmd) +{ + const GLuint target_or_name = cmd->target_or_name; + const GLsizei size = cmd->size; + const GLenum usage = cmd->usage; + const void *data; + + if (cmd->data_null) + data = NULL; + else if (!cmd->named && target_or_name == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) + data = cmd->data_external_mem; + else + data = (const void *) (cmd + 1); + + if (cmd->ext_dsa) { + CALL_NamedBufferDataEXT(ctx->CurrentServerDispatch, + (target_or_name, size, data, usage)); + } else if (cmd->named) { + CALL_NamedBufferData(ctx->CurrentServerDispatch, + (target_or_name, size, data, usage)); + } else { + CALL_BufferData(ctx->CurrentServerDispatch, + (target_or_name, size, data, usage)); + } +} + +void +_mesa_unmarshal_NamedBufferData(struct gl_context *ctx, + const struct marshal_cmd_NamedBufferData *cmd) +{ + unreachable("never used - all BufferData variants use DISPATCH_CMD_BufferData"); +} + +void +_mesa_unmarshal_NamedBufferDataEXT(struct gl_context *ctx, + const struct marshal_cmd_NamedBufferDataEXT *cmd) +{ + unreachable("never used - all BufferData variants use DISPATCH_CMD_BufferData"); +} + +static void +_mesa_marshal_BufferData_merged(GLuint target_or_name, GLsizeiptr size, + const GLvoid *data, GLenum usage, bool named, + bool ext_dsa, const char *func) +{ + GET_CURRENT_CONTEXT(ctx); + bool external_mem = !named && + target_or_name == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD; + bool copy_data = data && !external_mem; + int cmd_size = sizeof(struct marshal_cmd_BufferData) + (copy_data ? size : 0); + + if (unlikely(size < 0 || size > INT_MAX || cmd_size < 0 || + cmd_size > MARSHAL_MAX_CMD_SIZE || + (named && target_or_name == 0))) { + _mesa_glthread_finish_before(ctx, func); + if (named) { + CALL_NamedBufferData(ctx->CurrentServerDispatch, + (target_or_name, size, data, usage)); + } else { + CALL_BufferData(ctx->CurrentServerDispatch, + (target_or_name, size, data, usage)); + } + return; + } + + struct marshal_cmd_BufferData *cmd = + _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BufferData, + cmd_size); + + cmd->target_or_name = target_or_name; + cmd->size = size; + cmd->usage = usage; + cmd->data_null = !data; + cmd->named = named; + cmd->ext_dsa = ext_dsa; + cmd->data_external_mem = data; + + if (copy_data) { + char *variable_data = (char *) (cmd + 1); + memcpy(variable_data, data, size); + } +} + +void GLAPIENTRY +_mesa_marshal_BufferData(GLenum target, GLsizeiptr size, const GLvoid * data, + GLenum usage) +{ + _mesa_marshal_BufferData_merged(target, size, data, usage, false, false, + "BufferData"); +} + +void GLAPIENTRY +_mesa_marshal_NamedBufferData(GLuint buffer, GLsizeiptr size, + const GLvoid * data, GLenum usage) +{ + _mesa_marshal_BufferData_merged(buffer, size, data, usage, true, false, + "NamedBufferData"); +} + +void GLAPIENTRY +_mesa_marshal_NamedBufferDataEXT(GLuint buffer, GLsizeiptr size, + const GLvoid *data, GLenum usage) +{ + _mesa_marshal_BufferData_merged(buffer, size, data, usage, true, true, + "NamedBufferDataEXT"); +} + + +/* BufferSubData: marshalled asynchronously */ +struct marshal_cmd_BufferSubData +{ + struct marshal_cmd_base cmd_base; + GLenum target_or_name; + GLintptr offset; + GLsizeiptr size; + bool named; + bool ext_dsa; + /* Next size bytes are GLubyte data[size] */ +}; + +void +_mesa_unmarshal_BufferSubData(struct gl_context *ctx, + const struct marshal_cmd_BufferSubData *cmd) +{ + const GLenum target_or_name = cmd->target_or_name; + const GLintptr offset = cmd->offset; + const GLsizeiptr size = cmd->size; + const void *data = (const void *) (cmd + 1); + + if (cmd->ext_dsa) { + CALL_NamedBufferSubDataEXT(ctx->CurrentServerDispatch, + (target_or_name, offset, size, data)); + } else if (cmd->named) { + CALL_NamedBufferSubData(ctx->CurrentServerDispatch, + (target_or_name, offset, size, data)); + } else { + CALL_BufferSubData(ctx->CurrentServerDispatch, + (target_or_name, offset, size, data)); + } +} + +void +_mesa_unmarshal_NamedBufferSubData(struct gl_context *ctx, + const struct marshal_cmd_NamedBufferSubData *cmd) +{ + unreachable("never used - all BufferSubData variants use DISPATCH_CMD_BufferSubData"); +} + +void +_mesa_unmarshal_NamedBufferSubDataEXT(struct gl_context *ctx, + const struct marshal_cmd_NamedBufferSubDataEXT *cmd) +{ + unreachable("never used - all BufferSubData variants use DISPATCH_CMD_BufferSubData"); +} + +static void +_mesa_marshal_BufferSubData_merged(GLuint target_or_name, GLintptr offset, + GLsizeiptr size, const GLvoid *data, + bool named, bool ext_dsa, const char *func) +{ + GET_CURRENT_CONTEXT(ctx); + size_t cmd_size = sizeof(struct marshal_cmd_BufferSubData) + size; + + if (unlikely(size < 0 || size > INT_MAX || cmd_size < 0 || + cmd_size > MARSHAL_MAX_CMD_SIZE || !data || + (named && target_or_name == 0))) { + _mesa_glthread_finish_before(ctx, func); + if (named) { + CALL_NamedBufferSubData(ctx->CurrentServerDispatch, + (target_or_name, offset, size, data)); + } else { + CALL_BufferSubData(ctx->CurrentServerDispatch, + (target_or_name, offset, size, data)); + } + return; + } + + struct marshal_cmd_BufferSubData *cmd = + _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BufferSubData, + cmd_size); + cmd->target_or_name = target_or_name; + cmd->offset = offset; + cmd->size = size; + cmd->named = named; + cmd->ext_dsa = ext_dsa; + + char *variable_data = (char *) (cmd + 1); + memcpy(variable_data, data, size); +} + +void GLAPIENTRY +_mesa_marshal_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, + const GLvoid * data) +{ + _mesa_marshal_BufferSubData_merged(target, offset, size, data, false, + false, "BufferSubData"); +} + +void GLAPIENTRY +_mesa_marshal_NamedBufferSubData(GLuint buffer, GLintptr offset, + GLsizeiptr size, const GLvoid * data) +{ + _mesa_marshal_BufferSubData_merged(buffer, offset, size, data, true, + false, "NamedBufferSubData"); +} + +void GLAPIENTRY +_mesa_marshal_NamedBufferSubDataEXT(GLuint buffer, GLintptr offset, + GLsizeiptr size, const GLvoid * data) +{ + _mesa_marshal_BufferSubData_merged(buffer, offset, size, data, true, + true, "NamedBufferSubDataEXT"); +} diff --git a/src/mesa/main/marshal.c b/src/mesa/main/marshal.c index d68dadaabca..a6610095783 100644 --- a/src/mesa/main/marshal.c +++ b/src/mesa/main/marshal.c @@ -121,280 +121,3 @@ _mesa_marshal_ShaderSource(GLuint shader, GLsizei count, } free(length_tmp); } - - -/** Tracks the current bindings for the vertex array and index array buffers. - * - * This is part of what we need to enable glthread on compat-GL contexts that - * happen to use VBOs, without also supporting the full tracking of VBO vs - * user vertex array bindings per attribute on each vertex array for - * determining what to upload at draw call time. - * - * Note that GL core makes it so that a buffer binding with an invalid handle - * in the "buffer" parameter will throw an error, and then a - * glVertexAttribPointer() that followsmight not end up pointing at a VBO. - * However, in GL core the draw call would throw an error as well, so we don't - * really care if our tracking is wrong for this case -- we never need to - * marshal user data for draw calls, and the unmarshal will just generate an - * error or not as appropriate. - * - * For compatibility GL, we do need to accurately know whether the draw call - * on the unmarshal side will dereference a user pointer or load data from a - * VBO per vertex. That would make it seem like we need to track whether a - * "buffer" is valid, so that we can know when an error will be generated - * instead of updating the binding. However, compat GL has the ridiculous - * feature that if you pass a bad name, it just gens a buffer object for you, - * so we escape without having to know if things are valid or not. - */ -void -_mesa_glthread_BindBuffer(struct gl_context *ctx, GLenum target, GLuint buffer) -{ - struct glthread_state *glthread = ctx->GLThread; - - switch (target) { - case GL_ARRAY_BUFFER: - glthread->vertex_array_is_vbo = (buffer != 0); - break; - case GL_ELEMENT_ARRAY_BUFFER: - /* The current element array buffer binding is actually tracked in the - * vertex array object instead of the context, so this would need to - * change on vertex array object updates. - */ - glthread->CurrentVAO->IndexBufferIsUserPointer = buffer != 0; - break; - case GL_DRAW_INDIRECT_BUFFER: - glthread->draw_indirect_buffer_is_vbo = buffer != 0; - break; - } -} - - -/* BufferData: marshalled asynchronously */ -struct marshal_cmd_BufferData -{ - struct marshal_cmd_base cmd_base; - GLuint target_or_name; - GLsizeiptr size; - GLenum usage; - const GLvoid *data_external_mem; - bool data_null; /* If set, no data follows for "data" */ - bool named; - bool ext_dsa; - /* Next size bytes are GLubyte data[size] */ -}; - -void -_mesa_unmarshal_BufferData(struct gl_context *ctx, - const struct marshal_cmd_BufferData *cmd) -{ - const GLuint target_or_name = cmd->target_or_name; - const GLsizei size = cmd->size; - const GLenum usage = cmd->usage; - const void *data; - - if (cmd->data_null) - data = NULL; - else if (!cmd->named && target_or_name == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) - data = cmd->data_external_mem; - else - data = (const void *) (cmd + 1); - - if (cmd->ext_dsa) { - CALL_NamedBufferDataEXT(ctx->CurrentServerDispatch, - (target_or_name, size, data, usage)); - } else if (cmd->named) { - CALL_NamedBufferData(ctx->CurrentServerDispatch, - (target_or_name, size, data, usage)); - } else { - CALL_BufferData(ctx->CurrentServerDispatch, - (target_or_name, size, data, usage)); - } -} - -void -_mesa_unmarshal_NamedBufferData(struct gl_context *ctx, - const struct marshal_cmd_NamedBufferData *cmd) -{ - unreachable("never used - all BufferData variants use DISPATCH_CMD_BufferData"); -} - -void -_mesa_unmarshal_NamedBufferDataEXT(struct gl_context *ctx, - const struct marshal_cmd_NamedBufferDataEXT *cmd) -{ - unreachable("never used - all BufferData variants use DISPATCH_CMD_BufferData"); -} - -static void -_mesa_marshal_BufferData_merged(GLuint target_or_name, GLsizeiptr size, - const GLvoid *data, GLenum usage, bool named, - bool ext_dsa, const char *func) -{ - GET_CURRENT_CONTEXT(ctx); - bool external_mem = !named && - target_or_name == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD; - bool copy_data = data && !external_mem; - int cmd_size = sizeof(struct marshal_cmd_BufferData) + (copy_data ? size : 0); - - if (unlikely(size < 0 || size > INT_MAX || cmd_size < 0 || - cmd_size > MARSHAL_MAX_CMD_SIZE || - (named && target_or_name == 0))) { - _mesa_glthread_finish_before(ctx, func); - if (named) { - CALL_NamedBufferData(ctx->CurrentServerDispatch, - (target_or_name, size, data, usage)); - } else { - CALL_BufferData(ctx->CurrentServerDispatch, - (target_or_name, size, data, usage)); - } - return; - } - - struct marshal_cmd_BufferData *cmd = - _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BufferData, - cmd_size); - - cmd->target_or_name = target_or_name; - cmd->size = size; - cmd->usage = usage; - cmd->data_null = !data; - cmd->named = named; - cmd->ext_dsa = ext_dsa; - cmd->data_external_mem = data; - - if (copy_data) { - char *variable_data = (char *) (cmd + 1); - memcpy(variable_data, data, size); - } -} - -void GLAPIENTRY -_mesa_marshal_BufferData(GLenum target, GLsizeiptr size, const GLvoid * data, - GLenum usage) -{ - _mesa_marshal_BufferData_merged(target, size, data, usage, false, false, - "BufferData"); -} - -void GLAPIENTRY -_mesa_marshal_NamedBufferData(GLuint buffer, GLsizeiptr size, - const GLvoid * data, GLenum usage) -{ - _mesa_marshal_BufferData_merged(buffer, size, data, usage, true, false, - "NamedBufferData"); -} - -void GLAPIENTRY -_mesa_marshal_NamedBufferDataEXT(GLuint buffer, GLsizeiptr size, - const GLvoid *data, GLenum usage) -{ - _mesa_marshal_BufferData_merged(buffer, size, data, usage, true, true, - "NamedBufferDataEXT"); -} - - -/* BufferSubData: marshalled asynchronously */ -struct marshal_cmd_BufferSubData -{ - struct marshal_cmd_base cmd_base; - GLenum target_or_name; - GLintptr offset; - GLsizeiptr size; - bool named; - bool ext_dsa; - /* Next size bytes are GLubyte data[size] */ -}; - -void -_mesa_unmarshal_BufferSubData(struct gl_context *ctx, - const struct marshal_cmd_BufferSubData *cmd) -{ - const GLenum target_or_name = cmd->target_or_name; - const GLintptr offset = cmd->offset; - const GLsizeiptr size = cmd->size; - const void *data = (const void *) (cmd + 1); - - if (cmd->ext_dsa) { - CALL_NamedBufferSubDataEXT(ctx->CurrentServerDispatch, - (target_or_name, offset, size, data)); - } else if (cmd->named) { - CALL_NamedBufferSubData(ctx->CurrentServerDispatch, - (target_or_name, offset, size, data)); - } else { - CALL_BufferSubData(ctx->CurrentServerDispatch, - (target_or_name, offset, size, data)); - } -} - -void -_mesa_unmarshal_NamedBufferSubData(struct gl_context *ctx, - const struct marshal_cmd_NamedBufferSubData *cmd) -{ - unreachable("never used - all BufferSubData variants use DISPATCH_CMD_BufferSubData"); -} - -void -_mesa_unmarshal_NamedBufferSubDataEXT(struct gl_context *ctx, - const struct marshal_cmd_NamedBufferSubDataEXT *cmd) -{ - unreachable("never used - all BufferSubData variants use DISPATCH_CMD_BufferSubData"); -} - -static void -_mesa_marshal_BufferSubData_merged(GLuint target_or_name, GLintptr offset, - GLsizeiptr size, const GLvoid *data, - bool named, bool ext_dsa, const char *func) -{ - GET_CURRENT_CONTEXT(ctx); - size_t cmd_size = sizeof(struct marshal_cmd_BufferSubData) + size; - - if (unlikely(size < 0 || size > INT_MAX || cmd_size < 0 || - cmd_size > MARSHAL_MAX_CMD_SIZE || !data || - (named && target_or_name == 0))) { - _mesa_glthread_finish_before(ctx, func); - if (named) { - CALL_NamedBufferSubData(ctx->CurrentServerDispatch, - (target_or_name, offset, size, data)); - } else { - CALL_BufferSubData(ctx->CurrentServerDispatch, - (target_or_name, offset, size, data)); - } - return; - } - - struct marshal_cmd_BufferSubData *cmd = - _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_BufferSubData, - cmd_size); - cmd->target_or_name = target_or_name; - cmd->offset = offset; - cmd->size = size; - cmd->named = named; - cmd->ext_dsa = ext_dsa; - - char *variable_data = (char *) (cmd + 1); - memcpy(variable_data, data, size); -} - -void GLAPIENTRY -_mesa_marshal_BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, - const GLvoid * data) -{ - _mesa_marshal_BufferSubData_merged(target, offset, size, data, false, - false, "BufferSubData"); -} - -void GLAPIENTRY -_mesa_marshal_NamedBufferSubData(GLuint buffer, GLintptr offset, - GLsizeiptr size, const GLvoid * data) -{ - _mesa_marshal_BufferSubData_merged(buffer, offset, size, data, true, - false, "NamedBufferSubData"); -} - -void GLAPIENTRY -_mesa_marshal_NamedBufferSubDataEXT(GLuint buffer, GLintptr offset, - GLsizeiptr size, const GLvoid * data) -{ - _mesa_marshal_BufferSubData_merged(buffer, offset, size, data, true, - true, "NamedBufferSubDataEXT"); -} diff --git a/src/mesa/meson.build b/src/mesa/meson.build index 2db8bbe8e9c..a55ec73bfe3 100644 --- a/src/mesa/meson.build +++ b/src/mesa/meson.build @@ -167,6 +167,7 @@ files_libmesa_common = files( 'main/glspirv.h', 'main/glthread.c', 'main/glthread.h', + 'main/glthread_bufferobj.c', 'main/glthread_varray.c', 'main/glheader.h', 'main/hash.c', |