1 /*
2 * Copyright (C) 2018 Alyssa Rosenzweig
3 * Copyright (C) 2020 Collabora Ltd.
4 * Copyright © 2017 Intel Corporation
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26 #ifndef __PAN_CMDSTREAM_H__
27 #define __PAN_CMDSTREAM_H__
28
29 #ifndef PAN_ARCH
30 #error "PAN_ARCH undefined!"
31 #endif
32
33 #include "genxml/gen_macros.h"
34
35 #include "pan_context.h"
36 #include "pan_job.h"
37
38 #include "pipe/p_defines.h"
39 #include "pipe/p_state.h"
40
41 #include "util/u_prim.h"
42
43 #define PAN_GPU_SUPPORTS_DISPATCH_INDIRECT (PAN_ARCH == 7 || PAN_ARCH >= 10)
44 #define PAN_GPU_SUPPORTS_DRAW_INDIRECT (PAN_ARCH >= 10)
45
46 struct panfrost_rasterizer {
47 struct pipe_rasterizer_state base;
48
49 #if PAN_ARCH <= 7
50 /* Partially packed RSD words */
51 struct mali_multisample_misc_packed multisample;
52 struct mali_stencil_mask_misc_packed stencil_misc;
53 #endif
54 };
55
56 struct panfrost_zsa_state {
57 struct pipe_depth_stencil_alpha_state base;
58
59 /* Is any depth, stencil, or alpha testing enabled? */
60 bool enabled;
61
62 /* Does the depth and stencil tests always pass? This ignores write
63 * masks, we are only interested in whether pixels may be killed.
64 */
65 bool zs_always_passes;
66
67 /* Are depth or stencil writes possible? */
68 bool writes_zs;
69
70 #if PAN_ARCH <= 7
71 /* Prepacked words from the RSD */
72 struct mali_multisample_misc_packed rsd_depth;
73 struct mali_stencil_mask_misc_packed rsd_stencil;
74 struct mali_stencil_packed stencil_front, stencil_back;
75 #else
76 /* Depth/stencil descriptor template */
77 struct mali_depth_stencil_packed desc;
78 #endif
79 };
80
81 struct panfrost_vertex_state {
82 unsigned num_elements;
83 struct pipe_vertex_element pipe[PIPE_MAX_ATTRIBS];
84 uint16_t strides[PIPE_MAX_ATTRIBS];
85
86 #if PAN_ARCH >= 9
87 /* Packed attribute descriptors */
88 struct mali_attribute_packed attributes[PIPE_MAX_ATTRIBS];
89 #else
90 /* buffers corresponds to attribute buffer, element_buffers corresponds
91 * to an index in buffers for each vertex element */
92 struct pan_vertex_buffer buffers[PIPE_MAX_ATTRIBS];
93 unsigned element_buffer[PIPE_MAX_ATTRIBS];
94 unsigned nr_bufs;
95
96 unsigned formats[PIPE_MAX_ATTRIBS];
97 #endif
98 };
99
100 static inline bool
panfrost_is_implicit_prim_restart(const struct pipe_draw_info * info)101 panfrost_is_implicit_prim_restart(const struct pipe_draw_info *info)
102 {
103 /* As a reminder primitive_restart should always be checked before any
104 access to restart_index. */
105 return info->primitive_restart &&
106 info->restart_index == (unsigned)BITFIELD_MASK(info->index_size * 8);
107 }
108
109 static inline bool
pan_allow_forward_pixel_to_kill(struct panfrost_context * ctx,struct panfrost_compiled_shader * fs)110 pan_allow_forward_pixel_to_kill(struct panfrost_context *ctx,
111 struct panfrost_compiled_shader *fs)
112 {
113 /* Track if any colour buffer is reused across draws, either
114 * from reading it directly, or from failing to write it
115 */
116 unsigned rt_mask = ctx->fb_rt_mask;
117 uint64_t rt_written = (fs->info.outputs_written >> FRAG_RESULT_DATA0) &
118 ctx->blend->enabled_mask;
119 bool blend_reads_dest = (ctx->blend->load_dest_mask & rt_mask);
120 bool alpha_to_coverage = ctx->blend->base.alpha_to_coverage;
121
122 return fs->info.fs.can_fpk && !(rt_mask & ~rt_written) &&
123 !alpha_to_coverage && !blend_reads_dest;
124 }
125
126 /*
127 * Determine whether to set the respective overdraw alpha flag.
128 *
129 * The overdraw alpha=1 flag should be set when alpha=1 implies full overdraw,
130 * equivalently, all enabled render targets have alpha_one_store set. Likewise,
131 * overdraw alpha=0 should be set when alpha=0 implies no overdraw,
132 * equivalently, all enabled render targets have alpha_zero_nop set.
133 */
134 #if PAN_ARCH >= 6
135 static inline bool
panfrost_overdraw_alpha(const struct panfrost_context * ctx,bool zero)136 panfrost_overdraw_alpha(const struct panfrost_context *ctx, bool zero)
137 {
138 const struct panfrost_blend_state *so = ctx->blend;
139
140 for (unsigned i = 0; i < ctx->pipe_framebuffer.nr_cbufs; ++i) {
141 const struct pan_blend_info info = so->info[i];
142
143 bool enabled = ctx->pipe_framebuffer.cbufs[i] && !info.enabled;
144 bool flag = zero ? info.alpha_zero_nop : info.alpha_one_store;
145
146 if (enabled && !flag)
147 return false;
148 }
149
150 return true;
151 }
152 #endif
153
154 static inline void
panfrost_emit_primitive_size(struct panfrost_context * ctx,bool points,mali_ptr size_array,void * prim_size)155 panfrost_emit_primitive_size(struct panfrost_context *ctx, bool points,
156 mali_ptr size_array, void *prim_size)
157 {
158 struct panfrost_rasterizer *rast = ctx->rasterizer;
159
160 pan_pack(prim_size, PRIMITIVE_SIZE, cfg) {
161 if (panfrost_writes_point_size(ctx)) {
162 cfg.size_array = size_array;
163 } else {
164 cfg.constant = points ? rast->base.point_size : rast->base.line_width;
165 }
166 }
167 }
168
169 static inline uint8_t
pan_draw_mode(enum mesa_prim mode)170 pan_draw_mode(enum mesa_prim mode)
171 {
172 switch (mode) {
173
174 #define DEFINE_CASE(c) \
175 case MESA_PRIM_##c: \
176 return MALI_DRAW_MODE_##c;
177
178 DEFINE_CASE(POINTS);
179 DEFINE_CASE(LINES);
180 DEFINE_CASE(LINE_LOOP);
181 DEFINE_CASE(LINE_STRIP);
182 DEFINE_CASE(TRIANGLES);
183 DEFINE_CASE(TRIANGLE_STRIP);
184 DEFINE_CASE(TRIANGLE_FAN);
185 DEFINE_CASE(QUADS);
186 DEFINE_CASE(POLYGON);
187 #if PAN_ARCH <= 6
188 DEFINE_CASE(QUAD_STRIP);
189 #endif
190
191 #undef DEFINE_CASE
192
193 default:
194 unreachable("Invalid draw mode");
195 }
196 }
197
198 static inline enum mali_index_type
panfrost_translate_index_size(unsigned size)199 panfrost_translate_index_size(unsigned size)
200 {
201 STATIC_ASSERT(MALI_INDEX_TYPE_NONE == 0);
202 STATIC_ASSERT(MALI_INDEX_TYPE_UINT8 == 1);
203 STATIC_ASSERT(MALI_INDEX_TYPE_UINT16 == 2);
204
205 return (size == 4) ? MALI_INDEX_TYPE_UINT32 : size;
206 }
207
208 static inline bool
panfrost_fs_required(struct panfrost_compiled_shader * fs,struct panfrost_blend_state * blend,struct pipe_framebuffer_state * state,const struct panfrost_zsa_state * zsa)209 panfrost_fs_required(struct panfrost_compiled_shader *fs,
210 struct panfrost_blend_state *blend,
211 struct pipe_framebuffer_state *state,
212 const struct panfrost_zsa_state *zsa)
213 {
214 /* If we generally have side effects. This inclues use of discard,
215 * which can affect the results of an occlusion query. */
216 if (fs->info.fs.sidefx)
217 return true;
218
219 /* Using an empty FS requires early-z to be enabled, but alpha test
220 * needs it disabled. Alpha test is only native on Midgard, so only
221 * check there.
222 */
223 if (PAN_ARCH <= 5 && zsa->base.alpha_func != PIPE_FUNC_ALWAYS)
224 return true;
225
226 /* If colour is written we need to execute */
227 for (unsigned i = 0; i < state->nr_cbufs; ++i) {
228 if (state->cbufs[i] && blend->info[i].enabled)
229 return true;
230 }
231
232 /* If depth is written and not implied we need to execute.
233 * TODO: Predicate on Z/S writes being enabled */
234 return (fs->info.fs.writes_depth || fs->info.fs.writes_stencil);
235 }
236
237 #if PAN_ARCH >= 9
238 static inline mali_ptr
panfrost_get_position_shader(struct panfrost_batch * batch,const struct pipe_draw_info * info)239 panfrost_get_position_shader(struct panfrost_batch *batch,
240 const struct pipe_draw_info *info)
241 {
242 /* IDVS/points vertex shader */
243 mali_ptr vs_ptr = batch->rsd[PIPE_SHADER_VERTEX];
244
245 /* IDVS/triangle vertex shader */
246 if (vs_ptr && info->mode != MESA_PRIM_POINTS)
247 vs_ptr += pan_size(SHADER_PROGRAM);
248
249 return vs_ptr;
250 }
251
252 static inline mali_ptr
panfrost_get_varying_shader(struct panfrost_batch * batch)253 panfrost_get_varying_shader(struct panfrost_batch *batch)
254 {
255 return batch->rsd[PIPE_SHADER_VERTEX] + (2 * pan_size(SHADER_PROGRAM));
256 }
257
258 static inline unsigned
panfrost_vertex_attribute_stride(struct panfrost_compiled_shader * vs,struct panfrost_compiled_shader * fs)259 panfrost_vertex_attribute_stride(struct panfrost_compiled_shader *vs,
260 struct panfrost_compiled_shader *fs)
261 {
262 unsigned v = vs->info.varyings.output_count;
263 unsigned f = fs->info.varyings.input_count;
264 unsigned slots = MAX2(v, f);
265 slots += util_bitcount(fs->key.fs.fixed_varying_mask);
266
267 /* Assumes 16 byte slots. We could do better. */
268 return slots * 16;
269 }
270
271 static inline mali_ptr
panfrost_emit_resources(struct panfrost_batch * batch,enum pipe_shader_type stage)272 panfrost_emit_resources(struct panfrost_batch *batch,
273 enum pipe_shader_type stage)
274 {
275 struct panfrost_context *ctx = batch->ctx;
276 struct panfrost_ptr T;
277 unsigned nr_tables = PAN_NUM_RESOURCE_TABLES;
278
279 /* Although individual resources need only 16 byte alignment, the
280 * resource table as a whole must be 64-byte aligned.
281 */
282 T = pan_pool_alloc_aligned(&batch->pool.base, nr_tables * pan_size(RESOURCE),
283 64);
284 memset(T.cpu, 0, nr_tables * pan_size(RESOURCE));
285
286 panfrost_make_resource_table(T, PAN_TABLE_UBO, batch->uniform_buffers[stage],
287 batch->nr_uniform_buffers[stage]);
288
289 panfrost_make_resource_table(T, PAN_TABLE_TEXTURE, batch->textures[stage],
290 ctx->sampler_view_count[stage]);
291
292 /* We always need at least 1 sampler for txf to work */
293 panfrost_make_resource_table(T, PAN_TABLE_SAMPLER, batch->samplers[stage],
294 MAX2(ctx->sampler_count[stage], 1));
295
296 panfrost_make_resource_table(T, PAN_TABLE_IMAGE, batch->images[stage],
297 util_last_bit(ctx->image_mask[stage]));
298
299 if (stage == PIPE_SHADER_VERTEX) {
300 panfrost_make_resource_table(T, PAN_TABLE_ATTRIBUTE,
301 batch->attribs[stage],
302 ctx->vertex->num_elements);
303
304 panfrost_make_resource_table(T, PAN_TABLE_ATTRIBUTE_BUFFER,
305 batch->attrib_bufs[stage],
306 util_last_bit(ctx->vb_mask));
307 }
308
309 panfrost_make_resource_table(T, PAN_TABLE_SSBO, batch->ssbos[stage],
310 util_last_bit(ctx->ssbo_mask[stage]));
311
312 return T.gpu | nr_tables;
313 }
314 #endif /* PAN_ARCH >= 9 */
315
316 static bool
allow_rotating_primitives(const struct panfrost_compiled_shader * fs,const struct pipe_draw_info * info)317 allow_rotating_primitives(const struct panfrost_compiled_shader *fs,
318 const struct pipe_draw_info *info)
319 {
320 return u_reduced_prim(info->mode) != MESA_PRIM_LINES &&
321 !fs->info.bifrost.uses_flat_shading;
322 }
323
324 #endif
325