1 /*
2 * Copyright (C) 2020 Collabora Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include "pan_context.h"
25 #include "util/u_vbuf.h"
26
27 void
panfrost_analyze_sysvals(struct panfrost_shader_state * ss)28 panfrost_analyze_sysvals(struct panfrost_shader_state *ss)
29 {
30 unsigned dirty = 0;
31 unsigned dirty_shader =
32 PAN_DIRTY_STAGE_RENDERER | PAN_DIRTY_STAGE_CONST;
33
34 for (unsigned i = 0; i < ss->info.sysvals.sysval_count; ++i) {
35 switch (PAN_SYSVAL_TYPE(ss->info.sysvals.sysvals[i])) {
36 case PAN_SYSVAL_VIEWPORT_SCALE:
37 case PAN_SYSVAL_VIEWPORT_OFFSET:
38 dirty |= PAN_DIRTY_VIEWPORT;
39 break;
40
41 case PAN_SYSVAL_TEXTURE_SIZE:
42 dirty_shader |= PAN_DIRTY_STAGE_TEXTURE;
43 break;
44
45 case PAN_SYSVAL_SSBO:
46 dirty_shader |= PAN_DIRTY_STAGE_SSBO;
47 break;
48
49 case PAN_SYSVAL_SAMPLER:
50 dirty_shader |= PAN_DIRTY_STAGE_SAMPLER;
51 break;
52
53 case PAN_SYSVAL_IMAGE_SIZE:
54 dirty_shader |= PAN_DIRTY_STAGE_IMAGE;
55 break;
56
57 case PAN_SYSVAL_NUM_WORK_GROUPS:
58 case PAN_SYSVAL_LOCAL_GROUP_SIZE:
59 case PAN_SYSVAL_WORK_DIM:
60 case PAN_SYSVAL_VERTEX_INSTANCE_OFFSETS:
61 dirty |= PAN_DIRTY_PARAMS;
62 break;
63
64 case PAN_SYSVAL_DRAWID:
65 dirty |= PAN_DIRTY_DRAWID;
66 break;
67
68 case PAN_SYSVAL_SAMPLE_POSITIONS:
69 case PAN_SYSVAL_MULTISAMPLED:
70 case PAN_SYSVAL_RT_CONVERSION:
71 /* Nothing beyond the batch itself */
72 break;
73 default:
74 unreachable("Invalid sysval");
75 }
76 }
77
78 ss->dirty_3d = dirty;
79 ss->dirty_shader = dirty_shader;
80 }
81
82 /* Gets a GPU address for the associated index buffer. Only gauranteed to be
83 * good for the duration of the draw (transient), could last longer. Also get
84 * the bounds on the index buffer for the range accessed by the draw. We do
85 * these operations together because there are natural optimizations which
86 * require them to be together. */
87
88 mali_ptr
panfrost_get_index_buffer_bounded(struct panfrost_batch * batch,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw,unsigned * min_index,unsigned * max_index)89 panfrost_get_index_buffer_bounded(struct panfrost_batch *batch,
90 const struct pipe_draw_info *info,
91 const struct pipe_draw_start_count_bias *draw,
92 unsigned *min_index, unsigned *max_index)
93 {
94 struct panfrost_resource *rsrc = pan_resource(info->index.resource);
95 struct panfrost_context *ctx = batch->ctx;
96 off_t offset = draw->start * info->index_size;
97 bool needs_indices = true;
98 mali_ptr out = 0;
99
100 if (info->index_bounds_valid) {
101 *min_index = info->min_index;
102 *max_index = info->max_index;
103 needs_indices = false;
104 }
105
106 if (!info->has_user_indices) {
107 /* Only resources can be directly mapped */
108 panfrost_batch_read_rsrc(batch, rsrc, PIPE_SHADER_VERTEX);
109 out = rsrc->image.data.bo->ptr.gpu + offset;
110
111 /* Check the cache */
112 needs_indices = !panfrost_minmax_cache_get(rsrc->index_cache,
113 draw->start,
114 draw->count,
115 min_index,
116 max_index);
117 } else {
118 /* Otherwise, we need to upload to transient memory */
119 const uint8_t *ibuf8 = (const uint8_t *) info->index.user;
120 struct panfrost_ptr T =
121 pan_pool_alloc_aligned(&batch->pool.base,
122 draw->count *
123 info->index_size,
124 info->index_size);
125
126 memcpy(T.cpu, ibuf8 + offset, draw->count * info->index_size);
127 out = T.gpu;
128 }
129
130 if (needs_indices) {
131 /* Fallback */
132 u_vbuf_get_minmax_index(&ctx->base, info, draw, min_index, max_index);
133
134 if (!info->has_user_indices)
135 panfrost_minmax_cache_add(rsrc->index_cache,
136 draw->start, draw->count,
137 *min_index, *max_index);
138 }
139
140 return out;
141 }
142
143
144