1 |
From d66fcd1969979c7efa1861563236b4c2ff5a2d4d Mon Sep 17 00:00:00 2001 |
2 |
From: Erik Faye-Lund <erik.faye-lund@collabora.com> |
3 |
Date: Tue, 11 Dec 2018 14:02:53 +0000 |
4 |
Subject: [PATCH 13/78] virgl: work around bad assumptions in virglrenderer |
5 |
MIME-Version: 1.0 |
6 |
Content-Type: text/plain; charset=UTF-8 |
7 |
Content-Transfer-Encoding: 8bit |
8 |
|
9 |
Virglrenderer does the wrong thing when given an instance divisor; |
10 |
it tries to use the element-index rather than the binding-index as |
11 |
the argument to glVertexBindingDivisor(). This worked fine as long |
12 |
as there was a 1:1 relationship between elements and bindings, |
13 |
which was the case util 19a91841c34 "st/mesa: Use Array._DrawVAO in |
14 |
st_atom_array.c.". |
15 |
|
16 |
So let's detect instance divisors, and restore a 1:1 relationship in |
17 |
that case. This will make old versions of virglrenderer behave |
18 |
correctly. For newer versions, we can consider making a better |
19 |
interface, where the instance divisor isn't specified per element, |
20 |
but rather per binding. But let's save that for another day. |
21 |
|
22 |
Signed-off-by: Erik Faye-Lund <erik.faye-lund@collabora.com> |
23 |
Fixes: 19a91841c34 "st/mesa: Use Array._DrawVAO in st_atom_array.c." |
24 |
Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de> |
25 |
Tested-By: Gert Wollny <gert.wollny@collabora.com> |
26 |
(cherry picked from commit e888f28d1fd9f125fc70b2f5d1b3c42d8f25ae53) |
27 |
--- |
28 |
src/gallium/drivers/virgl/virgl_context.c | 33 ++++++++++++++++++++++- |
29 |
1 file changed, 32 insertions(+), 1 deletion(-) |
30 |
|
31 |
diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c |
32 |
index b1cd5e7ba4..61fb3f0636 100644 |
33 |
--- a/src/gallium/drivers/virgl/virgl_context.c |
34 |
+++ b/src/gallium/drivers/virgl/virgl_context.c |
35 |
@@ -49,6 +49,8 @@ |
36 |
|
37 |
struct virgl_vertex_elements_state { |
38 |
uint32_t handle; |
39 |
+ uint8_t binding_map[PIPE_MAX_ATTRIBS]; |
40 |
+ uint8_t num_bindings; |
41 |
}; |
42 |
|
43 |
static uint32_t next_handle; |
44 |
@@ -389,10 +391,28 @@ static void *virgl_create_vertex_elements_state(struct pipe_context *ctx, |
45 |
unsigned num_elements, |
46 |
const struct pipe_vertex_element *elements) |
47 |
{ |
48 |
+ struct pipe_vertex_element new_elements[PIPE_MAX_ATTRIBS]; |
49 |
struct virgl_context *vctx = virgl_context(ctx); |
50 |
struct virgl_vertex_elements_state *state = |
51 |
CALLOC_STRUCT(virgl_vertex_elements_state); |
52 |
|
53 |
+ for (int i = 0; i < num_elements; ++i) { |
54 |
+ if (elements[i].instance_divisor) { |
55 |
+ /* Virglrenderer doesn't deal with instance_divisor correctly if |
56 |
+ * there isn't a 1:1 relationship between elements and bindings. |
57 |
+ * So let's make sure there is, by duplicating bindings. |
58 |
+ */ |
59 |
+ for (int j = 0; j < num_elements; ++j) { |
60 |
+ new_elements[j] = elements[j]; |
61 |
+ new_elements[j].vertex_buffer_index = j; |
62 |
+ state->binding_map[j] = elements[j].vertex_buffer_index; |
63 |
+ } |
64 |
+ elements = new_elements; |
65 |
+ state->num_bindings = num_elements; |
66 |
+ break; |
67 |
+ } |
68 |
+ } |
69 |
+ |
70 |
state->handle = virgl_object_assign_handle(); |
71 |
virgl_encoder_create_vertex_elements(vctx, state->handle, |
72 |
num_elements, elements); |
73 |
@@ -418,6 +438,7 @@ static void virgl_bind_vertex_elements_state(struct pipe_context *ctx, |
74 |
vctx->vertex_elements = state; |
75 |
virgl_encode_bind_object(vctx, state ? state->handle : 0, |
76 |
VIRGL_OBJECT_VERTEX_ELEMENTS); |
77 |
+ vctx->vertex_array_dirty = TRUE; |
78 |
} |
79 |
|
80 |
static void virgl_set_vertex_buffers(struct pipe_context *ctx, |
81 |
@@ -439,7 +460,17 @@ static void virgl_hw_set_vertex_buffers(struct pipe_context *ctx) |
82 |
struct virgl_context *vctx = virgl_context(ctx); |
83 |
|
84 |
if (vctx->vertex_array_dirty) { |
85 |
- virgl_encoder_set_vertex_buffers(vctx, vctx->num_vertex_buffers, vctx->vertex_buffer); |
86 |
+ struct virgl_vertex_elements_state *ve = vctx->vertex_elements; |
87 |
+ |
88 |
+ if (ve->num_bindings) { |
89 |
+ struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; |
90 |
+ for (int i = 0; i < ve->num_bindings; ++i) |
91 |
+ vertex_buffers[i] = vctx->vertex_buffer[ve->binding_map[i]]; |
92 |
+ |
93 |
+ virgl_encoder_set_vertex_buffers(vctx, ve->num_bindings, vertex_buffers); |
94 |
+ } else |
95 |
+ virgl_encoder_set_vertex_buffers(vctx, vctx->num_vertex_buffers, vctx->vertex_buffer); |
96 |
+ |
97 |
virgl_attach_res_vertex_buffers(vctx); |
98 |
} |
99 |
} |
100 |
-- |
101 |
2.20.1 |
102 |
|