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 default_size;
|
||||||
unsigned alignment;
|
unsigned alignment;
|
||||||
unsigned usage;
|
unsigned bind;
|
||||||
|
|
||||||
/* The active buffer:
|
/* The active buffer:
|
||||||
*/
|
*/
|
||||||
|
@ -58,7 +58,7 @@ struct u_upload_mgr {
|
||||||
struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
|
struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
|
||||||
unsigned default_size,
|
unsigned default_size,
|
||||||
unsigned alignment,
|
unsigned alignment,
|
||||||
unsigned usage )
|
unsigned bind )
|
||||||
{
|
{
|
||||||
struct u_upload_mgr *upload = CALLOC_STRUCT( u_upload_mgr );
|
struct u_upload_mgr *upload = CALLOC_STRUCT( u_upload_mgr );
|
||||||
if (!upload)
|
if (!upload)
|
||||||
|
@ -67,7 +67,7 @@ struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
|
||||||
upload->pipe = pipe;
|
upload->pipe = pipe;
|
||||||
upload->default_size = default_size;
|
upload->default_size = default_size;
|
||||||
upload->alignment = alignment;
|
upload->alignment = alignment;
|
||||||
upload->usage = usage;
|
upload->bind = bind;
|
||||||
upload->buffer = NULL;
|
upload->buffer = NULL;
|
||||||
|
|
||||||
return upload;
|
return upload;
|
||||||
|
@ -115,7 +115,7 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload,
|
||||||
size = align(MAX2(upload->default_size, min_size), 4096);
|
size = align(MAX2(upload->default_size, min_size), 4096);
|
||||||
|
|
||||||
upload->buffer = pipe_buffer_create( upload->pipe->screen,
|
upload->buffer = pipe_buffer_create( upload->pipe->screen,
|
||||||
upload->usage,
|
upload->bind,
|
||||||
size );
|
size );
|
||||||
if (upload->buffer == NULL)
|
if (upload->buffer == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -135,33 +135,61 @@ fail:
|
||||||
return PIPE_ERROR_OUT_OF_MEMORY;
|
return PIPE_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum pipe_error u_upload_alloc( struct u_upload_mgr *upload,
|
||||||
enum pipe_error u_upload_data( struct u_upload_mgr *upload,
|
unsigned min_out_offset,
|
||||||
unsigned size,
|
unsigned size,
|
||||||
const void *data,
|
unsigned *out_offset,
|
||||||
unsigned *out_offset,
|
struct pipe_resource **outbuf,
|
||||||
struct pipe_resource **outbuf )
|
boolean *flushed,
|
||||||
|
void **ptr )
|
||||||
{
|
{
|
||||||
unsigned alloc_size = align( size, upload->alignment );
|
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) {
|
if (MAX2(upload->offset, alloc_offset) + alloc_size > upload->size) {
|
||||||
ret = u_upload_alloc_buffer( upload, alloc_size );
|
enum pipe_error ret = u_upload_alloc_buffer(upload,
|
||||||
|
alloc_offset + alloc_size);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
*flushed = TRUE;
|
||||||
|
} else {
|
||||||
|
*flushed = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(upload->offset < upload->buffer->width0);
|
offset = MAX2(upload->offset, alloc_offset);
|
||||||
assert(upload->offset + size <= upload->buffer->width0);
|
|
||||||
|
assert(offset < upload->buffer->width0);
|
||||||
|
assert(offset + size <= upload->buffer->width0);
|
||||||
assert(size);
|
assert(size);
|
||||||
|
|
||||||
memcpy(upload->map + upload->offset, data, size);
|
*ptr = upload->map + offset;
|
||||||
|
|
||||||
/* Emit the return values:
|
/* Emit the return values:
|
||||||
*/
|
*/
|
||||||
pipe_resource_reference( outbuf, upload->buffer );
|
pipe_resource_reference( outbuf, upload->buffer );
|
||||||
*out_offset = upload->offset;
|
*out_offset = offset;
|
||||||
upload->offset += alloc_size;
|
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;
|
return PIPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,11 +200,13 @@ enum pipe_error u_upload_data( struct u_upload_mgr *upload,
|
||||||
* renders or DrawElements calls.
|
* renders or DrawElements calls.
|
||||||
*/
|
*/
|
||||||
enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
|
enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
|
||||||
|
unsigned min_out_offset,
|
||||||
unsigned offset,
|
unsigned offset,
|
||||||
unsigned size,
|
unsigned size,
|
||||||
struct pipe_resource *inbuf,
|
struct pipe_resource *inbuf,
|
||||||
unsigned *out_offset,
|
unsigned *out_offset,
|
||||||
struct pipe_resource **outbuf )
|
struct pipe_resource **outbuf,
|
||||||
|
boolean *flushed )
|
||||||
{
|
{
|
||||||
enum pipe_error ret = PIPE_OK;
|
enum pipe_error ret = PIPE_OK;
|
||||||
struct pipe_transfer *transfer = NULL;
|
struct pipe_transfer *transfer = NULL;
|
||||||
|
@ -196,12 +226,11 @@ enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
|
||||||
debug_printf("upload ptr %p ofs %d sz %d\n", map, offset, size);
|
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,
|
size,
|
||||||
map + offset,
|
map + offset,
|
||||||
out_offset,
|
out_offset,
|
||||||
outbuf );
|
outbuf, flushed );
|
||||||
if (ret)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (map)
|
if (map)
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#ifndef U_UPLOAD_MGR_H
|
#ifndef U_UPLOAD_MGR_H
|
||||||
#define U_UPLOAD_MGR_H
|
#define U_UPLOAD_MGR_H
|
||||||
|
|
||||||
|
#include "pipe/p_compiler.h"
|
||||||
|
|
||||||
struct pipe_context;
|
struct pipe_context;
|
||||||
struct pipe_resource;
|
struct pipe_resource;
|
||||||
|
|
||||||
|
@ -39,7 +41,7 @@ struct pipe_resource;
|
||||||
struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
|
struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
|
||||||
unsigned default_size,
|
unsigned default_size,
|
||||||
unsigned alignment,
|
unsigned alignment,
|
||||||
unsigned usage );
|
unsigned bind );
|
||||||
|
|
||||||
void u_upload_destroy( struct u_upload_mgr *upload );
|
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 );
|
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,
|
enum pipe_error u_upload_data( struct u_upload_mgr *upload,
|
||||||
|
unsigned min_out_offset,
|
||||||
unsigned size,
|
unsigned size,
|
||||||
const void *data,
|
const void *data,
|
||||||
unsigned *out_offset,
|
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,
|
enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
|
||||||
|
unsigned min_out_offset,
|
||||||
unsigned offset,
|
unsigned offset,
|
||||||
unsigned size,
|
unsigned size,
|
||||||
struct pipe_resource *inbuf,
|
struct pipe_resource *inbuf,
|
||||||
unsigned *out_offset,
|
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 :
|
vb->buffer->width0 - vb->buffer_offset :
|
||||||
MAX2(vb->buffer->width0 - vb->buffer_offset,
|
MAX2(vb->buffer->width0 - vb->buffer_offset,
|
||||||
vb->stride * (max_index + 1 - min_index)));
|
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,
|
vb->buffer_offset + min_index * vb->stride,
|
||||||
size,
|
size,
|
||||||
vb->buffer,
|
vb->buffer,
|
||||||
&offset,
|
&offset,
|
||||||
&upload_buf );
|
&upload_buf,
|
||||||
|
&flushed );
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -251,13 +254,16 @@ static int brw_prepare_indices(struct brw_context *brw)
|
||||||
/* Turn userbuffer into a proper hardware buffer?
|
/* Turn userbuffer into a proper hardware buffer?
|
||||||
*/
|
*/
|
||||||
if (brw_buffer_is_user_buffer(index_buffer)) {
|
if (brw_buffer_is_user_buffer(index_buffer)) {
|
||||||
|
boolean flushed;
|
||||||
|
|
||||||
ret = u_upload_buffer( brw->vb.upload_index,
|
ret = u_upload_buffer( brw->vb.upload_index,
|
||||||
|
0,
|
||||||
index_offset,
|
index_offset,
|
||||||
ib_size,
|
ib_size,
|
||||||
index_buffer,
|
index_buffer,
|
||||||
&offset,
|
&offset,
|
||||||
&upload_buf );
|
&upload_buf,
|
||||||
|
&flushed );
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -62,15 +62,16 @@ void r300_upload_index_buffer(struct r300_context *r300,
|
||||||
unsigned count)
|
unsigned count)
|
||||||
{
|
{
|
||||||
unsigned index_offset;
|
unsigned index_offset;
|
||||||
|
boolean flushed;
|
||||||
uint8_t *ptr = r300_buffer(*index_buffer)->user_buffer;
|
uint8_t *ptr = r300_buffer(*index_buffer)->user_buffer;
|
||||||
|
|
||||||
*index_buffer = NULL;
|
*index_buffer = NULL;
|
||||||
|
|
||||||
u_upload_data(r300->upload_ib,
|
u_upload_data(r300->upload_ib,
|
||||||
count * index_size,
|
0, count * index_size,
|
||||||
ptr + (*start * index_size),
|
ptr + (*start * index_size),
|
||||||
&index_offset,
|
&index_offset,
|
||||||
index_buffer);
|
index_buffer, &flushed);
|
||||||
|
|
||||||
*start = index_offset / index_size;
|
*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)
|
void r300_upload_user_buffers(struct r300_context *r300)
|
||||||
{
|
{
|
||||||
int i, nr = r300->velems->count;
|
int i, nr = r300->velems->count;
|
||||||
|
boolean flushed;
|
||||||
|
|
||||||
for (i = 0; i < nr; i++) {
|
for (i = 0; i < nr; i++) {
|
||||||
struct pipe_vertex_buffer *vb =
|
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)) {
|
if (r300_buffer_is_user_buffer(vb->buffer)) {
|
||||||
u_upload_data(r300->upload_vb,
|
u_upload_data(r300->upload_vb,
|
||||||
vb->buffer->width0,
|
0, vb->buffer->width0,
|
||||||
r300_buffer(vb->buffer)->user_buffer,
|
r300_buffer(vb->buffer)->user_buffer,
|
||||||
&vb->buffer_offset, &vb->buffer);
|
&vb->buffer_offset, &vb->buffer, &flushed);
|
||||||
|
|
||||||
r300->validate_buffers = TRUE;
|
r300->validate_buffers = TRUE;
|
||||||
r300->vertex_arrays_dirty = TRUE;
|
r300->vertex_arrays_dirty = TRUE;
|
||||||
|
|
|
@ -120,14 +120,17 @@ svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,
|
||||||
if (index_buffer &&
|
if (index_buffer &&
|
||||||
svga_buffer_is_user_buffer(index_buffer))
|
svga_buffer_is_user_buffer(index_buffer))
|
||||||
{
|
{
|
||||||
|
boolean flushed;
|
||||||
assert( index_buffer->width0 >= index_offset + count * index_size );
|
assert( index_buffer->width0 >= index_offset + count * index_size );
|
||||||
|
|
||||||
ret = u_upload_buffer( hwtnl->upload_ib,
|
ret = u_upload_buffer( hwtnl->upload_ib,
|
||||||
|
0,
|
||||||
index_offset,
|
index_offset,
|
||||||
count * index_size,
|
count * index_size,
|
||||||
index_buffer,
|
index_buffer,
|
||||||
&index_offset,
|
&index_offset,
|
||||||
&upload_buffer );
|
&upload_buffer,
|
||||||
|
&flushed );
|
||||||
if (ret)
|
if (ret)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
|
|
@ -57,12 +57,14 @@ upload_user_buffers( struct svga_context *svga )
|
||||||
struct svga_buffer *buffer = svga_buffer(svga->curr.vb[i].buffer);
|
struct svga_buffer *buffer = svga_buffer(svga->curr.vb[i].buffer);
|
||||||
|
|
||||||
if (!buffer->uploaded.buffer) {
|
if (!buffer->uploaded.buffer) {
|
||||||
|
boolean flushed;
|
||||||
ret = u_upload_buffer( svga->upload_vb,
|
ret = u_upload_buffer( svga->upload_vb,
|
||||||
0,
|
0, 0,
|
||||||
buffer->b.b.width0,
|
buffer->b.b.width0,
|
||||||
&buffer->b.b,
|
&buffer->b.b,
|
||||||
&buffer->uploaded.offset,
|
&buffer->uploaded.offset,
|
||||||
&buffer->uploaded.buffer );
|
&buffer->uploaded.buffer,
|
||||||
|
&flushed);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue