panfrost: Move instancing routines to encoder/
[mesa.git] / src / gallium / drivers / panfrost / pan_attributes.c
1 /*
2 * Copyright (C) 2018-2019 Alyssa Rosenzweig
3 * Copyright (C) 2019 Collabora, Ltd.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 */
25
26 #include "pan_bo.h"
27 #include "pan_context.h"
28
29 void
30 panfrost_emit_vertex_data(struct panfrost_batch *batch)
31 {
32 struct panfrost_context *ctx = batch->ctx;
33 struct panfrost_vertex_state *so = ctx->vertex;
34
35 /* Staged mali_attr, and index into them. i =/= k, depending on the
36 * vertex buffer mask and instancing. Twice as much room is allocated,
37 * for a worst case of NPOT_DIVIDEs which take up extra slot */
38 union mali_attr attrs[PIPE_MAX_ATTRIBS * 2];
39 unsigned k = 0;
40
41 unsigned vertex_count = ctx->vertex_count;
42 unsigned instanced_count = ctx->instance_count;
43
44 for (unsigned i = 0; i < so->num_elements; ++i) {
45 /* We map a mali_attr to be 1:1 with the mali_attr_meta, which
46 * means duplicating some vertex buffers (who cares? aside from
47 * maybe some caching implications but I somehow doubt that
48 * matters) */
49
50 struct pipe_vertex_element *elem = &so->pipe[i];
51 unsigned vbi = elem->vertex_buffer_index;
52
53 /* The exception to 1:1 mapping is that we can have multiple
54 * entries (NPOT divisors), so we fixup anyways */
55
56 so->hw[i].index = k;
57
58 if (!(ctx->vb_mask & (1 << vbi))) continue;
59
60 struct pipe_vertex_buffer *buf = &ctx->vertex_buffers[vbi];
61 struct panfrost_resource *rsrc = (struct panfrost_resource *) (buf->buffer.resource);
62
63 if (!rsrc) continue;
64
65 /* Align to 64 bytes by masking off the lower bits. This
66 * will be adjusted back when we fixup the src_offset in
67 * mali_attr_meta */
68
69 mali_ptr raw_addr = rsrc->bo->gpu + buf->buffer_offset;
70 mali_ptr addr = raw_addr & ~63;
71 unsigned chopped_addr = raw_addr - addr;
72
73 /* Add a dependency of the batch on the vertex buffer */
74 panfrost_batch_add_bo(batch, rsrc->bo,
75 PAN_BO_ACCESS_SHARED |
76 PAN_BO_ACCESS_READ |
77 PAN_BO_ACCESS_VERTEX_TILER);
78
79 /* Set common fields */
80 attrs[k].elements = addr;
81 attrs[k].stride = buf->stride;
82
83 /* Since we advanced the base pointer, we shrink the buffer
84 * size */
85 attrs[k].size = rsrc->base.width0 - buf->buffer_offset;
86
87 /* We need to add the extra size we masked off (for
88 * correctness) so the data doesn't get clamped away */
89 attrs[k].size += chopped_addr;
90
91 /* For non-instancing make sure we initialize */
92 attrs[k].shift = attrs[k].extra_flags = 0;
93
94 /* Instancing uses a dramatically different code path than
95 * linear, so dispatch for the actual emission now that the
96 * common code is finished */
97
98 unsigned divisor = elem->instance_divisor;
99
100 if (divisor && instanced_count == 1) {
101 /* Silly corner case where there's a divisor(=1) but
102 * there's no legitimate instancing. So we want *every*
103 * attribute to be the same. So set stride to zero so
104 * we don't go anywhere. */
105
106 attrs[k].size = attrs[k].stride + chopped_addr;
107 attrs[k].stride = 0;
108 attrs[k++].elements |= MALI_ATTR_LINEAR;
109 } else if (instanced_count <= 1) {
110 /* Normal, non-instanced attributes */
111 attrs[k++].elements |= MALI_ATTR_LINEAR;
112 } else {
113 unsigned instance_shift = batch->ctx->payloads[PIPE_SHADER_FRAGMENT].instance_shift;
114 unsigned instance_odd = batch->ctx->payloads[PIPE_SHADER_FRAGMENT].instance_odd;
115
116 k += panfrost_vertex_instanced(batch->ctx->padded_count,
117 instance_shift, instance_odd, divisor, &attrs[k]);
118 }
119 }
120
121 /* Upload whatever we emitted and go */
122
123 ctx->payloads[PIPE_SHADER_VERTEX].postfix.attributes =
124 panfrost_upload_transient(batch, attrs, k * sizeof(union mali_attr));
125 }
126
127