• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2024 Collabora Ltd.
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #ifndef PANVK_CMD_DRAW_H
7 #define PANVK_CMD_DRAW_H
8 
9 #ifndef PAN_ARCH
10 #error "PAN_ARCH must be defined"
11 #endif
12 
13 #include "panvk_blend.h"
14 #include "panvk_cmd_oq.h"
15 #include "panvk_entrypoints.h"
16 #include "panvk_image.h"
17 #include "panvk_image_view.h"
18 #include "panvk_physical_device.h"
19 
20 #include "vk_command_buffer.h"
21 #include "vk_format.h"
22 
23 #include "pan_props.h"
24 
25 #define MAX_VBS 16
26 #define MAX_RTS 8
27 
28 struct panvk_cmd_buffer;
29 
30 struct panvk_attrib_buf {
31    uint64_t address;
32    unsigned size;
33 };
34 
35 struct panvk_resolve_attachment {
36    VkResolveModeFlagBits mode;
37    struct panvk_image_view *dst_iview;
38 };
39 
40 struct panvk_rendering_state {
41    VkRenderingFlags flags;
42    uint32_t layer_count;
43    uint32_t view_mask;
44 
45    enum vk_rp_attachment_flags bound_attachments;
46    struct {
47       struct panvk_image_view *iviews[MAX_RTS];
48       VkFormat fmts[MAX_RTS];
49       uint8_t samples[MAX_RTS];
50       struct panvk_resolve_attachment resolve[MAX_RTS];
51    } color_attachments;
52 
53    struct pan_image_view zs_pview;
54    struct pan_image_view s_pview;
55 
56    struct {
57       struct panvk_image_view *iview;
58       VkFormat fmt;
59       struct panvk_resolve_attachment resolve;
60    } z_attachment, s_attachment;
61 
62    struct {
63       struct pan_fb_info info;
64       bool crc_valid[MAX_RTS];
65 
66 #if PAN_ARCH <= 7
67       uint32_t bo_count;
68       struct pan_kmod_bo *bos[MAX_RTS + 2];
69 #endif
70    } fb;
71 
72 #if PAN_ARCH >= 10
73    struct panfrost_ptr fbds;
74    uint64_t tiler;
75 
76    /* When a secondary command buffer has to flush draws, it disturbs the
77     * inherited context, and the primary command buffer needs to know. */
78    bool invalidate_inherited_ctx;
79 
80    /* True if the last render pass was suspended. */
81    bool suspended;
82 
83    struct {
84       /* != 0 if the render pass contains one or more occlusion queries to
85        * signal. */
86       uint64_t chain;
87 
88       /* Point to the syncobj of the last occlusion query that was passed
89        * to a draw. */
90       uint64_t last;
91    } oq;
92 #endif
93 };
94 
95 enum panvk_cmd_graphics_dirty_state {
96    PANVK_CMD_GRAPHICS_DIRTY_VS,
97    PANVK_CMD_GRAPHICS_DIRTY_FS,
98    PANVK_CMD_GRAPHICS_DIRTY_VB,
99    PANVK_CMD_GRAPHICS_DIRTY_IB,
100    PANVK_CMD_GRAPHICS_DIRTY_OQ,
101    PANVK_CMD_GRAPHICS_DIRTY_DESC_STATE,
102    PANVK_CMD_GRAPHICS_DIRTY_RENDER_STATE,
103    PANVK_CMD_GRAPHICS_DIRTY_VS_PUSH_UNIFORMS,
104    PANVK_CMD_GRAPHICS_DIRTY_FS_PUSH_UNIFORMS,
105    PANVK_CMD_GRAPHICS_DIRTY_STATE_COUNT,
106 };
107 
108 struct panvk_cmd_graphics_state {
109    struct panvk_descriptor_state desc_state;
110 
111    struct {
112       struct vk_vertex_input_state vi;
113       struct vk_sample_locations_state sl;
114    } dynamic;
115 
116    struct panvk_occlusion_query_state occlusion_query;
117    struct panvk_graphics_sysvals sysvals;
118 
119 #if PAN_ARCH <= 7
120    struct panvk_shader_link link;
121 #endif
122 
123    struct {
124       const struct panvk_shader *shader;
125       struct panvk_shader_desc_state desc;
126       uint64_t push_uniforms;
127       bool required;
128 #if PAN_ARCH <= 7
129       uint64_t rsd;
130 #endif
131    } fs;
132 
133    struct {
134       const struct panvk_shader *shader;
135       struct panvk_shader_desc_state desc;
136       uint64_t push_uniforms;
137 #if PAN_ARCH <= 7
138       uint64_t attribs;
139       uint64_t attrib_bufs;
140 #endif
141    } vs;
142 
143    struct {
144       struct panvk_attrib_buf bufs[MAX_VBS];
145       unsigned count;
146    } vb;
147 
148    /* Index buffer */
149    struct {
150       struct panvk_buffer *buffer;
151       uint64_t offset;
152       uint8_t index_size;
153    } ib;
154 
155    struct {
156       struct panvk_blend_info info;
157    } cb;
158 
159    struct panvk_rendering_state render;
160 
161 #if PAN_ARCH <= 7
162    uint64_t vpd;
163 #endif
164 
165 #if PAN_ARCH >= 10
166    uint64_t tsd;
167 #endif
168 
169    BITSET_DECLARE(dirty, PANVK_CMD_GRAPHICS_DIRTY_STATE_COUNT);
170 };
171 
172 #define dyn_gfx_state_dirty(__cmdbuf, __name)                                  \
173    BITSET_TEST((__cmdbuf)->vk.dynamic_graphics_state.dirty,                    \
174                MESA_VK_DYNAMIC_##__name)
175 
176 #define gfx_state_dirty(__cmdbuf, __name)                                      \
177    BITSET_TEST((__cmdbuf)->state.gfx.dirty, PANVK_CMD_GRAPHICS_DIRTY_##__name)
178 
179 #define gfx_state_set_dirty(__cmdbuf, __name)                                  \
180    BITSET_SET((__cmdbuf)->state.gfx.dirty, PANVK_CMD_GRAPHICS_DIRTY_##__name)
181 
182 #define gfx_state_clear_all_dirty(__cmdbuf)                                    \
183    BITSET_ZERO((__cmdbuf)->state.gfx.dirty)
184 
185 #define gfx_state_set_all_dirty(__cmdbuf)                                      \
186    BITSET_ONES((__cmdbuf)->state.gfx.dirty)
187 
188 #define set_gfx_sysval(__cmdbuf, __dirty, __name, __val)                       \
189    do {                                                                        \
190       struct panvk_graphics_sysvals __new_sysval;                              \
191       __new_sysval.__name = __val;                                             \
192       if (memcmp(&(__cmdbuf)->state.gfx.sysvals.__name, &__new_sysval.__name,  \
193                  sizeof(__new_sysval.__name))) {                               \
194          (__cmdbuf)->state.gfx.sysvals.__name = __new_sysval.__name;           \
195          BITSET_SET_RANGE(__dirty, sysval_fau_start(graphics, __name),         \
196                           sysval_fau_end(graphics, __name));                   \
197       }                                                                        \
198    } while (0)
199 
200 static inline uint32_t
panvk_select_tiler_hierarchy_mask(const struct panvk_physical_device * phys_dev,const struct panvk_cmd_graphics_state * state)201 panvk_select_tiler_hierarchy_mask(const struct panvk_physical_device *phys_dev,
202                                   const struct panvk_cmd_graphics_state *state)
203 {
204    struct panfrost_tiler_features tiler_features =
205       panfrost_query_tiler_features(&phys_dev->kmod.props);
206 
207    uint32_t hierarchy_mask =
208       pan_select_tiler_hierarchy_mask(state->render.fb.info.width,
209                                       state->render.fb.info.height,
210                                       tiler_features.max_levels);
211 
212    /* For effective tile size larger than 16x16, disable first level */
213    if (state->render.fb.info.tile_size > 16 * 16)
214       hierarchy_mask &= ~1;
215 
216    return hierarchy_mask;
217 }
218 
219 static inline bool
fs_required(const struct panvk_cmd_graphics_state * state,const struct vk_dynamic_graphics_state * dyn_state)220 fs_required(const struct panvk_cmd_graphics_state *state,
221             const struct vk_dynamic_graphics_state *dyn_state)
222 {
223    const struct pan_shader_info *fs_info =
224       state->fs.shader ? &state->fs.shader->info : NULL;
225    const struct vk_color_blend_state *cb = &dyn_state->cb;
226    const struct vk_rasterization_state *rs = &dyn_state->rs;
227 
228    if (rs->rasterizer_discard_enable || !fs_info)
229       return false;
230 
231    /* If we generally have side effects */
232    if (fs_info->fs.sidefx)
233       return true;
234 
235    /* If colour is written we need to execute */
236    for (unsigned i = 0; i < cb->attachment_count; ++i) {
237       if ((cb->color_write_enables & BITFIELD_BIT(i)) &&
238           cb->attachments[i].write_mask)
239          return true;
240    }
241 
242    /* If alpha-to-coverage is enabled, we need to run the fragment shader even
243     * if we don't have a color attachment, so depth/stencil updates can be
244     * discarded if alpha, and thus coverage, is 0. */
245    if (dyn_state->ms.alpha_to_coverage_enable)
246       return true;
247 
248    /* If the sample mask is updated, we need to run the fragment shader,
249     * otherwise the fixed-function depth/stencil results will apply to all
250     * samples. */
251    if (fs_info->outputs_written & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK))
252       return true;
253 
254    /* If depth is written and not implied we need to execute.
255     * TODO: Predicate on Z/S writes being enabled */
256    return (fs_info->fs.writes_depth || fs_info->fs.writes_stencil);
257 }
258 
259 static inline bool
cached_fs_required(ASSERTED const struct panvk_cmd_graphics_state * state,ASSERTED const struct vk_dynamic_graphics_state * dyn_state,bool cached_value)260 cached_fs_required(ASSERTED const struct panvk_cmd_graphics_state *state,
261                    ASSERTED const struct vk_dynamic_graphics_state *dyn_state,
262                    bool cached_value)
263 {
264    /* Make sure the cached value was properly initialized. */
265    assert(fs_required(state, dyn_state) == cached_value);
266    return cached_value;
267 }
268 
269 #define get_fs(__cmdbuf)                                                       \
270    (cached_fs_required(&(__cmdbuf)->state.gfx,                                 \
271                        &(__cmdbuf)->vk.dynamic_graphics_state,                 \
272                        (__cmdbuf)->state.gfx.fs.required)                      \
273        ? (__cmdbuf)->state.gfx.fs.shader                                       \
274        : NULL)
275 
276 /* Anything that might change the value returned by get_fs() makes users of the
277  * fragment shader dirty, because not using the fragment shader (when
278  * fs_required() returns false) impacts various other things, like VS -> FS
279  * linking in the JM backend, or the update of the fragment shader pointer in
280  * the CSF backend. Call gfx_state_dirty(cmdbuf, FS) if you only care about
281  * fragment shader updates. */
282 
283 #define fs_user_dirty(__cmdbuf)                                                \
284    (gfx_state_dirty(cmdbuf, FS) ||                                             \
285     dyn_gfx_state_dirty(cmdbuf, RS_RASTERIZER_DISCARD_ENABLE) ||               \
286     dyn_gfx_state_dirty(cmdbuf, CB_ATTACHMENT_COUNT) ||                        \
287     dyn_gfx_state_dirty(cmdbuf, CB_COLOR_WRITE_ENABLES) ||                     \
288     dyn_gfx_state_dirty(cmdbuf, CB_WRITE_MASKS) ||                             \
289     dyn_gfx_state_dirty(cmdbuf, MS_ALPHA_TO_COVERAGE_ENABLE))
290 
291 /* After a draw, all dirty flags are cleared except the FS dirty flag which
292  * needs to be set again if the draw didn't use the fragment shader. */
293 
294 #define clear_dirty_after_draw(__cmdbuf)                                       \
295    do {                                                                        \
296       bool __set_fs_dirty =                                                    \
297          (__cmdbuf)->state.gfx.fs.shader != get_fs(__cmdbuf);                  \
298       bool __set_fs_push_dirty =                                               \
299          __set_fs_dirty && gfx_state_dirty(__cmdbuf, FS_PUSH_UNIFORMS);        \
300       vk_dynamic_graphics_state_clear_dirty(                                   \
301          &(__cmdbuf)->vk.dynamic_graphics_state);                              \
302       gfx_state_clear_all_dirty(__cmdbuf);                                     \
303       if (__set_fs_dirty)                                                      \
304          gfx_state_set_dirty(__cmdbuf, FS);                                    \
305       if (__set_fs_push_dirty)                                                 \
306          gfx_state_set_dirty(__cmdbuf, FS_PUSH_UNIFORMS);                      \
307    } while (0)
308 
309 void
310 panvk_per_arch(cmd_init_render_state)(struct panvk_cmd_buffer *cmdbuf,
311                                       const VkRenderingInfo *pRenderingInfo);
312 
313 void
314 panvk_per_arch(cmd_force_fb_preload)(struct panvk_cmd_buffer *cmdbuf,
315                                      const VkRenderingInfo *render_info);
316 
317 void
318 panvk_per_arch(cmd_preload_render_area_border)(struct panvk_cmd_buffer *cmdbuf,
319                                                const VkRenderingInfo *render_info);
320 
321 void panvk_per_arch(cmd_resolve_attachments)(struct panvk_cmd_buffer *cmdbuf);
322 
323 struct panvk_draw_info {
324    struct {
325       uint32_t size;
326       uint32_t offset;
327    } index;
328 
329    struct {
330 #if PAN_ARCH <= 7
331       int32_t raw_offset;
332 #endif
333       int32_t base;
334       uint32_t count;
335    } vertex;
336 
337    struct {
338       int32_t base;
339       uint32_t count;
340    } instance;
341 
342    struct {
343       uint64_t buffer_dev_addr;
344       uint32_t draw_count;
345       uint32_t stride;
346    } indirect;
347 
348 #if PAN_ARCH <= 7
349    uint32_t layer_id;
350 #endif
351 };
352 
353 void
354 panvk_per_arch(cmd_prepare_draw_sysvals)(struct panvk_cmd_buffer *cmdbuf,
355                                          const struct panvk_draw_info *info);
356 
357 #endif
358