u_upload_mgr: new features
- Added a parameter to specify a minimum offset that should be returned. r300g needs this to better implement user buffer uploads. This weird requirement comes from the fact that the Radeon DRM doesn't support negative offsets. - Added a parameter to notify a driver that the upload flush occured. A driver may skip buffer validation if there was no flush, resulting in a better performance. - Added a new upload function that returns a pointer to the upload buffer directly, so that the buffer can be filled e.g. by the translate module.
This commit is contained in:
parent
8b7bd3ce88
commit
06286110b4
|
@ -43,7 +43,7 @@ struct u_upload_mgr {
|
|||
|
||||
unsigned default_size;
|
||||
unsigned alignment;
|
||||
unsigned usage;
|
||||
unsigned bind;
|
||||
|
||||
/* The active buffer:
|
||||
*/
|
||||
|
@ -58,7 +58,7 @@ struct u_upload_mgr {
|
|||
struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
|
||||
unsigned default_size,
|
||||
unsigned alignment,
|
||||
unsigned usage )
|
||||
unsigned bind )
|
||||
{
|
||||
struct u_upload_mgr *upload = CALLOC_STRUCT( u_upload_mgr );
|
||||
if (!upload)
|
||||
|
@ -67,7 +67,7 @@ struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
|
|||
upload->pipe = pipe;
|
||||
upload->default_size = default_size;
|
||||
upload->alignment = alignment;
|
||||
upload->usage = usage;
|
||||
upload->bind = bind;
|
||||
upload->buffer = NULL;
|
||||
|
||||
return upload;
|
||||
|
@ -115,7 +115,7 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload,
|
|||
size = align(MAX2(upload->default_size, min_size), 4096);
|
||||
|
||||
upload->buffer = pipe_buffer_create( upload->pipe->screen,
|
||||
upload->usage,
|
||||
upload->bind,
|
||||
size );
|
||||
if (upload->buffer == NULL)
|
||||
goto fail;
|
||||
|
@ -135,33 +135,61 @@ fail:
|
|||
return PIPE_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
enum pipe_error u_upload_data( struct u_upload_mgr *upload,
|
||||
unsigned size,
|
||||
const void *data,
|
||||
unsigned *out_offset,
|
||||
struct pipe_resource **outbuf )
|
||||
enum pipe_error u_upload_alloc( struct u_upload_mgr *upload,
|
||||
unsigned min_out_offset,
|
||||
unsigned size,
|
||||
unsigned *out_offset,
|
||||
struct pipe_resource **outbuf,
|
||||
boolean *flushed,
|
||||
void **ptr )
|
||||
{
|
||||
unsigned alloc_size = align( size, upload->alignment );
|
||||
enum pipe_error ret = PIPE_OK;
|
||||
unsigned alloc_offset = align(min_out_offset, upload->alignment);
|
||||
unsigned offset;
|
||||
|
||||
if (upload->offset + alloc_size > upload->size) {
|
||||
ret = u_upload_alloc_buffer( upload, alloc_size );
|
||||
if (MAX2(upload->offset, alloc_offset) + alloc_size > upload->size) {
|
||||
enum pipe_error ret = u_upload_alloc_buffer(upload,
|
||||
alloc_offset + alloc_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*flushed = TRUE;
|
||||
} else {
|
||||
*flushed = FALSE;
|
||||
}
|
||||
|
||||
assert(upload->offset < upload->buffer->width0);
|
||||
assert(upload->offset + size <= upload->buffer->width0);
|
||||
offset = MAX2(upload->offset, alloc_offset);
|
||||
|
||||
assert(offset < upload->buffer->width0);
|
||||
assert(offset + size <= upload->buffer->width0);
|
||||
assert(size);
|
||||
|
||||
memcpy(upload->map + upload->offset, data, size);
|
||||
*ptr = upload->map + offset;
|
||||
|
||||
/* Emit the return values:
|
||||
*/
|
||||
pipe_resource_reference( outbuf, upload->buffer );
|
||||
*out_offset = upload->offset;
|
||||
upload->offset += alloc_size;
|
||||
*out_offset = offset;
|
||||
upload->offset = offset + alloc_size;
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
enum pipe_error u_upload_data( struct u_upload_mgr *upload,
|
||||
unsigned min_out_offset,
|
||||
unsigned size,
|
||||
const void *data,
|
||||
unsigned *out_offset,
|
||||
struct pipe_resource **outbuf,
|
||||
boolean *flushed )
|
||||
{
|
||||
uint8_t *ptr;
|
||||
enum pipe_error ret = u_upload_alloc(upload, min_out_offset, size,
|
||||
out_offset, outbuf, flushed,
|
||||
(void**)&ptr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(ptr, data, size);
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
@ -172,11 +200,13 @@ enum pipe_error u_upload_data( struct u_upload_mgr *upload,
|
|||
* renders or DrawElements calls.
|
||||
*/
|
||||
enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
|
||||
unsigned min_out_offset,
|
||||
unsigned offset,
|
||||
unsigned size,
|
||||
struct pipe_resource *inbuf,
|
||||
unsigned *out_offset,
|
||||
struct pipe_resource **outbuf )
|
||||
struct pipe_resource **outbuf,
|
||||
boolean *flushed )
|
||||
{
|
||||
enum pipe_error ret = PIPE_OK;
|
||||
struct pipe_transfer *transfer = NULL;
|
||||
|
@ -195,13 +225,12 @@ enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
|
|||
if (0)
|
||||
debug_printf("upload ptr %p ofs %d sz %d\n", map, offset, size);
|
||||
|
||||
ret = u_upload_data( upload,
|
||||
ret = u_upload_data( upload,
|
||||
min_out_offset,
|
||||
size,
|
||||
map + offset,
|
||||
out_offset,
|
||||
outbuf );
|
||||
if (ret)
|
||||
goto done;
|
||||
outbuf, flushed );
|
||||
|
||||
done:
|
||||
if (map)
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#ifndef U_UPLOAD_MGR_H
|
||||
#define U_UPLOAD_MGR_H
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
|
||||
struct pipe_context;
|
||||
struct pipe_resource;
|
||||
|
||||
|
@ -39,7 +41,7 @@ struct pipe_resource;
|
|||
struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
|
||||
unsigned default_size,
|
||||
unsigned alignment,
|
||||
unsigned usage );
|
||||
unsigned bind );
|
||||
|
||||
void u_upload_destroy( struct u_upload_mgr *upload );
|
||||
|
||||
|
@ -53,20 +55,55 @@ void u_upload_destroy( struct u_upload_mgr *upload );
|
|||
*/
|
||||
void u_upload_flush( struct u_upload_mgr *upload );
|
||||
|
||||
/**
|
||||
* Sub-allocate new memory from the upload buffer.
|
||||
*
|
||||
* \param upload Upload manager
|
||||
* \param min_out_offset Minimum offset that should be returned in out_offset.
|
||||
* \param size Size of the allocation.
|
||||
* \param out_offset Pointer to where the new buffer offset will be returned.
|
||||
* \param outbuf Pointer to where the upload buffer will be returned.
|
||||
* \param flushed Whether the upload buffer was flushed.
|
||||
* \param ptr Pointer to the allocated memory that is returned.
|
||||
*/
|
||||
enum pipe_error u_upload_alloc( struct u_upload_mgr *upload,
|
||||
unsigned min_out_offset,
|
||||
unsigned size,
|
||||
unsigned *out_offset,
|
||||
struct pipe_resource **outbuf,
|
||||
boolean *flushed,
|
||||
void **ptr );
|
||||
|
||||
|
||||
/**
|
||||
* Allocate and write data to the upload buffer.
|
||||
*
|
||||
* Same as u_upload_alloc, but in addition to that, it copies "data"
|
||||
* to the pointer returned from u_upload_alloc.
|
||||
*/
|
||||
enum pipe_error u_upload_data( struct u_upload_mgr *upload,
|
||||
unsigned min_out_offset,
|
||||
unsigned size,
|
||||
const void *data,
|
||||
unsigned *out_offset,
|
||||
struct pipe_resource **outbuf );
|
||||
struct pipe_resource **outbuf,
|
||||
boolean *flushed );
|
||||
|
||||
|
||||
/**
|
||||
* Allocate and copy an input buffer to the upload buffer.
|
||||
*
|
||||
* Same as u_upload_data, except that the input data comes from a buffer
|
||||
* instead of a user pointer.
|
||||
*/
|
||||
enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
|
||||
unsigned min_out_offset,
|
||||
unsigned offset,
|
||||
unsigned size,
|
||||
struct pipe_resource *inbuf,
|
||||
unsigned *out_offset,
|
||||
struct pipe_resource **outbuf );
|
||||
struct pipe_resource **outbuf,
|
||||
boolean *flushed );
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -89,13 +89,16 @@ static int brw_prepare_vertices(struct brw_context *brw)
|
|||
vb->buffer->width0 - vb->buffer_offset :
|
||||
MAX2(vb->buffer->width0 - vb->buffer_offset,
|
||||
vb->stride * (max_index + 1 - min_index)));
|
||||
boolean flushed;
|
||||
|
||||
ret = u_upload_buffer( brw->vb.upload_vertex,
|
||||
ret = u_upload_buffer( brw->vb.upload_vertex,
|
||||
0,
|
||||
vb->buffer_offset + min_index * vb->stride,
|
||||
size,
|
||||
vb->buffer,
|
||||
&offset,
|
||||
&upload_buf );
|
||||
&upload_buf,
|
||||
&flushed );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -251,13 +254,16 @@ static int brw_prepare_indices(struct brw_context *brw)
|
|||
/* Turn userbuffer into a proper hardware buffer?
|
||||
*/
|
||||
if (brw_buffer_is_user_buffer(index_buffer)) {
|
||||
boolean flushed;
|
||||
|
||||
ret = u_upload_buffer( brw->vb.upload_index,
|
||||
0,
|
||||
index_offset,
|
||||
ib_size,
|
||||
index_buffer,
|
||||
&offset,
|
||||
&upload_buf );
|
||||
&upload_buf,
|
||||
&flushed );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -62,15 +62,16 @@ void r300_upload_index_buffer(struct r300_context *r300,
|
|||
unsigned count)
|
||||
{
|
||||
unsigned index_offset;
|
||||
boolean flushed;
|
||||
uint8_t *ptr = r300_buffer(*index_buffer)->user_buffer;
|
||||
|
||||
*index_buffer = NULL;
|
||||
|
||||
u_upload_data(r300->upload_ib,
|
||||
count * index_size,
|
||||
0, count * index_size,
|
||||
ptr + (*start * index_size),
|
||||
&index_offset,
|
||||
index_buffer);
|
||||
index_buffer, &flushed);
|
||||
|
||||
*start = index_offset / index_size;
|
||||
}
|
||||
|
@ -78,6 +79,7 @@ void r300_upload_index_buffer(struct r300_context *r300,
|
|||
void r300_upload_user_buffers(struct r300_context *r300)
|
||||
{
|
||||
int i, nr = r300->velems->count;
|
||||
boolean flushed;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
struct pipe_vertex_buffer *vb =
|
||||
|
@ -85,9 +87,9 @@ void r300_upload_user_buffers(struct r300_context *r300)
|
|||
|
||||
if (r300_buffer_is_user_buffer(vb->buffer)) {
|
||||
u_upload_data(r300->upload_vb,
|
||||
vb->buffer->width0,
|
||||
0, vb->buffer->width0,
|
||||
r300_buffer(vb->buffer)->user_buffer,
|
||||
&vb->buffer_offset, &vb->buffer);
|
||||
&vb->buffer_offset, &vb->buffer, &flushed);
|
||||
|
||||
r300->validate_buffers = TRUE;
|
||||
r300->vertex_arrays_dirty = TRUE;
|
||||
|
|
|
@ -120,14 +120,17 @@ svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,
|
|||
if (index_buffer &&
|
||||
svga_buffer_is_user_buffer(index_buffer))
|
||||
{
|
||||
boolean flushed;
|
||||
assert( index_buffer->width0 >= index_offset + count * index_size );
|
||||
|
||||
ret = u_upload_buffer( hwtnl->upload_ib,
|
||||
0,
|
||||
index_offset,
|
||||
count * index_size,
|
||||
index_buffer,
|
||||
&index_offset,
|
||||
&upload_buffer );
|
||||
&upload_buffer,
|
||||
&flushed );
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
|
|
|
@ -57,12 +57,14 @@ upload_user_buffers( struct svga_context *svga )
|
|||
struct svga_buffer *buffer = svga_buffer(svga->curr.vb[i].buffer);
|
||||
|
||||
if (!buffer->uploaded.buffer) {
|
||||
boolean flushed;
|
||||
ret = u_upload_buffer( svga->upload_vb,
|
||||
0,
|
||||
0, 0,
|
||||
buffer->b.b.width0,
|
||||
&buffer->b.b,
|
||||
&buffer->uploaded.offset,
|
||||
&buffer->uploaded.buffer );
|
||||
&buffer->uploaded.buffer,
|
||||
&flushed);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
Loading…
Reference in New Issue