summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/auxiliary/util/u_vbuf_mgr.c52
1 files changed, 33 insertions, 19 deletions
diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.c b/src/gallium/auxiliary/util/u_vbuf_mgr.c
index ca4f795f034..7926b4244b7 100644
--- a/src/gallium/auxiliary/util/u_vbuf_mgr.c
+++ b/src/gallium/auxiliary/util/u_vbuf_mgr.c
@@ -50,6 +50,8 @@ struct u_vbuf_elements {
* - src_format != native_format, as discussed above.
* - src_offset % 4 != 0 (if the caps don't allow such an offset). */
boolean incompatible_layout;
+ /* Per-element flags. */
+ boolean incompatible_layout_elem[PIPE_MAX_ATTRIBS];
};
struct u_vbuf_priv {
@@ -61,10 +63,16 @@ struct u_vbuf_priv {
struct u_vbuf_elements *ve;
void *saved_ve, *fallback_ve;
+
+ /* Vertex elements used for the translate fallback. */
+ struct pipe_vertex_element fallback_velems[PIPE_MAX_ATTRIBS];
boolean ve_binding_lock;
boolean any_user_vbs;
+
boolean incompatible_vb_layout;
+ /* Per-buffer flags. */
+ boolean incompatible_vb[PIPE_MAX_ATTRIBS];
};
static void u_vbuf_init_format_caps(struct u_vbuf_priv *mgr)
@@ -107,6 +115,7 @@ u_vbuf_create(struct pipe_context *pipe,
mgr->pipe = pipe;
mgr->translate_cache = translate_cache_create();
+ mgr->translate_vb_slot = ~0;
mgr->b.uploader = u_upload_create(pipe, upload_buffer_size,
upload_buffer_alignment,
@@ -151,27 +160,21 @@ u_vbuf_translate_begin(struct u_vbuf_priv *mgr,
struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0};
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. */
+ * 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];
enum pipe_format output_format = mgr->ve->native_format[i];
unsigned output_format_size = mgr->ve->native_format_size[i];
/* Check for support. */
- if (mgr->ve->ve[i].src_format == mgr->ve->native_format[i] &&
- (mgr->b.caps.fetch_dword_unaligned ||
- (vb->buffer_offset % 4 == 0 &&
- vb->stride % 4 == 0 &&
- mgr->ve->ve[i].src_offset % 4 == 0))) {
+ if (!mgr->ve->incompatible_layout_elem[i] &&
+ !mgr->incompatible_vb[mgr->ve->ve[i].vertex_buffer_index]) {
continue;
}
@@ -274,19 +277,19 @@ u_vbuf_translate_begin(struct u_vbuf_priv *mgr,
for (i = 0; i < mgr->ve->count; i++) {
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;
- new_velems[i].src_offset = te->output_offset;
- new_velems[i].vertex_buffer_index = mgr->translate_vb_slot;
+ mgr->fallback_velems[i].instance_divisor = mgr->ve->ve[i].instance_divisor;
+ mgr->fallback_velems[i].src_format = te->output_format;
+ mgr->fallback_velems[i].src_offset = te->output_offset;
+ mgr->fallback_velems[i].vertex_buffer_index = mgr->translate_vb_slot;
} else {
- memcpy(&new_velems[i], &mgr->ve->ve[i],
+ memcpy(&mgr->fallback_velems[i], &mgr->ve->ve[i],
sizeof(struct pipe_vertex_element));
}
}
mgr->fallback_ve =
mgr->pipe->create_vertex_elements_state(mgr->pipe, mgr->ve->count,
- new_velems);
+ mgr->fallback_velems);
/* Preserve saved_ve. */
mgr->ve_binding_lock = TRUE;
@@ -312,6 +315,7 @@ static void u_vbuf_translate_end(struct u_vbuf_priv *mgr)
/* Delete the now-unused VBO. */
pipe_resource_reference(&mgr->b.real_vertex_buffer[mgr->translate_vb_slot].buffer,
NULL);
+ mgr->translate_vb_slot = ~0;
mgr->b.nr_real_vertex_buffers = mgr->b.nr_vertex_buffers;
}
@@ -406,10 +410,12 @@ u_vbuf_create_vertex_elements(struct u_vbuf_mgr *mgrb,
ve->native_format_size[i] =
util_format_get_blocksize(ve->native_format[i]);
- ve->incompatible_layout =
- ve->incompatible_layout ||
+ ve->incompatible_layout_elem[i] =
ve->ve[i].src_format != ve->native_format[i] ||
(!mgr->b.caps.fetch_dword_unaligned && ve->ve[i].src_offset % 4 != 0);
+ ve->incompatible_layout =
+ ve->incompatible_layout ||
+ ve->incompatible_layout_elem[i];
}
/* Align the formats to the size of DWORD if needed. */
@@ -453,6 +459,7 @@ void u_vbuf_set_vertex_buffers(struct u_vbuf_mgr *mgrb,
mgr->any_user_vbs = FALSE;
mgr->incompatible_vb_layout = FALSE;
+ memset(mgr->incompatible_vb, 0, sizeof(mgr->incompatible_vb));
if (!mgr->b.caps.fetch_dword_unaligned) {
/* Check if the strides and offsets are aligned to the size of DWORD. */
@@ -461,7 +468,7 @@ void u_vbuf_set_vertex_buffers(struct u_vbuf_mgr *mgrb,
if (bufs[i].stride % 4 != 0 ||
bufs[i].buffer_offset % 4 != 0) {
mgr->incompatible_vb_layout = TRUE;
- break;
+ mgr->incompatible_vb[i] = TRUE;
}
}
}
@@ -512,16 +519,23 @@ u_vbuf_upload_buffers(struct u_vbuf_priv *mgr,
unsigned count = max_index + 1 - min_index;
unsigned nr_velems = mgr->ve->count;
unsigned nr_vbufs = mgr->b.nr_vertex_buffers;
+ struct pipe_vertex_element *velems =
+ mgr->fallback_ve ? mgr->fallback_velems : mgr->ve->ve;
unsigned start_offset[PIPE_MAX_ATTRIBS];
unsigned end_offset[PIPE_MAX_ATTRIBS] = {0};
/* Determine how much data needs to be uploaded. */
for (i = 0; i < nr_velems; i++) {
- struct pipe_vertex_element *velem = &mgr->ve->ve[i];
+ struct pipe_vertex_element *velem = &velems[i];
unsigned index = velem->vertex_buffer_index;
struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[index];
unsigned instance_div, first, size;
+ /* Skip the buffer generated by translate. */
+ if (index == mgr->translate_vb_slot) {
+ continue;
+ }
+
assert(vb->buffer);
if (!u_vbuf_resource(vb->buffer)->user_ptr) {