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