diff options
-rw-r--r-- | src/mesa/state_tracker/st_cb_bufferobjects.c | 191 |
1 files changed, 104 insertions, 87 deletions
diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c index a9104a90095..6b64ba132c7 100644 --- a/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -164,107 +164,84 @@ st_bufferobj_get_subdata(struct gl_context *ctx, offset, size, data); } -static ALWAYS_INLINE GLboolean -bufferobj_data(struct gl_context *ctx, - GLenum target, - GLsizeiptrARB size, - const void *data, - struct gl_memory_object *memObj, - GLuint64 offset, - GLenum usage, - GLbitfield storageFlags, - struct gl_buffer_object *obj) -{ - struct st_context *st = st_context(ctx); - struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; - struct st_buffer_object *st_obj = st_buffer_object(obj); - struct st_memory_object *st_mem_obj = st_memory_object(memObj); - unsigned bind, pipe_usage, pipe_flags = 0; - - if (target != GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD && - size && st_obj->buffer && - st_obj->Base.Size == size && - st_obj->Base.Usage == usage && - st_obj->Base.StorageFlags == storageFlags) { - if (data) { - /* Just discard the old contents and write new data. - * This should be the same as creating a new buffer, but we avoid - * a lot of validation in Mesa. - */ - pipe->buffer_subdata(pipe, st_obj->buffer, - PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, - 0, size, data); - return GL_TRUE; - } else if (screen->get_param(screen, PIPE_CAP_INVALIDATE_BUFFER)) { - pipe->invalidate_resource(pipe, st_obj->buffer); - return GL_TRUE; - } - } - - st_obj->Base.Size = size; - st_obj->Base.Usage = usage; - st_obj->Base.StorageFlags = storageFlags; +/** + * Return bitmask of PIPE_BIND_x flags corresponding a GL buffer target. + */ +static unsigned +buffer_target_to_bind_flags(GLenum target) +{ switch (target) { case GL_PIXEL_PACK_BUFFER_ARB: case GL_PIXEL_UNPACK_BUFFER_ARB: - bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - break; + return PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; case GL_ARRAY_BUFFER_ARB: - bind = PIPE_BIND_VERTEX_BUFFER; - break; + return PIPE_BIND_VERTEX_BUFFER; case GL_ELEMENT_ARRAY_BUFFER_ARB: - bind = PIPE_BIND_INDEX_BUFFER; - break; + return PIPE_BIND_INDEX_BUFFER; case GL_TEXTURE_BUFFER: - bind = PIPE_BIND_SAMPLER_VIEW; - break; + return PIPE_BIND_SAMPLER_VIEW; case GL_TRANSFORM_FEEDBACK_BUFFER: - bind = PIPE_BIND_STREAM_OUTPUT; - break; + return PIPE_BIND_STREAM_OUTPUT; case GL_UNIFORM_BUFFER: - bind = PIPE_BIND_CONSTANT_BUFFER; - break; + return PIPE_BIND_CONSTANT_BUFFER; case GL_DRAW_INDIRECT_BUFFER: case GL_PARAMETER_BUFFER_ARB: - bind = PIPE_BIND_COMMAND_ARGS_BUFFER; - break; + return PIPE_BIND_COMMAND_ARGS_BUFFER; case GL_ATOMIC_COUNTER_BUFFER: case GL_SHADER_STORAGE_BUFFER: - bind = PIPE_BIND_SHADER_BUFFER; - break; + return PIPE_BIND_SHADER_BUFFER; case GL_QUERY_BUFFER: - bind = PIPE_BIND_QUERY_BUFFER; - break; + return PIPE_BIND_QUERY_BUFFER; default: - bind = 0; + return 0; } +} - /* Set usage. */ - if (st_obj->Base.Immutable) { + +/** + * Return bitmask of PIPE_RESOURCE_x flags corresponding to GL_MAP_x flags. + */ +static unsigned +storage_flags_to_buffer_flags(GLbitfield storageFlags) +{ + unsigned flags = 0; + if (storageFlags & GL_MAP_PERSISTENT_BIT) + flags |= PIPE_RESOURCE_FLAG_MAP_PERSISTENT; + if (storageFlags & GL_MAP_COHERENT_BIT) + flags |= PIPE_RESOURCE_FLAG_MAP_COHERENT; + if (storageFlags & GL_SPARSE_STORAGE_BIT_ARB) + flags |= PIPE_RESOURCE_FLAG_SPARSE; + return flags; +} + + +/** + * From a buffer object's target, immutability flag, storage flags and + * usage hint, return a pipe_resource_usage value (PIPE_USAGE_DYNAMIC, + * STREAM, etc). + */ +static const enum pipe_resource_usage +buffer_usage(GLenum target, GLboolean immutable, + GLbitfield storageFlags, GLenum usage) +{ + if (immutable) { /* BufferStorage */ if (storageFlags & GL_CLIENT_STORAGE_BIT) { if (storageFlags & GL_MAP_READ_BIT) - pipe_usage = PIPE_USAGE_STAGING; + return PIPE_USAGE_STAGING; else - pipe_usage = PIPE_USAGE_STREAM; + return PIPE_USAGE_STREAM; } else { - pipe_usage = PIPE_USAGE_DEFAULT; + return PIPE_USAGE_DEFAULT; } } else { /* BufferData */ switch (usage) { - case GL_STATIC_DRAW: - case GL_STATIC_COPY: - default: - pipe_usage = PIPE_USAGE_DEFAULT; - break; case GL_DYNAMIC_DRAW: case GL_DYNAMIC_COPY: - pipe_usage = PIPE_USAGE_DYNAMIC; - break; + return PIPE_USAGE_DYNAMIC; case GL_STREAM_DRAW: case GL_STREAM_COPY: /* XXX: Remove this test and fall-through when we have PBO unpacking @@ -272,31 +249,70 @@ bufferobj_data(struct gl_context *ctx, * have to make sure CPU reads are fast. */ if (target != GL_PIXEL_UNPACK_BUFFER_ARB) { - pipe_usage = PIPE_USAGE_STREAM; - break; + return PIPE_USAGE_STREAM; } /* fall through */ case GL_STATIC_READ: case GL_DYNAMIC_READ: case GL_STREAM_READ: - pipe_usage = PIPE_USAGE_STAGING; - break; + return PIPE_USAGE_STAGING; + case GL_STATIC_DRAW: + case GL_STATIC_COPY: + default: + return PIPE_USAGE_DEFAULT; } } +} - /* Set flags. */ - if (storageFlags & GL_MAP_PERSISTENT_BIT) - pipe_flags |= PIPE_RESOURCE_FLAG_MAP_PERSISTENT; - if (storageFlags & GL_MAP_COHERENT_BIT) - pipe_flags |= PIPE_RESOURCE_FLAG_MAP_COHERENT; - if (storageFlags & GL_SPARSE_STORAGE_BIT_ARB) - pipe_flags |= PIPE_RESOURCE_FLAG_SPARSE; + +static ALWAYS_INLINE GLboolean +bufferobj_data(struct gl_context *ctx, + GLenum target, + GLsizeiptrARB size, + const void *data, + struct gl_memory_object *memObj, + GLuint64 offset, + GLenum usage, + GLbitfield storageFlags, + struct gl_buffer_object *obj) +{ + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; + struct st_buffer_object *st_obj = st_buffer_object(obj); + struct st_memory_object *st_mem_obj = st_memory_object(memObj); + + if (target != GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD && + size && st_obj->buffer && + st_obj->Base.Size == size && + st_obj->Base.Usage == usage && + st_obj->Base.StorageFlags == storageFlags) { + if (data) { + /* Just discard the old contents and write new data. + * This should be the same as creating a new buffer, but we avoid + * a lot of validation in Mesa. + */ + pipe->buffer_subdata(pipe, st_obj->buffer, + PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, + 0, size, data); + return GL_TRUE; + } else if (screen->get_param(screen, PIPE_CAP_INVALIDATE_BUFFER)) { + pipe->invalidate_resource(pipe, st_obj->buffer); + return GL_TRUE; + } + } + + st_obj->Base.Size = size; + st_obj->Base.Usage = usage; + st_obj->Base.StorageFlags = storageFlags; pipe_resource_reference( &st_obj->buffer, NULL ); + const unsigned bindings = buffer_target_to_bind_flags(target); + if (ST_DEBUG & DEBUG_BUFFER) { debug_printf("Create buffer size %" PRId64 " bind 0x%x\n", - (int64_t) size, bind); + (int64_t) size, bindings); } if (size != 0) { @@ -305,9 +321,10 @@ bufferobj_data(struct gl_context *ctx, memset(&buffer, 0, sizeof buffer); buffer.target = PIPE_BUFFER; buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */ - buffer.bind = bind; - buffer.usage = pipe_usage; - buffer.flags = pipe_flags; + buffer.bind = bindings; + buffer.usage = + buffer_usage(target, st_obj->Base.Immutable, storageFlags, usage); + buffer.flags = storage_flags_to_buffer_flags(storageFlags); buffer.width0 = size; buffer.height0 = 1; buffer.depth0 = 1; |