summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw_upload.c71
1 files changed, 49 insertions, 22 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c
index 3ec37f805e3..0a7725dcb96 100644
--- a/src/mesa/drivers/dri/i965/brw_draw_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c
@@ -453,6 +453,11 @@ brw_prepare_vertices(struct brw_context *brw)
if (brw->vb.nr_buffers)
return;
+ /* The range of data in a given buffer represented as [min, max) */
+ struct intel_buffer_object *enabled_buffer[VERT_ATTRIB_MAX];
+ uint32_t buffer_range_start[VERT_ATTRIB_MAX];
+ uint32_t buffer_range_end[VERT_ATTRIB_MAX];
+
for (i = j = 0; i < brw->vb.nr_enabled; i++) {
struct brw_vertex_element *input = brw->vb.enabled[i];
const struct gl_client_array *glarray = input->glarray;
@@ -460,12 +465,31 @@ brw_prepare_vertices(struct brw_context *brw)
if (_mesa_is_bufferobj(glarray->BufferObj)) {
struct intel_buffer_object *intel_buffer =
intel_buffer_object(glarray->BufferObj);
- unsigned k;
+
+ const uint32_t offset = (uintptr_t)glarray->Ptr;
+
+ uint32_t start, range;
+ if (glarray->InstanceDivisor) {
+ start = offset;
+ range = (glarray->StrideB * ((brw->num_instances /
+ glarray->InstanceDivisor) - 1) +
+ glarray->_ElementSize);
+ } else {
+ if (!brw->vb.index_bounds_valid) {
+ start = 0;
+ range = intel_buffer->Base.Size;
+ } else {
+ start = offset + min_index * glarray->StrideB;
+ range = (glarray->StrideB * (max_index - min_index) +
+ glarray->_ElementSize);
+ }
+ }
/* If we have a VB set to be uploaded for this buffer object
* already, reuse that VB state so that we emit fewer
* relocations.
*/
+ unsigned k;
for (k = 0; k < i; k++) {
const struct gl_client_array *other = brw->vb.enabled[k]->glarray;
if (glarray->BufferObj == other->BufferObj &&
@@ -475,6 +499,9 @@ brw_prepare_vertices(struct brw_context *brw)
{
input->buffer = brw->vb.enabled[k]->buffer;
input->offset = glarray->Ptr - other->Ptr;
+
+ buffer_range_start[k] = MIN2(buffer_range_start[k], start);
+ buffer_range_end[k] = MAX2(buffer_range_end[k], start + range);
break;
}
}
@@ -482,29 +509,13 @@ brw_prepare_vertices(struct brw_context *brw)
struct brw_vertex_buffer *buffer = &brw->vb.buffers[j];
/* Named buffer object: Just reference its contents directly. */
- buffer->offset = (uintptr_t)glarray->Ptr;
+ buffer->offset = offset;
buffer->stride = glarray->StrideB;
buffer->step_rate = glarray->InstanceDivisor;
- uint32_t offset, size;
- if (glarray->InstanceDivisor) {
- offset = buffer->offset;
- size = (buffer->stride * ((brw->num_instances /
- glarray->InstanceDivisor) - 1) +
- glarray->_ElementSize);
- } else {
- if (!brw->vb.index_bounds_valid) {
- offset = 0;
- size = intel_buffer->Base.Size;
- } else {
- offset = buffer->offset + min_index * buffer->stride;
- size = (buffer->stride * (max_index - min_index) +
- glarray->_ElementSize);
- }
- }
- buffer->bo = intel_bufferobj_buffer(brw, intel_buffer,
- offset, size);
- drm_intel_bo_reference(buffer->bo);
+ enabled_buffer[j] = intel_buffer;
+ buffer_range_start[j] = start;
+ buffer_range_end[j] = start + range;
input->buffer = j++;
input->offset = 0;
@@ -519,7 +530,7 @@ brw_prepare_vertices(struct brw_context *brw)
* probably a service to the poor programmer to do so rather than
* trying to just not render.
*/
- assert(input->offset < brw->vb.buffers[input->buffer].bo->size);
+ assert(input->offset < intel_buffer->Base.Size);
} else {
/* Queue the buffer object up to be uploaded in the next pass,
* when we've decided if we're doing interleaved or not.
@@ -554,6 +565,22 @@ brw_prepare_vertices(struct brw_context *brw)
}
}
+ /* Now that we've set up all of the buffers, we walk through and reference
+ * each of them. We do this late so that we get the right size in each
+ * buffer and don't reference too little data.
+ */
+ for (i = 0; i < j; i++) {
+ struct brw_vertex_buffer *buffer = &brw->vb.buffers[i];
+ if (buffer->bo)
+ continue;
+
+ const uint32_t start = buffer_range_start[i];
+ const uint32_t range = buffer_range_end[i] - buffer_range_start[i];
+
+ buffer->bo = intel_bufferobj_buffer(brw, enabled_buffer[i], start, range);
+ drm_intel_bo_reference(buffer->bo);
+ }
+
/* If we need to upload all the arrays, then we can trim those arrays to
* only the used elements [min_index, max_index] so long as we adjust all
* the values used in the 3DPRIMITIVE i.e. by setting the vertex bias.