1 /*
2  * Copyright 2021 Alyssa Rosenzweig
3  * Copyright (C) 2019-2020 Collabora, Ltd.
4  * Copyright 2010 Red Hat Inc.
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  * on the rights to use, copy, modify, merge, publish, distribute, sub
10  * license, and/or sell copies of the Software, and to permit persons to whom
11  * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23  * USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 #include <stdio.h>
26 #include <errno.h>
27 #include "pipe/p_defines.h"
28 #include "pipe/p_state.h"
29 #include "pipe/p_context.h"
30 #include "pipe/p_screen.h"
31 #include "util/u_memory.h"
32 #include "util/u_inlines.h"
33 #include "util/u_transfer.h"
34 #include "gallium/auxiliary/util/u_draw.h"
35 #include "gallium/auxiliary/util/u_helpers.h"
36 #include "gallium/auxiliary/util/u_viewport.h"
37 #include "gallium/auxiliary/util/u_blend.h"
38 #include "gallium/auxiliary/util/u_framebuffer.h"
39 #include "gallium/auxiliary/tgsi/tgsi_from_mesa.h"
40 #include "gallium/auxiliary/nir/tgsi_to_nir.h"
41 #include "compiler/nir/nir.h"
42 #include "asahi/compiler/agx_compile.h"
43 #include "agx_state.h"
44 #include "asahi/lib/agx_pack.h"
45 #include "asahi/lib/agx_formats.h"
46 
47 static struct pipe_stream_output_target *
agx_create_stream_output_target(struct pipe_context * pctx,struct pipe_resource * prsc,unsigned buffer_offset,unsigned buffer_size)48 agx_create_stream_output_target(struct pipe_context *pctx,
49                                 struct pipe_resource *prsc,
50                                 unsigned buffer_offset,
51                                 unsigned buffer_size)
52 {
53    struct pipe_stream_output_target *target;
54 
55    target = &rzalloc(pctx, struct agx_streamout_target)->base;
56 
57    if (!target)
58       return NULL;
59 
60    pipe_reference_init(&target->reference, 1);
61    pipe_resource_reference(&target->buffer, prsc);
62 
63    target->context = pctx;
64    target->buffer_offset = buffer_offset;
65    target->buffer_size = buffer_size;
66 
67    return target;
68 }
69 
70 static void
agx_stream_output_target_destroy(struct pipe_context * pctx,struct pipe_stream_output_target * target)71 agx_stream_output_target_destroy(struct pipe_context *pctx,
72                                  struct pipe_stream_output_target *target)
73 {
74    pipe_resource_reference(&target->buffer, NULL);
75    ralloc_free(target);
76 }
77 
78 static void
agx_set_stream_output_targets(struct pipe_context * pctx,unsigned num_targets,struct pipe_stream_output_target ** targets,const unsigned * offsets)79 agx_set_stream_output_targets(struct pipe_context *pctx,
80                               unsigned num_targets,
81                               struct pipe_stream_output_target **targets,
82                               const unsigned *offsets)
83 {
84    struct agx_context *ctx = agx_context(pctx);
85    struct agx_streamout *so = &ctx->streamout;
86 
87    assert(num_targets <= ARRAY_SIZE(so->targets));
88 
89    for (unsigned i = 0; i < num_targets; i++) {
90       if (offsets[i] != -1)
91          agx_so_target(targets[i])->offset = offsets[i];
92 
93       pipe_so_target_reference(&so->targets[i], targets[i]);
94    }
95 
96    for (unsigned i = 0; i < so->num_targets; i++)
97       pipe_so_target_reference(&so->targets[i], NULL);
98 
99    so->num_targets = num_targets;
100 }
101 
102 static void
agx_set_blend_color(struct pipe_context * pctx,const struct pipe_blend_color * state)103 agx_set_blend_color(struct pipe_context *pctx,
104                     const struct pipe_blend_color *state)
105 {
106    struct agx_context *ctx = agx_context(pctx);
107 
108    if (state)
109       memcpy(&ctx->blend_color, state, sizeof(*state));
110 }
111 
112 static void *
agx_create_blend_state(struct pipe_context * ctx,const struct pipe_blend_state * state)113 agx_create_blend_state(struct pipe_context *ctx,
114                        const struct pipe_blend_state *state)
115 {
116    struct agx_blend *so = CALLOC_STRUCT(agx_blend);
117 
118    assert(!state->alpha_to_coverage);
119    assert(!state->alpha_to_coverage_dither);
120    assert(!state->alpha_to_one);
121    assert(!state->advanced_blend_func);
122 
123    if (state->logicop_enable) {
124       so->logicop_enable = true;
125       so->logicop_func = state->logicop_func;
126       return so;
127    }
128 
129    for (unsigned i = 0; i < PIPE_MAX_COLOR_BUFS; ++i) {
130       unsigned rti = state->independent_blend_enable ? i : 0;
131       struct pipe_rt_blend_state rt = state->rt[rti];
132 
133       if (!rt.blend_enable) {
134          static const nir_lower_blend_channel replace = {
135             .func = BLEND_FUNC_ADD,
136             .src_factor = BLEND_FACTOR_ZERO,
137             .invert_src_factor = true,
138             .dst_factor = BLEND_FACTOR_ZERO,
139             .invert_dst_factor = false,
140          };
141 
142          so->rt[i].rgb = replace;
143          so->rt[i].alpha = replace;
144       } else {
145          so->rt[i].rgb.func = util_blend_func_to_shader(rt.rgb_func);
146          so->rt[i].rgb.src_factor = util_blend_factor_to_shader(rt.rgb_src_factor);
147          so->rt[i].rgb.invert_src_factor = util_blend_factor_is_inverted(rt.rgb_src_factor);
148          so->rt[i].rgb.dst_factor = util_blend_factor_to_shader(rt.rgb_dst_factor);
149          so->rt[i].rgb.invert_dst_factor = util_blend_factor_is_inverted(rt.rgb_dst_factor);
150 
151          so->rt[i].alpha.func = util_blend_func_to_shader(rt.alpha_func);
152          so->rt[i].alpha.src_factor = util_blend_factor_to_shader(rt.alpha_src_factor);
153          so->rt[i].alpha.invert_src_factor = util_blend_factor_is_inverted(rt.alpha_src_factor);
154          so->rt[i].alpha.dst_factor = util_blend_factor_to_shader(rt.alpha_dst_factor);
155          so->rt[i].alpha.invert_dst_factor = util_blend_factor_is_inverted(rt.alpha_dst_factor);
156 
157 	 so->blend_enable = true;
158       }
159 
160       so->rt[i].colormask = rt.colormask;
161    }
162 
163    return so;
164 }
165 
166 static void
agx_bind_blend_state(struct pipe_context * pctx,void * cso)167 agx_bind_blend_state(struct pipe_context *pctx, void *cso)
168 {
169    struct agx_context *ctx = agx_context(pctx);
170    ctx->blend = cso;
171 }
172 
173 static const enum agx_stencil_op agx_stencil_ops[PIPE_STENCIL_OP_INVERT + 1] = {
174    [PIPE_STENCIL_OP_KEEP] = AGX_STENCIL_OP_KEEP,
175    [PIPE_STENCIL_OP_ZERO] = AGX_STENCIL_OP_ZERO,
176    [PIPE_STENCIL_OP_REPLACE] = AGX_STENCIL_OP_REPLACE,
177    [PIPE_STENCIL_OP_INCR] = AGX_STENCIL_OP_INCR_SAT,
178    [PIPE_STENCIL_OP_DECR] = AGX_STENCIL_OP_DECR_SAT,
179    [PIPE_STENCIL_OP_INCR_WRAP] = AGX_STENCIL_OP_INCR_WRAP,
180    [PIPE_STENCIL_OP_DECR_WRAP] = AGX_STENCIL_OP_DECR_WRAP,
181    [PIPE_STENCIL_OP_INVERT] = AGX_STENCIL_OP_INVERT,
182 };
183 
184 static void
agx_pack_rasterizer_face(struct agx_rasterizer_face_packed * out,struct pipe_stencil_state st,enum agx_zs_func z_func,bool disable_z_write)185 agx_pack_rasterizer_face(struct agx_rasterizer_face_packed *out,
186                          struct pipe_stencil_state st,
187                          enum agx_zs_func z_func,
188                          bool disable_z_write)
189 {
190    agx_pack(out, RASTERIZER_FACE, cfg) {
191       cfg.depth_function = z_func;
192       cfg.disable_depth_write = disable_z_write;
193 
194       if (st.enabled) {
195          cfg.stencil_write_mask = st.writemask;
196          cfg.stencil_read_mask = st.valuemask;
197 
198          cfg.depth_pass   = agx_stencil_ops[st.zpass_op];
199          cfg.depth_fail   = agx_stencil_ops[st.zfail_op];
200          cfg.stencil_fail = agx_stencil_ops[st.fail_op];
201 
202          cfg.stencil_compare = (enum agx_zs_func) st.func;
203       } else {
204          cfg.stencil_write_mask = 0xFF;
205          cfg.stencil_read_mask = 0xFF;
206 
207          cfg.depth_pass = AGX_STENCIL_OP_KEEP;
208          cfg.depth_fail = AGX_STENCIL_OP_KEEP;
209          cfg.stencil_fail = AGX_STENCIL_OP_KEEP;
210 
211          cfg.stencil_compare = AGX_ZS_FUNC_ALWAYS;
212       }
213    }
214 }
215 
216 static void *
agx_create_zsa_state(struct pipe_context * ctx,const struct pipe_depth_stencil_alpha_state * state)217 agx_create_zsa_state(struct pipe_context *ctx,
218                      const struct pipe_depth_stencil_alpha_state *state)
219 {
220    struct agx_zsa *so = CALLOC_STRUCT(agx_zsa);
221    assert(!state->depth_bounds_test && "todo");
222 
223    so->base = *state;
224 
225    /* Z func can be used as-is */
226    STATIC_ASSERT((enum agx_zs_func) PIPE_FUNC_NEVER    == AGX_ZS_FUNC_NEVER);
227    STATIC_ASSERT((enum agx_zs_func) PIPE_FUNC_LESS     == AGX_ZS_FUNC_LESS);
228    STATIC_ASSERT((enum agx_zs_func) PIPE_FUNC_EQUAL    == AGX_ZS_FUNC_EQUAL);
229    STATIC_ASSERT((enum agx_zs_func) PIPE_FUNC_LEQUAL   == AGX_ZS_FUNC_LEQUAL);
230    STATIC_ASSERT((enum agx_zs_func) PIPE_FUNC_GREATER  == AGX_ZS_FUNC_GREATER);
231    STATIC_ASSERT((enum agx_zs_func) PIPE_FUNC_NOTEQUAL == AGX_ZS_FUNC_NOT_EQUAL);
232    STATIC_ASSERT((enum agx_zs_func) PIPE_FUNC_GEQUAL   == AGX_ZS_FUNC_GEQUAL);
233    STATIC_ASSERT((enum agx_zs_func) PIPE_FUNC_ALWAYS   == AGX_ZS_FUNC_ALWAYS);
234 
235    enum agx_zs_func z_func = state->depth_enabled ?
236                 ((enum agx_zs_func) state->depth_func) : AGX_ZS_FUNC_ALWAYS;
237 
238    agx_pack_rasterizer_face(&so->front,
239          state->stencil[0], z_func, !state->depth_writemask);
240 
241    if (state->stencil[1].enabled) {
242       agx_pack_rasterizer_face(&so->back,
243             state->stencil[1], z_func, !state->depth_writemask);
244    } else {
245       /* One sided stencil */
246       so->back = so->front;
247    }
248 
249    return so;
250 }
251 
252 static void
agx_bind_zsa_state(struct pipe_context * pctx,void * cso)253 agx_bind_zsa_state(struct pipe_context *pctx, void *cso)
254 {
255    struct agx_context *ctx = agx_context(pctx);
256 
257    if (cso)
258       memcpy(&ctx->zs, cso, sizeof(ctx->zs));
259 }
260 
261 static void *
agx_create_rs_state(struct pipe_context * ctx,const struct pipe_rasterizer_state * cso)262 agx_create_rs_state(struct pipe_context *ctx,
263                     const struct pipe_rasterizer_state *cso)
264 {
265    struct agx_rasterizer *so = CALLOC_STRUCT(agx_rasterizer);
266    so->base = *cso;
267 
268    /* Line width is packed in a 4:4 fixed point format */
269    unsigned line_width_fixed = ((unsigned) (cso->line_width * 16.0f)) - 1;
270 
271    /* Clamp to maximum line width */
272    so->line_width = MIN2(line_width_fixed, 0xFF);
273 
274    agx_pack(so->cull, CULL, cfg) {
275       cfg.cull_front = cso->cull_face & PIPE_FACE_FRONT;
276       cfg.cull_back = cso->cull_face & PIPE_FACE_BACK;
277       cfg.front_face_ccw = cso->front_ccw;
278       cfg.depth_clip = cso->depth_clip_near;
279       cfg.depth_clamp = !cso->depth_clip_near;
280    };
281 
282    return so;
283 }
284 
285 static void
agx_bind_rasterizer_state(struct pipe_context * pctx,void * cso)286 agx_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
287 {
288    struct agx_context *ctx = agx_context(pctx);
289    struct agx_rasterizer *so = cso;
290 
291    /* Check if scissor state has changed, since scissor enable is part of the
292     * rasterizer state but everything else needed for scissors is part of
293     * viewport/scissor states */
294    bool scissor_changed = (cso == NULL) || (ctx->rast == NULL) ||
295       (ctx->rast->base.scissor != so->base.scissor);
296 
297    ctx->rast = so;
298 
299    if (scissor_changed)
300       ctx->dirty |= AGX_DIRTY_SCISSOR;
301 }
302 
303 static enum agx_wrap
agx_wrap_from_pipe(enum pipe_tex_wrap in)304 agx_wrap_from_pipe(enum pipe_tex_wrap in)
305 {
306    switch (in) {
307    case PIPE_TEX_WRAP_REPEAT: return AGX_WRAP_REPEAT;
308    case PIPE_TEX_WRAP_CLAMP_TO_EDGE: return AGX_WRAP_CLAMP_TO_EDGE;
309    case PIPE_TEX_WRAP_MIRROR_REPEAT: return AGX_WRAP_MIRRORED_REPEAT;
310    case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return AGX_WRAP_CLAMP_TO_BORDER;
311    default: unreachable("todo: more wrap modes");
312    }
313 }
314 
315 static enum agx_mip_filter
agx_mip_filter_from_pipe(enum pipe_tex_mipfilter in)316 agx_mip_filter_from_pipe(enum pipe_tex_mipfilter in)
317 {
318    switch (in) {
319    case PIPE_TEX_MIPFILTER_NEAREST: return AGX_MIP_FILTER_NEAREST;
320    case PIPE_TEX_MIPFILTER_LINEAR: return AGX_MIP_FILTER_LINEAR;
321    case PIPE_TEX_MIPFILTER_NONE: return AGX_MIP_FILTER_NONE;
322    }
323 
324    unreachable("Invalid mip filter");
325 }
326 
327 static const enum agx_compare_func agx_compare_funcs[PIPE_FUNC_ALWAYS + 1] = {
328    [PIPE_FUNC_NEVER] = AGX_COMPARE_FUNC_NEVER,
329    [PIPE_FUNC_LESS] = AGX_COMPARE_FUNC_LESS,
330    [PIPE_FUNC_EQUAL] = AGX_COMPARE_FUNC_EQUAL,
331    [PIPE_FUNC_LEQUAL] = AGX_COMPARE_FUNC_LEQUAL,
332    [PIPE_FUNC_GREATER] = AGX_COMPARE_FUNC_GREATER,
333    [PIPE_FUNC_NOTEQUAL] = AGX_COMPARE_FUNC_NOT_EQUAL,
334    [PIPE_FUNC_GEQUAL] = AGX_COMPARE_FUNC_GEQUAL,
335    [PIPE_FUNC_ALWAYS] = AGX_COMPARE_FUNC_ALWAYS,
336 };
337 
338 static void *
agx_create_sampler_state(struct pipe_context * pctx,const struct pipe_sampler_state * state)339 agx_create_sampler_state(struct pipe_context *pctx,
340                          const struct pipe_sampler_state *state)
341 {
342    struct agx_device *dev = agx_device(pctx->screen);
343    struct agx_bo *bo = agx_bo_create(dev, AGX_SAMPLER_LENGTH,
344                                      AGX_MEMORY_TYPE_FRAMEBUFFER);
345 
346    assert(state->lod_bias == 0 && "todo: lod bias");
347 
348    agx_pack(bo->ptr.cpu, SAMPLER, cfg) {
349       cfg.minimum_lod = state->min_lod;
350       cfg.maximum_lod = state->max_lod;
351       cfg.magnify_linear = (state->mag_img_filter == PIPE_TEX_FILTER_LINEAR);
352       cfg.minify_linear = (state->min_img_filter == PIPE_TEX_FILTER_LINEAR);
353       cfg.mip_filter = agx_mip_filter_from_pipe(state->min_mip_filter);
354       cfg.wrap_s = agx_wrap_from_pipe(state->wrap_s);
355       cfg.wrap_t = agx_wrap_from_pipe(state->wrap_t);
356       cfg.wrap_r = agx_wrap_from_pipe(state->wrap_r);
357       cfg.pixel_coordinates = !state->normalized_coords;
358       cfg.compare_func = agx_compare_funcs[state->compare_func];
359    }
360 
361    struct agx_sampler_state *so = CALLOC_STRUCT(agx_sampler_state);
362    so->base = *state;
363    so->desc = bo;
364 
365    return so;
366 }
367 
368 static void
agx_delete_sampler_state(struct pipe_context * ctx,void * state)369 agx_delete_sampler_state(struct pipe_context *ctx, void *state)
370 {
371    struct agx_sampler_state *so = state;
372    agx_bo_unreference(so->desc);
373 }
374 
375 static void
agx_bind_sampler_states(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start,unsigned count,void ** states)376 agx_bind_sampler_states(struct pipe_context *pctx,
377                         enum pipe_shader_type shader,
378                         unsigned start, unsigned count,
379                         void **states)
380 {
381    struct agx_context *ctx = agx_context(pctx);
382 
383    ctx->stage[shader].sampler_count = states ? count : 0;
384 
385    memcpy(&ctx->stage[shader].samplers[start], states,
386           sizeof(struct agx_sampler_state *) * count);
387 }
388 
389 /* Channels agree for RGBA but are weird for force 0/1 */
390 
391 static enum agx_channel
agx_channel_from_pipe(enum pipe_swizzle in)392 agx_channel_from_pipe(enum pipe_swizzle in)
393 {
394    STATIC_ASSERT((enum agx_channel) PIPE_SWIZZLE_X == AGX_CHANNEL_R);
395    STATIC_ASSERT((enum agx_channel) PIPE_SWIZZLE_Y == AGX_CHANNEL_G);
396    STATIC_ASSERT((enum agx_channel) PIPE_SWIZZLE_Z == AGX_CHANNEL_B);
397    STATIC_ASSERT((enum agx_channel) PIPE_SWIZZLE_W == AGX_CHANNEL_A);
398    STATIC_ASSERT((enum agx_channel) PIPE_SWIZZLE_0 & 0x4);
399    STATIC_ASSERT((enum agx_channel) PIPE_SWIZZLE_1 & 0x4);
400    STATIC_ASSERT((enum agx_channel) PIPE_SWIZZLE_NONE & 0x4);
401 
402    if ((in & 0x4) == 0)
403       return (enum agx_channel) in;
404    else if (in == PIPE_SWIZZLE_1)
405       return AGX_CHANNEL_1;
406    else
407       return AGX_CHANNEL_0;
408 }
409 
410 static enum agx_layout
agx_translate_layout(uint64_t modifier)411 agx_translate_layout(uint64_t modifier)
412 {
413    switch (modifier) {
414    case DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER:
415       return AGX_LAYOUT_TILED_64X64;
416    case DRM_FORMAT_MOD_LINEAR:
417       return AGX_LAYOUT_LINEAR;
418    default:
419       unreachable("Invalid modifier");
420    }
421 }
422 
423 static enum agx_texture_dimension
agx_translate_texture_dimension(enum pipe_texture_target dim)424 agx_translate_texture_dimension(enum pipe_texture_target dim)
425 {
426    switch (dim) {
427    case PIPE_TEXTURE_2D: return AGX_TEXTURE_DIMENSION_2D;
428    case PIPE_TEXTURE_2D_ARRAY: return AGX_TEXTURE_DIMENSION_2D_ARRAY;
429    case PIPE_TEXTURE_3D: return AGX_TEXTURE_DIMENSION_3D;
430    case PIPE_TEXTURE_CUBE: return AGX_TEXTURE_DIMENSION_CUBE;
431    default: unreachable("Unsupported texture dimension");
432    }
433 }
434 
435 static struct pipe_sampler_view *
agx_create_sampler_view(struct pipe_context * pctx,struct pipe_resource * texture,const struct pipe_sampler_view * state)436 agx_create_sampler_view(struct pipe_context *pctx,
437                         struct pipe_resource *texture,
438                         const struct pipe_sampler_view *state)
439 {
440    struct agx_device *dev = agx_device(pctx->screen);
441    struct agx_resource *rsrc = agx_resource(texture);
442    struct agx_sampler_view *so = CALLOC_STRUCT(agx_sampler_view);
443 
444    if (!so)
445       return NULL;
446 
447    /* We prepare the descriptor at CSO create time */
448    so->desc = agx_bo_create(dev, AGX_TEXTURE_LENGTH,
449                             AGX_MEMORY_TYPE_FRAMEBUFFER);
450 
451    const struct util_format_description *desc =
452       util_format_description(state->format);
453 
454    /* We only have a single swizzle for the user swizzle and the format fixup,
455     * so compose them now. */
456    uint8_t out_swizzle[4];
457    uint8_t view_swizzle[4] = {
458       state->swizzle_r, state->swizzle_g,
459       state->swizzle_b, state->swizzle_a
460    };
461 
462    util_format_compose_swizzles(desc->swizzle, view_swizzle, out_swizzle);
463 
464    unsigned level = state->u.tex.first_level;
465    assert(state->u.tex.first_layer == 0);
466 
467    /* Must tile array textures */
468    assert((rsrc->modifier != DRM_FORMAT_MOD_LINEAR) ||
469           (state->u.tex.last_layer == state->u.tex.first_layer));
470 
471    /* Pack the descriptor into GPU memory */
472    agx_pack(so->desc->ptr.cpu, TEXTURE, cfg) {
473       cfg.dimension = agx_translate_texture_dimension(state->target);
474       cfg.layout = agx_translate_layout(rsrc->modifier);
475       cfg.format = agx_pixel_format[state->format].hw;
476       cfg.swizzle_r = agx_channel_from_pipe(out_swizzle[0]);
477       cfg.swizzle_g = agx_channel_from_pipe(out_swizzle[1]);
478       cfg.swizzle_b = agx_channel_from_pipe(out_swizzle[2]);
479       cfg.swizzle_a = agx_channel_from_pipe(out_swizzle[3]);
480       cfg.width = u_minify(texture->width0, level);
481       cfg.height = u_minify(texture->height0, level);
482       cfg.levels = state->u.tex.last_level - level + 1;
483       cfg.srgb = (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB);
484       cfg.address = agx_map_texture_gpu(rsrc, level, state->u.tex.first_layer);
485       cfg.unk_mipmapped = rsrc->mipmapped;
486       cfg.unk_2 = false;
487 
488       if (state->target == PIPE_TEXTURE_3D)
489          cfg.depth = u_minify(texture->depth0, level);
490       else
491          cfg.depth = state->u.tex.last_layer - state->u.tex.first_layer + 1;
492 
493       cfg.stride = (rsrc->modifier == DRM_FORMAT_MOD_LINEAR) ?
494          (rsrc->slices[level].line_stride - 16) :
495          AGX_RT_STRIDE_TILED;
496    }
497 
498    /* Initialize base object */
499    so->base = *state;
500    so->base.texture = NULL;
501    pipe_resource_reference(&so->base.texture, texture);
502    pipe_reference_init(&so->base.reference, 1);
503    so->base.context = pctx;
504    return &so->base;
505 }
506 
507 static void
agx_set_sampler_views(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start,unsigned count,unsigned unbind_num_trailing_slots,bool take_ownership,struct pipe_sampler_view ** views)508 agx_set_sampler_views(struct pipe_context *pctx,
509                       enum pipe_shader_type shader,
510                       unsigned start, unsigned count,
511                       unsigned unbind_num_trailing_slots,
512                       bool take_ownership,
513                       struct pipe_sampler_view **views)
514 {
515    struct agx_context *ctx = agx_context(pctx);
516    unsigned new_nr = 0;
517    unsigned i;
518 
519    assert(start == 0);
520 
521    if (!views)
522       count = 0;
523 
524    for (i = 0; i < count; ++i) {
525       if (views[i])
526          new_nr = i + 1;
527 
528       if (take_ownership) {
529          pipe_sampler_view_reference((struct pipe_sampler_view **)
530                                      &ctx->stage[shader].textures[i], NULL);
531          ctx->stage[shader].textures[i] = (struct agx_sampler_view *)views[i];
532       } else {
533          pipe_sampler_view_reference((struct pipe_sampler_view **)
534                                      &ctx->stage[shader].textures[i], views[i]);
535       }
536    }
537 
538    for (; i < ctx->stage[shader].texture_count; i++) {
539       pipe_sampler_view_reference((struct pipe_sampler_view **)
540                                   &ctx->stage[shader].textures[i], NULL);
541    }
542    ctx->stage[shader].texture_count = new_nr;
543 }
544 
545 static void
agx_sampler_view_destroy(struct pipe_context * ctx,struct pipe_sampler_view * pview)546 agx_sampler_view_destroy(struct pipe_context *ctx,
547                          struct pipe_sampler_view *pview)
548 {
549    struct agx_sampler_view *view = (struct agx_sampler_view *) pview;
550    pipe_resource_reference(&view->base.texture, NULL);
551    agx_bo_unreference(view->desc);
552    FREE(view);
553 }
554 
555 static struct pipe_surface *
agx_create_surface(struct pipe_context * ctx,struct pipe_resource * texture,const struct pipe_surface * surf_tmpl)556 agx_create_surface(struct pipe_context *ctx,
557                    struct pipe_resource *texture,
558                    const struct pipe_surface *surf_tmpl)
559 {
560    struct pipe_surface *surface = CALLOC_STRUCT(pipe_surface);
561 
562    if (!surface)
563       return NULL;
564    pipe_reference_init(&surface->reference, 1);
565    pipe_resource_reference(&surface->texture, texture);
566    surface->context = ctx;
567    surface->format = surf_tmpl->format;
568    surface->width = texture->width0;
569    surface->height = texture->height0;
570    surface->texture = texture;
571    surface->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
572    surface->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
573    surface->u.tex.level = surf_tmpl->u.tex.level;
574 
575    return surface;
576 }
577 
578 static void
agx_set_clip_state(struct pipe_context * ctx,const struct pipe_clip_state * state)579 agx_set_clip_state(struct pipe_context *ctx,
580                    const struct pipe_clip_state *state)
581 {
582 }
583 
584 static void
agx_set_polygon_stipple(struct pipe_context * ctx,const struct pipe_poly_stipple * state)585 agx_set_polygon_stipple(struct pipe_context *ctx,
586                         const struct pipe_poly_stipple *state)
587 {
588 }
589 
590 static void
agx_set_sample_mask(struct pipe_context * pipe,unsigned sample_mask)591 agx_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
592 {
593    struct agx_context *ctx = agx_context(pipe);
594    ctx->sample_mask = sample_mask;
595 }
596 
597 static void
agx_set_scissor_states(struct pipe_context * pctx,unsigned start_slot,unsigned num_scissors,const struct pipe_scissor_state * scissor)598 agx_set_scissor_states(struct pipe_context *pctx,
599                        unsigned start_slot,
600                        unsigned num_scissors,
601                        const struct pipe_scissor_state *scissor)
602 {
603    struct agx_context *ctx = agx_context(pctx);
604 
605    assert(start_slot == 0 && "no geometry shaders");
606    assert(num_scissors == 1 && "no geometry shaders");
607 
608    ctx->scissor = *scissor;
609    ctx->dirty |= AGX_DIRTY_SCISSOR;
610 }
611 
612 static void
agx_set_stencil_ref(struct pipe_context * pctx,const struct pipe_stencil_ref state)613 agx_set_stencil_ref(struct pipe_context *pctx,
614                     const struct pipe_stencil_ref state)
615 {
616    struct agx_context *ctx = agx_context(pctx);
617    ctx->stencil_ref = state;
618 }
619 
620 static void
agx_set_viewport_states(struct pipe_context * pctx,unsigned start_slot,unsigned num_viewports,const struct pipe_viewport_state * vp)621 agx_set_viewport_states(struct pipe_context *pctx,
622                         unsigned start_slot,
623                         unsigned num_viewports,
624                         const struct pipe_viewport_state *vp)
625 {
626    struct agx_context *ctx = agx_context(pctx);
627 
628    assert(start_slot == 0 && "no geometry shaders");
629    assert(num_viewports == 1 && "no geometry shaders");
630 
631    ctx->dirty |= AGX_DIRTY_VIEWPORT;
632    ctx->viewport = *vp;
633 }
634 
635 struct agx_viewport_scissor {
636    uint64_t viewport;
637    unsigned scissor;
638 };
639 
640 static struct agx_viewport_scissor
agx_upload_viewport_scissor(struct agx_pool * pool,struct agx_batch * batch,const struct pipe_viewport_state * vp,const struct pipe_scissor_state * ss)641 agx_upload_viewport_scissor(struct agx_pool *pool,
642                             struct agx_batch *batch,
643                             const struct pipe_viewport_state *vp,
644                             const struct pipe_scissor_state *ss)
645 {
646    struct agx_ptr T = agx_pool_alloc_aligned(pool, AGX_VIEWPORT_LENGTH, 64);
647 
648    float trans_x = vp->translate[0], trans_y = vp->translate[1];
649    float abs_scale_x = fabsf(vp->scale[0]), abs_scale_y = fabsf(vp->scale[1]);
650 
651    /* Calculate the extent of the viewport. Note if a particular dimension of
652     * the viewport is an odd number of pixels, both the translate and the scale
653     * will have a fractional part of 0.5, so adding and subtracting them yields
654     * an integer. Therefore we don't need to round explicitly */
655    unsigned minx = CLAMP((int) (trans_x - abs_scale_x), 0, batch->width);
656    unsigned miny = CLAMP((int) (trans_y - abs_scale_y), 0, batch->height);
657    unsigned maxx = CLAMP((int) (trans_x + abs_scale_x), 0, batch->width);
658    unsigned maxy = CLAMP((int) (trans_y + abs_scale_y), 0, batch->height);
659 
660    if (ss) {
661       minx = MAX2(ss->minx, minx);
662       miny = MAX2(ss->miny, miny);
663       maxx = MIN2(ss->maxx, maxx);
664       maxy = MIN2(ss->maxy, maxy);
665    }
666 
667    assert(maxx > minx && maxy > miny);
668 
669    float minz, maxz;
670    util_viewport_zmin_zmax(vp, false, &minz, &maxz);
671 
672    agx_pack(T.cpu, VIEWPORT, cfg) {
673       cfg.min_tile_x = minx / 32;
674       cfg.min_tile_y = miny / 32;
675       cfg.max_tile_x = DIV_ROUND_UP(maxx, 32);
676       cfg.max_tile_y = DIV_ROUND_UP(maxy, 32);
677       cfg.clip_tile = true;
678 
679       cfg.translate_x = vp->translate[0];
680       cfg.translate_y = vp->translate[1];
681       cfg.scale_x = vp->scale[0];
682       cfg.scale_y = vp->scale[1];
683 
684       /* Assumes [0, 1] clip coordinates. If half-z is not in use, lower_half_z
685        * is called to ensure this works. */
686       cfg.translate_z = minz;
687       cfg.scale_z = maxz - minz;
688    };
689 
690    /* Allocate a new scissor descriptor */
691    struct agx_scissor_packed *ptr = batch->scissor.bo->ptr.cpu;
692    unsigned index = (batch->scissor.count++);
693 
694    agx_pack(ptr + index, SCISSOR, cfg) {
695       cfg.min_x = minx;
696       cfg.min_y = miny;
697       cfg.min_z = minz;
698       cfg.max_x = maxx;
699       cfg.max_y = maxy;
700       cfg.max_z = maxz;
701    }
702 
703    return (struct agx_viewport_scissor) {
704       .viewport = T.gpu,
705       .scissor = index
706    };
707 }
708 
709 /* A framebuffer state can be reused across batches, so it doesn't make sense
710  * to add surfaces to the BO list here. Instead we added them when flushing.
711  */
712 
713 static void
agx_set_framebuffer_state(struct pipe_context * pctx,const struct pipe_framebuffer_state * state)714 agx_set_framebuffer_state(struct pipe_context *pctx,
715                           const struct pipe_framebuffer_state *state)
716 {
717    struct agx_context *ctx = agx_context(pctx);
718 
719    if (!state)
720       return;
721 
722    /* XXX: eliminate this flush with batch tracking logic */
723    pctx->flush(pctx, NULL, 0);
724 
725    util_copy_framebuffer_state(&ctx->framebuffer, state);
726    ctx->batch->width = state->width;
727    ctx->batch->height = state->height;
728    ctx->batch->nr_cbufs = state->nr_cbufs;
729    ctx->batch->cbufs[0] = state->cbufs[0];
730    ctx->batch->zsbuf = state->zsbuf;
731    ctx->dirty = ~0;
732 
733    for (unsigned i = 0; i < state->nr_cbufs; ++i) {
734       struct pipe_surface *surf = state->cbufs[i];
735       struct agx_resource *tex = agx_resource(surf->texture);
736       const struct util_format_description *desc =
737          util_format_description(surf->format);
738       unsigned level = surf->u.tex.level;
739       unsigned layer = surf->u.tex.first_layer;
740 
741       assert(surf->u.tex.last_layer == layer);
742 
743       agx_pack(ctx->render_target[i], RENDER_TARGET, cfg) {
744          cfg.layout = agx_translate_layout(tex->modifier);
745          cfg.format = agx_pixel_format[surf->format].hw;
746          cfg.swizzle_r = agx_channel_from_pipe(desc->swizzle[0]);
747          cfg.swizzle_g = agx_channel_from_pipe(desc->swizzle[1]);
748          cfg.swizzle_b = agx_channel_from_pipe(desc->swizzle[2]);
749          cfg.swizzle_a = agx_channel_from_pipe(desc->swizzle[3]);
750          cfg.width = state->width;
751          cfg.height = state->height;
752          cfg.level = surf->u.tex.level;
753          cfg.buffer = agx_map_texture_gpu(tex, 0, layer);
754 
755          if (tex->mipmapped)
756             cfg.unk_55 = 0x8;
757 
758          cfg.stride = (tex->modifier == DRM_FORMAT_MOD_LINEAR) ?
759             (tex->slices[level].line_stride - 4) :
760             tex->mipmapped ? AGX_RT_STRIDE_TILED_MIPMAPPED :
761             AGX_RT_STRIDE_TILED;
762       };
763    }
764 }
765 
766 /* Likewise constant buffers, textures, and samplers are handled in a common
767  * per-draw path, with dirty tracking to reduce the costs involved.
768  */
769 
770 static void
agx_set_constant_buffer(struct pipe_context * pctx,enum pipe_shader_type shader,uint index,bool take_ownership,const struct pipe_constant_buffer * cb)771 agx_set_constant_buffer(struct pipe_context *pctx,
772                         enum pipe_shader_type shader, uint index,
773                         bool take_ownership,
774                         const struct pipe_constant_buffer *cb)
775 {
776    struct agx_context *ctx = agx_context(pctx);
777    struct agx_stage *s = &ctx->stage[shader];
778 
779    util_copy_constant_buffer(&s->cb[index], cb, take_ownership);
780 
781    unsigned mask = (1 << index);
782 
783    if (cb)
784       s->cb_mask |= mask;
785    else
786       s->cb_mask &= ~mask;
787 }
788 
789 static void
agx_surface_destroy(struct pipe_context * ctx,struct pipe_surface * surface)790 agx_surface_destroy(struct pipe_context *ctx,
791                     struct pipe_surface *surface)
792 {
793    pipe_resource_reference(&surface->texture, NULL);
794    FREE(surface);
795 }
796 
797 static void
agx_delete_state(struct pipe_context * ctx,void * state)798 agx_delete_state(struct pipe_context *ctx, void *state)
799 {
800    FREE(state);
801 }
802 
803 /* BOs added to the batch in the uniform upload path */
804 
805 static void
agx_set_vertex_buffers(struct pipe_context * pctx,unsigned start_slot,unsigned count,unsigned unbind_num_trailing_slots,bool take_ownership,const struct pipe_vertex_buffer * buffers)806 agx_set_vertex_buffers(struct pipe_context *pctx,
807                        unsigned start_slot, unsigned count,
808                        unsigned unbind_num_trailing_slots,
809                        bool take_ownership,
810                        const struct pipe_vertex_buffer *buffers)
811 {
812    struct agx_context *ctx = agx_context(pctx);
813 
814    util_set_vertex_buffers_mask(ctx->vertex_buffers, &ctx->vb_mask, buffers,
815                                 start_slot, count, unbind_num_trailing_slots, take_ownership);
816 
817    ctx->dirty |= AGX_DIRTY_VERTEX;
818 }
819 
820 static void *
agx_create_vertex_elements(struct pipe_context * ctx,unsigned count,const struct pipe_vertex_element * state)821 agx_create_vertex_elements(struct pipe_context *ctx,
822                            unsigned count,
823                            const struct pipe_vertex_element *state)
824 {
825    assert(count < AGX_MAX_ATTRIBS);
826 
827    struct agx_attribute *attribs = calloc(sizeof(*attribs), AGX_MAX_ATTRIBS);
828    for (unsigned i = 0; i < count; ++i) {
829       const struct pipe_vertex_element ve = state[i];
830 
831       const struct util_format_description *desc =
832          util_format_description(ve.src_format);
833 
834       unsigned chan_size = desc->channel[0].size / 8;
835 
836       assert(chan_size == 1 || chan_size == 2 || chan_size == 4);
837       assert(desc->nr_channels >= 1 && desc->nr_channels <= 4);
838       assert((ve.src_offset & (chan_size - 1)) == 0);
839 
840       attribs[i] = (struct agx_attribute) {
841          .buf = ve.vertex_buffer_index,
842          .src_offset = ve.src_offset / chan_size,
843          .nr_comps_minus_1 = desc->nr_channels - 1,
844          .format = agx_vertex_format[ve.src_format],
845          .divisor = ve.instance_divisor
846       };
847    }
848 
849    return attribs;
850 }
851 
852 static void
agx_bind_vertex_elements_state(struct pipe_context * pctx,void * cso)853 agx_bind_vertex_elements_state(struct pipe_context *pctx, void *cso)
854 {
855    struct agx_context *ctx = agx_context(pctx);
856    ctx->attributes = cso;
857    ctx->dirty |= AGX_DIRTY_VERTEX;
858 }
859 
asahi_shader_key_hash(const void * key)860 static uint32_t asahi_shader_key_hash(const void *key)
861 {
862    return _mesa_hash_data(key, sizeof(struct asahi_shader_key));
863 }
864 
asahi_shader_key_equal(const void * a,const void * b)865 static bool asahi_shader_key_equal(const void *a, const void *b)
866 {
867    return memcmp(a, b, sizeof(struct asahi_shader_key)) == 0;
868 }
869 
870 static void *
agx_create_shader_state(struct pipe_context * pctx,const struct pipe_shader_state * cso)871 agx_create_shader_state(struct pipe_context *pctx,
872                         const struct pipe_shader_state *cso)
873 {
874    struct agx_uncompiled_shader *so = CALLOC_STRUCT(agx_uncompiled_shader);
875 
876    if (!so)
877       return NULL;
878 
879    so->base = *cso;
880 
881    if (cso->type == PIPE_SHADER_IR_NIR) {
882       so->nir = cso->ir.nir;
883    } else {
884       assert(cso->type == PIPE_SHADER_IR_TGSI);
885       so->nir = tgsi_to_nir(cso->tokens, pctx->screen, false);
886    }
887 
888    so->variants = _mesa_hash_table_create(NULL, asahi_shader_key_hash, asahi_shader_key_equal);
889    return so;
890 }
891 
892 /* Does not take ownership of key. Clones if necessary. */
893 static bool
agx_update_shader(struct agx_context * ctx,struct agx_compiled_shader ** out,enum pipe_shader_type stage,struct asahi_shader_key * key)894 agx_update_shader(struct agx_context *ctx, struct agx_compiled_shader **out,
895                   enum pipe_shader_type stage, struct asahi_shader_key *key)
896 {
897    struct agx_uncompiled_shader *so = ctx->stage[stage].shader;
898    assert(so != NULL);
899 
900    struct hash_entry *he = _mesa_hash_table_search(so->variants, key);
901 
902    if (he) {
903       if ((*out) == he->data)
904          return false;
905 
906       *out = he->data;
907       return true;
908    }
909 
910    struct agx_compiled_shader *compiled = CALLOC_STRUCT(agx_compiled_shader);
911    struct util_dynarray binary;
912    util_dynarray_init(&binary, NULL);
913 
914    nir_shader *nir = nir_shader_clone(NULL, so->nir);
915 
916    if (key->blend.blend_enable) {
917       nir_lower_blend_options opts = {
918          .format = { key->rt_formats[0] },
919          .scalar_blend_const = true
920       };
921 
922       memcpy(opts.rt, key->blend.rt, sizeof(opts.rt));
923       NIR_PASS_V(nir, nir_lower_blend, opts);
924    } else if (key->blend.logicop_enable) {
925       nir_lower_blend_options opts = {
926          .format = { key->rt_formats[0] },
927          .logicop_enable = true,
928          .logicop_func = key->blend.logicop_func,
929       };
930 
931       NIR_PASS_V(nir, nir_lower_blend, opts);
932    }
933 
934    if (stage == PIPE_SHADER_FRAGMENT)
935       NIR_PASS_V(nir, nir_lower_fragcolor, key->nr_cbufs);
936 
937    agx_compile_shader_nir(nir, &key->base, &binary, &compiled->info);
938 
939    struct agx_varyings *varyings = &compiled->info.varyings;
940    unsigned packed_varying_sz = (AGX_VARYING_HEADER_LENGTH + varyings->nr_descs * AGX_VARYING_LENGTH);
941    uint8_t *packed_varyings = alloca(packed_varying_sz);
942 
943    agx_pack(packed_varyings, VARYING_HEADER, cfg) {
944       cfg.triangle_slots = cfg.point_slots = varyings->nr_slots;
945    }
946 
947    memcpy(packed_varyings + AGX_VARYING_HEADER_LENGTH, varyings->packed,
948          varyings->nr_descs * AGX_VARYING_LENGTH);
949 
950    if (binary.size) {
951       struct agx_device *dev = agx_device(ctx->base.screen);
952       compiled->bo = agx_bo_create(dev,
953                                    ALIGN_POT(binary.size, 256) + (3 * packed_varying_sz),
954                                    AGX_MEMORY_TYPE_SHADER);
955       memcpy(compiled->bo->ptr.cpu, binary.data, binary.size);
956 
957 
958       /* TODO: Why is the varying descriptor duplicated 3x? */
959       unsigned offs = ALIGN_POT(binary.size, 256);
960       for (unsigned copy = 0; copy < 3; ++copy) {
961          memcpy(((uint8_t *) compiled->bo->ptr.cpu) + offs, packed_varyings, packed_varying_sz);
962          offs += packed_varying_sz;
963       }
964 
965       compiled->varyings = compiled->bo->ptr.gpu + ALIGN_POT(binary.size, 256);
966    }
967 
968    ralloc_free(nir);
969    util_dynarray_fini(&binary);
970 
971    /* key may be destroyed after we return, so clone it before using it as a
972     * hash table key. The clone is logically owned by the hash table.
973     */
974    struct asahi_shader_key *cloned_key = ralloc(so->variants, struct asahi_shader_key);
975    memcpy(cloned_key, key, sizeof(struct asahi_shader_key));
976 
977    he = _mesa_hash_table_insert(so->variants, cloned_key, compiled);
978    *out = he->data;
979    return true;
980 }
981 
982 static bool
agx_update_vs(struct agx_context * ctx)983 agx_update_vs(struct agx_context *ctx)
984 {
985    struct agx_vs_shader_key key = {
986       .num_vbufs = util_last_bit(ctx->vb_mask),
987       .clip_halfz = ctx->rast->base.clip_halfz,
988    };
989 
990    memcpy(key.attributes, ctx->attributes,
991           sizeof(key.attributes[0]) * AGX_MAX_ATTRIBS);
992 
993    u_foreach_bit(i, ctx->vb_mask) {
994       key.vbuf_strides[i] = ctx->vertex_buffers[i].stride;
995    }
996 
997    struct asahi_shader_key akey = {
998       .base.vs = key
999    };
1000 
1001    return agx_update_shader(ctx, &ctx->vs, PIPE_SHADER_VERTEX, &akey);
1002 }
1003 
1004 static bool
agx_update_fs(struct agx_context * ctx)1005 agx_update_fs(struct agx_context *ctx)
1006 {
1007    struct asahi_shader_key key = {
1008       .nr_cbufs = ctx->batch->nr_cbufs,
1009    };
1010 
1011    for (unsigned i = 0; i < key.nr_cbufs; ++i) {
1012       struct pipe_surface *surf = ctx->batch->cbufs[i];
1013 
1014       if (surf) {
1015          enum pipe_format fmt = surf->format;
1016          key.rt_formats[i] = fmt;
1017          key.base.fs.tib_formats[i] = agx_pixel_format[fmt].internal;
1018       } else {
1019          key.rt_formats[i] = PIPE_FORMAT_NONE;
1020       }
1021    }
1022 
1023    memcpy(&key.blend, ctx->blend, sizeof(key.blend));
1024 
1025    return agx_update_shader(ctx, &ctx->fs, PIPE_SHADER_FRAGMENT, &key);
1026 }
1027 
1028 static void
agx_bind_shader_state(struct pipe_context * pctx,void * cso)1029 agx_bind_shader_state(struct pipe_context *pctx, void *cso)
1030 {
1031    if (!cso)
1032       return;
1033 
1034    struct agx_context *ctx = agx_context(pctx);
1035    struct agx_uncompiled_shader *so = cso;
1036 
1037    enum pipe_shader_type type = pipe_shader_type_from_mesa(so->nir->info.stage);
1038    ctx->stage[type].shader = so;
1039 }
1040 
1041 static void
agx_delete_compiled_shader(struct hash_entry * ent)1042 agx_delete_compiled_shader(struct hash_entry *ent)
1043 {
1044    struct agx_compiled_shader *so = ent->data;
1045    agx_bo_unreference(so->bo);
1046    FREE(so);
1047 }
1048 
1049 static void
agx_delete_shader_state(struct pipe_context * ctx,void * cso)1050 agx_delete_shader_state(struct pipe_context *ctx,
1051                         void *cso)
1052 {
1053    struct agx_uncompiled_shader *so = cso;
1054    _mesa_hash_table_destroy(so->variants, agx_delete_compiled_shader);
1055    free(so);
1056 }
1057 
1058 /* Pipeline consists of a sequence of binding commands followed by a set shader command */
1059 static uint32_t
agx_build_pipeline(struct agx_context * ctx,struct agx_compiled_shader * cs,enum pipe_shader_type stage)1060 agx_build_pipeline(struct agx_context *ctx, struct agx_compiled_shader *cs, enum pipe_shader_type stage)
1061 {
1062    /* Pipelines must be 64-byte aligned */
1063    struct agx_ptr ptr = agx_pool_alloc_aligned(&ctx->batch->pipeline_pool,
1064                         (16 * AGX_BIND_UNIFORM_LENGTH) + // XXX: correct sizes, break up at compile time
1065                         (ctx->stage[stage].texture_count * AGX_BIND_TEXTURE_LENGTH) +
1066                         (PIPE_MAX_SAMPLERS * AGX_BIND_SAMPLER_LENGTH) +
1067                         AGX_SET_SHADER_EXTENDED_LENGTH + 8,
1068                         64);
1069 
1070    uint8_t *record = ptr.cpu;
1071 
1072    /* There is a maximum number of half words we may push with a single
1073     * BIND_UNIFORM record, so split up the range to fit. We only need to call
1074     * agx_push_location once, however, which reduces the cost. */
1075    unsigned unif_records = 0;
1076 
1077    for (unsigned i = 0; i < cs->info.push_ranges; ++i) {
1078       struct agx_push push = cs->info.push[i];
1079       uint64_t buffer = agx_push_location(ctx, push, stage);
1080       unsigned halfs_per_record = 14;
1081       unsigned records = DIV_ROUND_UP(push.length, halfs_per_record);
1082 
1083       /* Ensure we don't overflow */
1084       unif_records += records;
1085       assert(unif_records < 16);
1086 
1087       for (unsigned j = 0; j < records; ++j) {
1088          agx_pack(record, BIND_UNIFORM, cfg) {
1089             cfg.start_halfs = push.base + (j * halfs_per_record);
1090             cfg.size_halfs = MIN2(push.length - (j * halfs_per_record), halfs_per_record);
1091             cfg.buffer = buffer + (j * halfs_per_record * 2);
1092          }
1093 
1094          record += AGX_BIND_UNIFORM_LENGTH;
1095       }
1096    }
1097 
1098    for (unsigned i = 0; i < ctx->stage[stage].texture_count; ++i) {
1099       struct agx_sampler_view *tex = ctx->stage[stage].textures[i];
1100       agx_batch_add_bo(ctx->batch, tex->desc);
1101       agx_batch_add_bo(ctx->batch, agx_resource(tex->base.texture)->bo);
1102 
1103 
1104       agx_pack(record, BIND_TEXTURE, cfg) {
1105          cfg.start = i;
1106          cfg.count = 1;
1107          cfg.buffer = tex->desc->ptr.gpu;
1108       }
1109 
1110       record += AGX_BIND_TEXTURE_LENGTH;
1111    }
1112 
1113    for (unsigned i = 0; i < PIPE_MAX_SAMPLERS; ++i) {
1114       struct agx_sampler_state *sampler = ctx->stage[stage].samplers[i];
1115 
1116       if (!sampler)
1117          continue;
1118 
1119       struct agx_bo *bo = sampler->desc;
1120       agx_batch_add_bo(ctx->batch, bo);
1121 
1122       agx_pack(record, BIND_SAMPLER, cfg) {
1123          cfg.start = i;
1124          cfg.count = 1;
1125          cfg.buffer = bo->ptr.gpu;
1126       }
1127 
1128       record += AGX_BIND_SAMPLER_LENGTH;
1129    }
1130 
1131    /* TODO: Can we prepack this? */
1132    if (stage == PIPE_SHADER_FRAGMENT) {
1133       bool writes_sample_mask = ctx->fs->info.writes_sample_mask;
1134 
1135       agx_pack(record, SET_SHADER_EXTENDED, cfg) {
1136          cfg.code = cs->bo->ptr.gpu;
1137          cfg.register_quadwords = 0;
1138          cfg.unk_3 = 0x8d;
1139          cfg.unk_1 = 0x2010bd;
1140          cfg.unk_2 = 0x0d;
1141          cfg.unk_2b = writes_sample_mask ? 5 : 1;
1142          cfg.fragment_parameters.early_z_testing = !writes_sample_mask;
1143          cfg.unk_3b = 0x1;
1144          cfg.unk_4 = 0x800;
1145          cfg.preshader_unk = 0xc080;
1146          cfg.spill_size = 0x2;
1147       }
1148 
1149       record += AGX_SET_SHADER_EXTENDED_LENGTH;
1150    } else {
1151       agx_pack(record, SET_SHADER, cfg) {
1152          cfg.code = cs->bo->ptr.gpu;
1153          cfg.register_quadwords = 0;
1154          cfg.unk_2b = cs->info.varyings.nr_slots;
1155          cfg.unk_2 = 0x0d;
1156       }
1157 
1158       record += AGX_SET_SHADER_LENGTH;
1159    }
1160 
1161    /* End pipeline */
1162    memset(record, 0, 8);
1163    assert(ptr.gpu < (1ull << 32));
1164    return ptr.gpu;
1165 }
1166 
1167 /* Internal pipelines (TODO: refactor?) */
1168 uint64_t
agx_build_clear_pipeline(struct agx_context * ctx,uint32_t code,uint64_t clear_buf)1169 agx_build_clear_pipeline(struct agx_context *ctx, uint32_t code, uint64_t clear_buf)
1170 {
1171    struct agx_ptr ptr = agx_pool_alloc_aligned(&ctx->batch->pipeline_pool,
1172                         (1 * AGX_BIND_UNIFORM_LENGTH) +
1173                         AGX_SET_SHADER_EXTENDED_LENGTH + 8,
1174                         64);
1175 
1176    uint8_t *record = ptr.cpu;
1177 
1178    agx_pack(record, BIND_UNIFORM, cfg) {
1179       cfg.start_halfs = (6 * 2);
1180       cfg.size_halfs = 4;
1181       cfg.buffer = clear_buf;
1182    }
1183 
1184    record += AGX_BIND_UNIFORM_LENGTH;
1185 
1186    /* TODO: Can we prepack this? */
1187    agx_pack(record, SET_SHADER_EXTENDED, cfg) {
1188       cfg.code = code;
1189       cfg.register_quadwords = 1;
1190       cfg.unk_3 = 0x8d;
1191       cfg.unk_2 = 0x0d;
1192       cfg.unk_2b = 4;
1193       cfg.fragment_parameters.unk_1 = 0x880100;
1194       cfg.fragment_parameters.early_z_testing = false;
1195       cfg.fragment_parameters.unk_2 = false;
1196       cfg.fragment_parameters.unk_3 = 0;
1197       cfg.preshader_mode = 0; // XXX
1198    }
1199 
1200    record += AGX_SET_SHADER_EXTENDED_LENGTH;
1201 
1202    /* End pipeline */
1203    memset(record, 0, 8);
1204    return ptr.gpu;
1205 }
1206 
1207 uint64_t
agx_build_reload_pipeline(struct agx_context * ctx,uint32_t code,struct pipe_surface * surf)1208 agx_build_reload_pipeline(struct agx_context *ctx, uint32_t code, struct pipe_surface *surf)
1209 {
1210    struct agx_ptr ptr = agx_pool_alloc_aligned(&ctx->batch->pipeline_pool,
1211                         (1 * AGX_BIND_TEXTURE_LENGTH) +
1212                         (1 * AGX_BIND_SAMPLER_LENGTH) +
1213                         AGX_SET_SHADER_EXTENDED_LENGTH + 8,
1214                         64);
1215 
1216    uint8_t *record = ptr.cpu;
1217    struct agx_ptr sampler = agx_pool_alloc_aligned(&ctx->batch->pool, AGX_SAMPLER_LENGTH, 64);
1218    struct agx_ptr texture = agx_pool_alloc_aligned(&ctx->batch->pool, AGX_TEXTURE_LENGTH, 64);
1219 
1220    agx_pack(sampler.cpu, SAMPLER, cfg) {
1221       cfg.magnify_linear = true;
1222       cfg.minify_linear = false;
1223       cfg.mip_filter = AGX_MIP_FILTER_NONE;
1224       cfg.wrap_s = AGX_WRAP_CLAMP_TO_EDGE;
1225       cfg.wrap_t = AGX_WRAP_CLAMP_TO_EDGE;
1226       cfg.wrap_r = AGX_WRAP_CLAMP_TO_EDGE;
1227       cfg.pixel_coordinates = true;
1228       cfg.compare_func = AGX_COMPARE_FUNC_ALWAYS;
1229       cfg.unk_3 = 0;
1230    }
1231 
1232    agx_pack(texture.cpu, TEXTURE, cfg) {
1233       struct agx_resource *rsrc = agx_resource(surf->texture);
1234       unsigned level = surf->u.tex.level;
1235       unsigned layer = surf->u.tex.first_layer;
1236       const struct util_format_description *desc =
1237          util_format_description(surf->format);
1238 
1239       /* To reduce shader variants, we always use a non-mipmapped 2D texture.
1240        * For reloads of arrays, cube maps, etc -- we only logically reload a
1241        * single 2D image. This does mean we need to be careful about
1242        * width/height and address.
1243        */
1244       cfg.dimension = AGX_TEXTURE_DIMENSION_2D;
1245 
1246       cfg.layout = agx_translate_layout(rsrc->modifier);
1247       cfg.format = agx_pixel_format[surf->format].hw;
1248       cfg.swizzle_r = agx_channel_from_pipe(desc->swizzle[0]);
1249       cfg.swizzle_g = agx_channel_from_pipe(desc->swizzle[1]);
1250       cfg.swizzle_b = agx_channel_from_pipe(desc->swizzle[2]);
1251       cfg.swizzle_a = agx_channel_from_pipe(desc->swizzle[3]);
1252       cfg.width = u_minify(surf->width, level);
1253       cfg.height = u_minify(surf->height, level);
1254       cfg.levels = 1;
1255       cfg.srgb = (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB);
1256       cfg.address = agx_map_texture_gpu(rsrc, level, layer);
1257 
1258       cfg.stride = (rsrc->modifier == DRM_FORMAT_MOD_LINEAR) ?
1259          (rsrc->slices[level].line_stride - 16) :
1260          AGX_RT_STRIDE_TILED;
1261    }
1262 
1263    agx_pack(record, BIND_TEXTURE, cfg) {
1264       cfg.start = 0;
1265       cfg.count = 1;
1266       cfg.buffer = texture.gpu;
1267    }
1268 
1269    record += AGX_BIND_TEXTURE_LENGTH;
1270 
1271    agx_pack(record, BIND_SAMPLER, cfg) {
1272       cfg.start = 0;
1273       cfg.count = 1;
1274       cfg.buffer = sampler.gpu;
1275    }
1276 
1277    record += AGX_BIND_SAMPLER_LENGTH;
1278 
1279    /* TODO: Can we prepack this? */
1280    agx_pack(record, SET_SHADER_EXTENDED, cfg) {
1281       cfg.code = code;
1282       cfg.register_quadwords = 0;
1283       cfg.unk_3 = 0x8d;
1284       cfg.unk_2 = 0x0d;
1285       cfg.unk_2b = 4;
1286       cfg.unk_4 = 0;
1287       cfg.fragment_parameters.unk_1 = 0x880100;
1288       cfg.fragment_parameters.early_z_testing = false;
1289       cfg.fragment_parameters.unk_2 = false;
1290       cfg.fragment_parameters.unk_3 = 0;
1291       cfg.preshader_mode = 0; // XXX
1292    }
1293 
1294    record += AGX_SET_SHADER_EXTENDED_LENGTH;
1295 
1296    /* End pipeline */
1297    memset(record, 0, 8);
1298    return ptr.gpu;
1299 }
1300 
1301 uint64_t
agx_build_store_pipeline(struct agx_context * ctx,uint32_t code,uint64_t render_target)1302 agx_build_store_pipeline(struct agx_context *ctx, uint32_t code,
1303                          uint64_t render_target)
1304 {
1305    struct agx_ptr ptr = agx_pool_alloc_aligned(&ctx->batch->pipeline_pool,
1306                         (1 * AGX_BIND_TEXTURE_LENGTH) +
1307                         (1 * AGX_BIND_UNIFORM_LENGTH) +
1308                         AGX_SET_SHADER_EXTENDED_LENGTH + 8,
1309                         64);
1310 
1311    uint8_t *record = ptr.cpu;
1312 
1313    agx_pack(record, BIND_TEXTURE, cfg) {
1314       cfg.start = 0;
1315       cfg.count = 1;
1316       cfg.buffer = render_target;
1317    }
1318 
1319    record += AGX_BIND_TEXTURE_LENGTH;
1320 
1321    uint32_t unk[] = { 0, ~0 };
1322 
1323    agx_pack(record, BIND_UNIFORM, cfg) {
1324       cfg.start_halfs = 4;
1325       cfg.size_halfs = 4;
1326       cfg.buffer = agx_pool_upload_aligned(&ctx->batch->pool, unk, sizeof(unk), 16);
1327    }
1328 
1329    record += AGX_BIND_UNIFORM_LENGTH;
1330 
1331    /* TODO: Can we prepack this? */
1332    agx_pack(record, SET_SHADER_EXTENDED, cfg) {
1333       cfg.code = code;
1334       cfg.register_quadwords = 1;
1335       cfg.unk_2 = 0xd;
1336       cfg.unk_3 = 0x8d;
1337       cfg.fragment_parameters.unk_1 = 0x880100;
1338       cfg.fragment_parameters.early_z_testing = false;
1339       cfg.fragment_parameters.unk_2 = false;
1340       cfg.fragment_parameters.unk_3 = 0;
1341       cfg.preshader_mode = 0; // XXX
1342    }
1343 
1344    record += AGX_SET_SHADER_EXTENDED_LENGTH;
1345 
1346    /* End pipeline */
1347    memset(record, 0, 8);
1348    return ptr.gpu;
1349 }
1350 
1351 static uint64_t
demo_launch_fragment(struct agx_context * ctx,struct agx_pool * pool,uint32_t pipeline,uint32_t varyings,unsigned input_count)1352 demo_launch_fragment(struct agx_context *ctx, struct agx_pool *pool, uint32_t pipeline, uint32_t varyings, unsigned input_count)
1353 {
1354    struct agx_ptr t = agx_pool_alloc_aligned(pool, AGX_BIND_PIPELINE_LENGTH, 64);
1355 
1356    agx_pack(t.cpu, BIND_PIPELINE, cfg) {
1357       cfg.tag = AGX_BIND_PIPELINE_FRAGMENT;
1358       cfg.sampler_count = ctx->stage[PIPE_SHADER_FRAGMENT].texture_count;
1359       cfg.texture_count = ctx->stage[PIPE_SHADER_FRAGMENT].texture_count;
1360       cfg.input_count = input_count;
1361       cfg.pipeline = pipeline;
1362       cfg.fs_varyings = varyings;
1363    };
1364 
1365    return t.gpu;
1366 }
1367 
1368 static uint64_t
demo_interpolation(struct agx_compiled_shader * fs,struct agx_pool * pool)1369 demo_interpolation(struct agx_compiled_shader *fs, struct agx_pool *pool)
1370 {
1371    struct agx_ptr t = agx_pool_alloc_aligned(pool, AGX_INTERPOLATION_LENGTH, 64);
1372 
1373    agx_pack(t.cpu, INTERPOLATION, cfg) {
1374       cfg.varying_count = fs->info.varyings.nr_slots;
1375    };
1376 
1377    return t.gpu;
1378 }
1379 
1380 static uint64_t
demo_linkage(struct agx_compiled_shader * vs,struct agx_pool * pool)1381 demo_linkage(struct agx_compiled_shader *vs, struct agx_pool *pool)
1382 {
1383    struct agx_ptr t = agx_pool_alloc_aligned(pool, AGX_LINKAGE_LENGTH, 64);
1384 
1385    agx_pack(t.cpu, LINKAGE, cfg) {
1386       cfg.varying_count = vs->info.varyings.nr_slots;
1387 
1388       // 0x2 for fragcoordz, 0x1 for varyings at all
1389       cfg.unk_1 = 0x210000 | (vs->info.writes_psiz ? 0x40000 : 0);
1390    };
1391 
1392    return t.gpu;
1393 }
1394 
1395 static uint64_t
demo_rasterizer(struct agx_context * ctx,struct agx_pool * pool,bool is_points)1396 demo_rasterizer(struct agx_context *ctx, struct agx_pool *pool, bool is_points)
1397 {
1398    struct agx_rasterizer *rast = ctx->rast;
1399    struct agx_rasterizer_packed out;
1400 
1401    agx_pack(&out, RASTERIZER, cfg) {
1402       bool back_stencil = ctx->zs.base.stencil[1].enabled;
1403       cfg.front.stencil_reference = ctx->stencil_ref.ref_value[0];
1404       cfg.back.stencil_reference = back_stencil ?
1405          ctx->stencil_ref.ref_value[1] :
1406          cfg.front.stencil_reference;
1407 
1408       cfg.front.line_width = cfg.back.line_width = rast->line_width;
1409       cfg.front.polygon_mode = cfg.back.polygon_mode = AGX_POLYGON_MODE_FILL;
1410 
1411       cfg.unk_fill_lines = is_points; /* XXX: what is this? */
1412 
1413       /* Always enable scissoring so we may scissor to the viewport (TODO:
1414        * optimize this out if the viewport is the default and the app does not
1415        * use the scissor test) */
1416       cfg.scissor_enable = true;
1417    };
1418 
1419    /* Words 2-3: front */
1420    out.opaque[2] |= ctx->zs.front.opaque[0];
1421    out.opaque[3] |= ctx->zs.front.opaque[1];
1422 
1423    /* Words 4-5: back */
1424    out.opaque[4] |= ctx->zs.back.opaque[0];
1425    out.opaque[5] |= ctx->zs.back.opaque[1];
1426 
1427    return agx_pool_upload_aligned(pool, &out, sizeof(out), 64);
1428 }
1429 
1430 static uint64_t
demo_unk11(struct agx_pool * pool,bool prim_lines,bool prim_points,bool reads_tib,bool sample_mask_from_shader)1431 demo_unk11(struct agx_pool *pool, bool prim_lines, bool prim_points, bool reads_tib, bool sample_mask_from_shader)
1432 {
1433    struct agx_ptr T = agx_pool_alloc_aligned(pool, AGX_UNKNOWN_4A_LENGTH, 64);
1434 
1435    agx_pack(T.cpu, UNKNOWN_4A, cfg) {
1436       cfg.lines_or_points = (prim_lines || prim_points);
1437       cfg.reads_tilebuffer = reads_tib;
1438       cfg.sample_mask_from_shader = sample_mask_from_shader;
1439 
1440       cfg.front.lines = cfg.back.lines = prim_lines;
1441       cfg.front.points = cfg.back.points = prim_points;
1442    };
1443 
1444    return T.gpu;
1445 }
1446 
1447 static uint64_t
demo_unk12(struct agx_pool * pool)1448 demo_unk12(struct agx_pool *pool)
1449 {
1450    uint32_t unk[] = {
1451       0x410000,
1452       0x1e3ce508,
1453       0xa0
1454    };
1455 
1456    return agx_pool_upload(pool, unk, sizeof(unk));
1457 }
1458 
1459 static uint64_t
agx_set_scissor_index(struct agx_pool * pool,unsigned index)1460 agx_set_scissor_index(struct agx_pool *pool, unsigned index)
1461 {
1462    struct agx_ptr T = agx_pool_alloc_aligned(pool, AGX_SET_SCISSOR_LENGTH, 64);
1463 
1464    agx_pack(T.cpu, SET_SCISSOR, cfg) {
1465       cfg.index = index;
1466    };
1467 
1468    return T.gpu;
1469 }
1470 
1471 static void
agx_push_record(uint8_t ** out,unsigned size_words,uint64_t ptr)1472 agx_push_record(uint8_t **out, unsigned size_words, uint64_t ptr)
1473 {
1474    assert(ptr < (1ull << 40));
1475    assert(size_words < (1ull << 24));
1476 
1477    agx_pack(*out, RECORD, cfg) {
1478       cfg.pointer_hi = (ptr >> 32);
1479       cfg.pointer_lo = (uint32_t) ptr;
1480       cfg.size_words = size_words;
1481    };
1482 
1483    *out += AGX_RECORD_LENGTH;
1484 }
1485 
1486 static uint8_t *
agx_encode_state(struct agx_context * ctx,uint8_t * out,uint32_t pipeline_vertex,uint32_t pipeline_fragment,uint32_t varyings,bool is_lines,bool is_points)1487 agx_encode_state(struct agx_context *ctx, uint8_t *out,
1488                  uint32_t pipeline_vertex, uint32_t pipeline_fragment, uint32_t varyings,
1489                  bool is_lines, bool is_points)
1490 {
1491    agx_pack(out, BIND_PIPELINE, cfg) {
1492       cfg.tag = AGX_BIND_PIPELINE_VERTEX;
1493       cfg.pipeline = pipeline_vertex;
1494       cfg.vs_output_count_1 = ctx->vs->info.varyings.nr_slots;
1495       cfg.vs_output_count_2 = ctx->vs->info.varyings.nr_slots;
1496       cfg.sampler_count = ctx->stage[PIPE_SHADER_VERTEX].texture_count;
1497       cfg.texture_count = ctx->stage[PIPE_SHADER_VERTEX].texture_count;
1498    }
1499 
1500    out += AGX_BIND_PIPELINE_LENGTH;
1501 
1502    struct agx_pool *pool = &ctx->batch->pool;
1503    bool reads_tib = ctx->fs->info.reads_tib;
1504    bool sample_mask_from_shader = ctx->fs->info.writes_sample_mask;
1505 
1506    agx_push_record(&out, 5, demo_interpolation(ctx->fs, pool));
1507    agx_push_record(&out, 5, demo_launch_fragment(ctx, pool, pipeline_fragment, varyings, ctx->fs->info.varyings.nr_descs));
1508    agx_push_record(&out, 4, demo_linkage(ctx->vs, pool));
1509    agx_push_record(&out, 7, demo_rasterizer(ctx, pool, is_points));
1510    agx_push_record(&out, 5, demo_unk11(pool, is_lines, is_points, reads_tib, sample_mask_from_shader));
1511 
1512    if (ctx->dirty & (AGX_DIRTY_VIEWPORT | AGX_DIRTY_SCISSOR)) {
1513       struct agx_viewport_scissor vps = agx_upload_viewport_scissor(pool,
1514             ctx->batch, &ctx->viewport,
1515             ctx->rast->base.scissor ? &ctx->scissor : NULL);
1516 
1517       agx_push_record(&out, 10, vps.viewport);
1518       agx_push_record(&out, 2, agx_set_scissor_index(pool, vps.scissor));
1519    }
1520 
1521    agx_push_record(&out, 3, demo_unk12(pool));
1522    agx_push_record(&out, 2, agx_pool_upload(pool, ctx->rast->cull, sizeof(ctx->rast->cull)));
1523 
1524    return out;
1525 }
1526 
1527 static enum agx_primitive
agx_primitive_for_pipe(enum pipe_prim_type mode)1528 agx_primitive_for_pipe(enum pipe_prim_type mode)
1529 {
1530    switch (mode) {
1531    case PIPE_PRIM_POINTS: return AGX_PRIMITIVE_POINTS;
1532    case PIPE_PRIM_LINES: return AGX_PRIMITIVE_LINES;
1533    case PIPE_PRIM_LINE_STRIP: return AGX_PRIMITIVE_LINE_STRIP;
1534    case PIPE_PRIM_LINE_LOOP: return AGX_PRIMITIVE_LINE_LOOP;
1535    case PIPE_PRIM_TRIANGLES: return AGX_PRIMITIVE_TRIANGLES;
1536    case PIPE_PRIM_TRIANGLE_STRIP: return AGX_PRIMITIVE_TRIANGLE_STRIP;
1537    case PIPE_PRIM_TRIANGLE_FAN: return AGX_PRIMITIVE_TRIANGLE_FAN;
1538    case PIPE_PRIM_QUADS: return AGX_PRIMITIVE_QUADS;
1539    case PIPE_PRIM_QUAD_STRIP: return AGX_PRIMITIVE_QUAD_STRIP;
1540    default: unreachable("todo: other primitive types");
1541    }
1542 }
1543 
1544 static uint64_t
agx_index_buffer_ptr(struct agx_batch * batch,const struct pipe_draw_start_count_bias * draw,const struct pipe_draw_info * info)1545 agx_index_buffer_ptr(struct agx_batch *batch,
1546                      const struct pipe_draw_start_count_bias *draw,
1547                      const struct pipe_draw_info *info)
1548 {
1549    off_t offset = draw->start * info->index_size;
1550 
1551    if (!info->has_user_indices) {
1552       struct agx_bo *bo = agx_resource(info->index.resource)->bo;
1553       agx_batch_add_bo(batch, bo);
1554 
1555       return bo->ptr.gpu + offset;
1556    } else {
1557       return agx_pool_upload_aligned(&batch->pool,
1558                                      ((uint8_t *) info->index.user) + offset,
1559                                      draw->count * info->index_size, 64);
1560    }
1561 }
1562 
1563 static bool
agx_scissor_culls_everything(struct agx_context * ctx)1564 agx_scissor_culls_everything(struct agx_context *ctx)
1565 {
1566         const struct pipe_scissor_state ss = ctx->scissor;
1567 
1568         return ctx->rast->base.scissor &&
1569 		((ss.minx == ss.maxx) || (ss.miny == ss.maxy));
1570 }
1571 
1572 static void
agx_draw_vbo(struct pipe_context * pctx,const struct pipe_draw_info * info,unsigned drawid_offset,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * draws,unsigned num_draws)1573 agx_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
1574              unsigned drawid_offset,
1575              const struct pipe_draw_indirect_info *indirect,
1576              const struct pipe_draw_start_count_bias *draws,
1577              unsigned num_draws)
1578 {
1579    if (num_draws > 1) {
1580       util_draw_multi(pctx, info, drawid_offset, indirect, draws, num_draws);
1581       return;
1582    }
1583 
1584    if (info->index_size && draws->index_bias)
1585       unreachable("todo: index bias");
1586 
1587    struct agx_context *ctx = agx_context(pctx);
1588    struct agx_batch *batch = ctx->batch;
1589 
1590    if (agx_scissor_culls_everything(ctx))
1591 	   return;
1592 
1593    /* TODO: masks */
1594    ctx->batch->draw |= ~0;
1595 
1596    /* TODO: Dirty track */
1597    agx_update_vs(ctx);
1598    agx_update_fs(ctx);
1599 
1600    agx_batch_add_bo(batch, ctx->vs->bo);
1601    agx_batch_add_bo(batch, ctx->fs->bo);
1602 
1603    bool is_lines =
1604       (info->mode == PIPE_PRIM_LINES) ||
1605       (info->mode == PIPE_PRIM_LINE_STRIP) ||
1606       (info->mode == PIPE_PRIM_LINE_LOOP);
1607 
1608    uint8_t *out = agx_encode_state(ctx, batch->encoder_current,
1609                                    agx_build_pipeline(ctx, ctx->vs, PIPE_SHADER_VERTEX),
1610                                    agx_build_pipeline(ctx, ctx->fs, PIPE_SHADER_FRAGMENT),
1611                                    ctx->fs->varyings, is_lines, info->mode == PIPE_PRIM_POINTS);
1612 
1613    enum agx_primitive prim = agx_primitive_for_pipe(info->mode);
1614    unsigned idx_size = info->index_size;
1615 
1616    if (idx_size) {
1617       uint64_t ib = agx_index_buffer_ptr(batch, draws, info);
1618 
1619       /* Index sizes are encoded logarithmically */
1620       STATIC_ASSERT(__builtin_ctz(1) == AGX_INDEX_SIZE_U8);
1621       STATIC_ASSERT(__builtin_ctz(2) == AGX_INDEX_SIZE_U16);
1622       STATIC_ASSERT(__builtin_ctz(4) == AGX_INDEX_SIZE_U32);
1623       assert((idx_size == 1) || (idx_size == 2) || (idx_size == 4));
1624 
1625       agx_pack(out, INDEXED_DRAW, cfg) {
1626          cfg.restart_index = info->restart_index;
1627          cfg.unk_2a = (ib >> 32);
1628          cfg.primitive = prim;
1629          cfg.restart_enable = info->primitive_restart;
1630          cfg.index_size = __builtin_ctz(idx_size);
1631          cfg.index_buffer_offset = (ib & BITFIELD_MASK(32));
1632          cfg.index_buffer_size = ALIGN_POT(draws->count * idx_size, 4);
1633          cfg.index_count = draws->count;
1634          cfg.instance_count = info->instance_count;
1635          cfg.base_vertex = draws->index_bias;
1636       };
1637 
1638       out += AGX_INDEXED_DRAW_LENGTH;
1639    } else {
1640       agx_pack(out, DRAW, cfg) {
1641          cfg.primitive = prim;
1642          cfg.vertex_start = draws->start;
1643          cfg.vertex_count = draws->count;
1644          cfg.instance_count = info->instance_count;
1645       };
1646 
1647       out += AGX_DRAW_LENGTH;
1648    }
1649 
1650    batch->encoder_current = out;
1651    ctx->dirty = 0;
1652 }
1653 
1654 void agx_init_state_functions(struct pipe_context *ctx);
1655 
1656 void
agx_init_state_functions(struct pipe_context * ctx)1657 agx_init_state_functions(struct pipe_context *ctx)
1658 {
1659    ctx->create_blend_state = agx_create_blend_state;
1660    ctx->create_depth_stencil_alpha_state = agx_create_zsa_state;
1661    ctx->create_fs_state = agx_create_shader_state;
1662    ctx->create_rasterizer_state = agx_create_rs_state;
1663    ctx->create_sampler_state = agx_create_sampler_state;
1664    ctx->create_sampler_view = agx_create_sampler_view;
1665    ctx->create_surface = agx_create_surface;
1666    ctx->create_vertex_elements_state = agx_create_vertex_elements;
1667    ctx->create_vs_state = agx_create_shader_state;
1668    ctx->bind_blend_state = agx_bind_blend_state;
1669    ctx->bind_depth_stencil_alpha_state = agx_bind_zsa_state;
1670    ctx->bind_sampler_states = agx_bind_sampler_states;
1671    ctx->bind_fs_state = agx_bind_shader_state;
1672    ctx->bind_rasterizer_state = agx_bind_rasterizer_state;
1673    ctx->bind_vertex_elements_state = agx_bind_vertex_elements_state;
1674    ctx->bind_vs_state = agx_bind_shader_state;
1675    ctx->delete_blend_state = agx_delete_state;
1676    ctx->delete_depth_stencil_alpha_state = agx_delete_state;
1677    ctx->delete_fs_state = agx_delete_shader_state;
1678    ctx->delete_rasterizer_state = agx_delete_state;
1679    ctx->delete_sampler_state = agx_delete_sampler_state;
1680    ctx->delete_vertex_elements_state = agx_delete_state;
1681    ctx->delete_vs_state = agx_delete_state;
1682    ctx->set_blend_color = agx_set_blend_color;
1683    ctx->set_clip_state = agx_set_clip_state;
1684    ctx->set_constant_buffer = agx_set_constant_buffer;
1685    ctx->set_sampler_views = agx_set_sampler_views;
1686    ctx->set_framebuffer_state = agx_set_framebuffer_state;
1687    ctx->set_polygon_stipple = agx_set_polygon_stipple;
1688    ctx->set_sample_mask = agx_set_sample_mask;
1689    ctx->set_scissor_states = agx_set_scissor_states;
1690    ctx->set_stencil_ref = agx_set_stencil_ref;
1691    ctx->set_vertex_buffers = agx_set_vertex_buffers;
1692    ctx->set_viewport_states = agx_set_viewport_states;
1693    ctx->sampler_view_destroy = agx_sampler_view_destroy;
1694    ctx->surface_destroy = agx_surface_destroy;
1695    ctx->draw_vbo = agx_draw_vbo;
1696    ctx->create_stream_output_target = agx_create_stream_output_target;
1697    ctx->stream_output_target_destroy = agx_stream_output_target_destroy;
1698    ctx->set_stream_output_targets = agx_set_stream_output_targets;
1699 }
1700