unsigned count;
struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
- /* If (velem[i].src_format != real_format[i]), the vertex buffer
+ unsigned src_format_size[PIPE_MAX_ATTRIBS];
+
+ /* If (velem[i].src_format != native_format[i]), the vertex buffer
* referenced by the vertex element cannot be used for rendering and
- * its vertex data must be translated to real_format[i]. */
+ * its vertex data must be translated to native_format[i]. */
enum pipe_format native_format[PIPE_MAX_ATTRIBS];
unsigned native_format_size[PIPE_MAX_ATTRIBS];
mgr->caps.format_fixed32 =
screen->is_format_supported(screen, PIPE_FORMAT_R32_FIXED, PIPE_BUFFER,
- 0, PIPE_BIND_VERTEX_BUFFER, 0);
+ 0, PIPE_BIND_VERTEX_BUFFER);
mgr->caps.format_float16 =
screen->is_format_supported(screen, PIPE_FORMAT_R16_FLOAT, PIPE_BUFFER,
- 0, PIPE_BIND_VERTEX_BUFFER, 0);
+ 0, PIPE_BIND_VERTEX_BUFFER);
mgr->caps.format_float64 =
screen->is_format_supported(screen, PIPE_FORMAT_R64_FLOAT, PIPE_BUFFER,
- 0, PIPE_BIND_VERTEX_BUFFER, 0);
+ 0, PIPE_BIND_VERTEX_BUFFER);
mgr->caps.format_norm32 =
screen->is_format_supported(screen, PIPE_FORMAT_R32_UNORM, PIPE_BUFFER,
- 0, PIPE_BIND_VERTEX_BUFFER, 0) &&
+ 0, PIPE_BIND_VERTEX_BUFFER) &&
screen->is_format_supported(screen, PIPE_FORMAT_R32_SNORM, PIPE_BUFFER,
- 0, PIPE_BIND_VERTEX_BUFFER, 0);
+ 0, PIPE_BIND_VERTEX_BUFFER);
mgr->caps.format_scaled32 =
screen->is_format_supported(screen, PIPE_FORMAT_R32_USCALED, PIPE_BUFFER,
- 0, PIPE_BIND_VERTEX_BUFFER, 0) &&
+ 0, PIPE_BIND_VERTEX_BUFFER) &&
screen->is_format_supported(screen, PIPE_FORMAT_R32_SSCALED, PIPE_BUFFER,
- 0, PIPE_BIND_VERTEX_BUFFER, 0);
+ 0, PIPE_BIND_VERTEX_BUFFER);
}
struct u_vbuf_mgr *
u_vbuf_mgr_create(struct pipe_context *pipe,
- unsigned upload_buffer_size,
- unsigned upload_buffer_alignment,
- enum u_fetch_alignment fetch_alignment)
+ unsigned upload_buffer_size,
+ unsigned upload_buffer_alignment,
+ unsigned upload_buffer_bind,
+ enum u_fetch_alignment fetch_alignment)
{
struct u_vbuf_mgr_priv *mgr = CALLOC_STRUCT(u_vbuf_mgr_priv);
mgr->b.uploader = u_upload_create(pipe, upload_buffer_size,
upload_buffer_alignment,
- PIPE_BIND_VERTEX_BUFFER);
+ upload_buffer_bind);
mgr->caps.fetch_dword_unaligned =
fetch_alignment == U_VERTEX_FETCH_BYTE_ALIGNED;
}
-static void u_vbuf_translate_begin(struct u_vbuf_mgr_priv *mgr,
- int min_index, int max_index,
- boolean *upload_flushed)
+static enum u_vbuf_return_flags
+u_vbuf_translate_begin(struct u_vbuf_mgr_priv *mgr,
+ int min_index, int max_index)
{
- struct translate_key key = {0};
+ struct translate_key key;
struct translate_element *te;
- unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0};
+ unsigned tr_elem_index[PIPE_MAX_ATTRIBS];
struct translate *tr;
boolean vb_translated[PIPE_MAX_ATTRIBS] = {0};
uint8_t *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map;
struct pipe_resource *out_buffer = NULL;
unsigned i, num_verts, out_offset;
struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS];
+ boolean upload_flushed = FALSE;
+
+ memset(&key, 0, sizeof(key));
+ memset(tr_elem_index, 0xff, sizeof(tr_elem_index));
/* Initialize the translate key, i.e. the recipe how vertices should be
* translated. */
+ memset(&key, 0, sizeof key);
for (i = 0; i < mgr->ve->count; i++) {
struct pipe_vertex_buffer *vb =
&mgr->b.vertex_buffer[mgr->ve->ve[i].vertex_buffer_index];
u_upload_alloc(mgr->b.uploader,
key.output_stride * min_index,
key.output_stride * num_verts,
- &out_offset, &out_buffer, upload_flushed,
+ &out_offset, &out_buffer, &upload_flushed,
(void**)&out_map);
out_offset -= key.output_stride * min_index;
/* Setup new vertex elements. */
for (i = 0; i < mgr->ve->count; i++) {
- if (vb_translated[mgr->ve->ve[i].vertex_buffer_index]) {
+ if (tr_elem_index[i] < key.nr_elements) {
te = &key.element[tr_elem_index[i]];
new_velems[i].instance_divisor = mgr->ve->ve[i].instance_divisor;
new_velems[i].src_format = te->output_format;
}
pipe_resource_reference(&out_buffer, NULL);
+
+ return upload_flushed ? U_VBUF_UPLOAD_FLUSHED : 0;
}
static void u_vbuf_translate_end(struct u_vbuf_mgr_priv *mgr)
struct u_vbuf_mgr_elements *
u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgrb,
- unsigned count,
- const struct pipe_vertex_element *attribs,
- struct pipe_vertex_element *native_attribs)
+ unsigned count,
+ const struct pipe_vertex_element *attribs,
+ struct pipe_vertex_element *native_attribs)
{
struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
unsigned i;
for (i = 0; i < count; i++) {
enum pipe_format format = ve->ve[i].src_format;
+ ve->src_format_size[i] = util_format_get_blocksize(format);
+
/* Choose a native format.
* For now we don't care about the alignment, that's going to
* be sorted out later. */
}
void u_vbuf_mgr_bind_vertex_elements(struct u_vbuf_mgr *mgrb,
- void *cso,
- struct u_vbuf_mgr_elements *ve)
+ void *cso,
+ struct u_vbuf_mgr_elements *ve)
{
struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
}
void u_vbuf_mgr_destroy_vertex_elements(struct u_vbuf_mgr *mgr,
- struct u_vbuf_mgr_elements *ve)
+ struct u_vbuf_mgr_elements *ve)
{
FREE(ve);
}
void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgrb,
- unsigned count,
- const struct pipe_vertex_buffer *bufs)
+ unsigned count,
+ const struct pipe_vertex_buffer *bufs)
{
struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
unsigned i;
- mgr->b.max_index = ~0;
mgr->any_user_vbs = FALSE;
mgr->incompatible_vb_layout = FALSE;
pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, vb->buffer);
pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL);
- if (u_vbuf_resource(vb->buffer)->user_ptr) {
- mgr->any_user_vbs = TRUE;
+ if (!vb->buffer) {
continue;
}
- pipe_resource_reference(&mgr->b.real_vertex_buffer[i], vb->buffer);
-
- /* The stride of zero means we will be fetching only the first
- * vertex, so don't care about max_index. */
- if (!vb->stride) {
+ if (u_vbuf_resource(vb->buffer)->user_ptr) {
+ mgr->any_user_vbs = TRUE;
continue;
}
- /* Update the maximum index. */
- mgr->b.max_index =
- MIN2(mgr->b.max_index,
- (vb->buffer->width0 - vb->buffer_offset) / vb->stride);
+ pipe_resource_reference(&mgr->b.real_vertex_buffer[i], vb->buffer);
}
for (; i < mgr->b.nr_real_vertex_buffers; i++) {
mgr->b.nr_real_vertex_buffers = count;
}
-static void u_vbuf_upload_buffers(struct u_vbuf_mgr_priv *mgr,
- int min_index, int max_index,
- boolean *upload_flushed)
+static enum u_vbuf_return_flags
+u_vbuf_upload_buffers(struct u_vbuf_mgr_priv *mgr,
+ int min_index, int max_index,
+ unsigned instance_count)
{
- int i, nr = mgr->ve->count;
+ unsigned i, nr = mgr->ve->count;
unsigned count = max_index + 1 - min_index;
boolean uploaded[PIPE_MAX_ATTRIBS] = {0};
+ enum u_vbuf_return_flags retval = 0;
for (i = 0; i < nr; i++) {
unsigned index = mgr->ve->ve[i].vertex_buffer_index;
!uploaded[index]) {
unsigned first, size;
boolean flushed;
+ unsigned instance_div = mgr->ve->ve[i].instance_divisor;
- if (vb->stride) {
+ if (instance_div) {
+ first = 0;
+ size = vb->stride *
+ ((instance_count + instance_div - 1) / instance_div);
+ } else if (vb->stride) {
first = vb->stride * min_index;
size = vb->stride * count;
+
+ /* Unusual case when stride is smaller than the format size.
+ * XXX This won't work with interleaved arrays. */
+ if (mgr->ve->native_format_size[i] > vb->stride)
+ size += mgr->ve->native_format_size[i] - vb->stride;
} else {
first = 0;
size = mgr->ve->native_format_size[i];
vb->buffer_offset -= first;
uploaded[index] = TRUE;
- *upload_flushed = *upload_flushed || flushed;
+ if (flushed)
+ retval |= U_VBUF_UPLOAD_FLUSHED;
} else {
assert(mgr->b.real_vertex_buffer[index]);
}
}
+
+ return retval;
+}
+
+static void u_vbuf_mgr_compute_max_index(struct u_vbuf_mgr_priv *mgr)
+{
+ unsigned i, nr = mgr->ve->count;
+
+ mgr->b.max_index = ~0;
+
+ for (i = 0; i < nr; i++) {
+ struct pipe_vertex_buffer *vb =
+ &mgr->b.vertex_buffer[mgr->ve->ve[i].vertex_buffer_index];
+ int unused;
+ unsigned max_index;
+
+ if (!vb->buffer ||
+ !vb->stride ||
+ u_vbuf_resource(vb->buffer)->user_ptr) {
+ continue;
+ }
+
+ /* How many bytes is unused after the last vertex.
+ * width0 may be "count*stride - unused" and we have to compensate
+ * for that when dividing by stride. */
+ unused = vb->stride -
+ (mgr->ve->ve[i].src_offset + mgr->ve->src_format_size[i]);
+
+ /* If src_offset is greater than stride (which means it's a buffer
+ * offset rather than a vertex offset)... */
+ if (unused < 0) {
+ unused = 0;
+ }
+
+ /* Compute the maximum index for this vertex element. */
+ max_index =
+ (vb->buffer->width0 - vb->buffer_offset + (unsigned)unused) /
+ vb->stride - 1;
+
+ mgr->b.max_index = MIN2(mgr->b.max_index, max_index);
+ }
}
-void u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgrb,
- const struct pipe_draw_info *info,
- boolean *buffers_updated,
- boolean *uploader_flushed)
+enum u_vbuf_return_flags
+u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgrb,
+ const struct pipe_draw_info *info)
{
struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
- boolean bufs_updated, upload_flushed = FALSE;
int min_index, max_index;
+ enum u_vbuf_return_flags retval = 0;
+
+ u_vbuf_mgr_compute_max_index(mgr);
min_index = info->min_index - info->index_bias;
- max_index = MIN2(info->max_index, mgr->b.max_index) - info->index_bias;
+ if (info->max_index == ~0) {
+ max_index = mgr->b.max_index;
+ } else {
+ max_index = MIN2(info->max_index - info->index_bias, mgr->b.max_index);
+ }
/* Translate vertices with non-native layouts or formats. */
if (mgr->incompatible_vb_layout || mgr->ve->incompatible_layout) {
- u_vbuf_translate_begin(mgr, min_index, max_index, &upload_flushed);
+ retval |= u_vbuf_translate_begin(mgr, min_index, max_index);
if (mgr->fallback_ve) {
- bufs_updated = TRUE;
+ retval |= U_VBUF_BUFFERS_UPDATED;
}
}
/* Upload user buffers. */
if (mgr->any_user_vbs) {
- u_vbuf_upload_buffers(mgr, min_index, max_index, &upload_flushed);
- bufs_updated = TRUE;
- }
-
- /* Set the return values. */
- if (buffers_updated) {
- *buffers_updated = bufs_updated;
- }
- if (uploader_flushed) {
- *uploader_flushed = upload_flushed;
+ retval |= u_vbuf_upload_buffers(mgr, min_index, max_index,
+ info->instance_count);
+ retval |= U_VBUF_BUFFERS_UPDATED;
}
+ return retval;
}
void u_vbuf_mgr_draw_end(struct u_vbuf_mgr *mgrb)