1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2021 Alyssa Rosenzweig 3bf215546Sopenharmony_ci * Copyright (C) 2019-2021 Collabora, Ltd. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#ifndef AGX_STATE_H 26bf215546Sopenharmony_ci#define AGX_STATE_H 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "gallium/include/pipe/p_context.h" 29bf215546Sopenharmony_ci#include "gallium/include/pipe/p_state.h" 30bf215546Sopenharmony_ci#include "gallium/include/pipe/p_screen.h" 31bf215546Sopenharmony_ci#include "gallium/auxiliary/util/u_blitter.h" 32bf215546Sopenharmony_ci#include "asahi/lib/agx_pack.h" 33bf215546Sopenharmony_ci#include "asahi/lib/agx_bo.h" 34bf215546Sopenharmony_ci#include "asahi/lib/agx_device.h" 35bf215546Sopenharmony_ci#include "asahi/lib/pool.h" 36bf215546Sopenharmony_ci#include "asahi/compiler/agx_compile.h" 37bf215546Sopenharmony_ci#include "compiler/nir/nir_lower_blend.h" 38bf215546Sopenharmony_ci#include "util/hash_table.h" 39bf215546Sopenharmony_ci#include "util/bitset.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cistruct agx_streamout_target { 42bf215546Sopenharmony_ci struct pipe_stream_output_target base; 43bf215546Sopenharmony_ci uint32_t offset; 44bf215546Sopenharmony_ci}; 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_cistruct agx_streamout { 47bf215546Sopenharmony_ci struct pipe_stream_output_target *targets[PIPE_MAX_SO_BUFFERS]; 48bf215546Sopenharmony_ci unsigned num_targets; 49bf215546Sopenharmony_ci}; 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_cistatic inline struct agx_streamout_target * 52bf215546Sopenharmony_ciagx_so_target(struct pipe_stream_output_target *target) 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci return (struct agx_streamout_target *)target; 55bf215546Sopenharmony_ci} 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_cistruct agx_compiled_shader { 58bf215546Sopenharmony_ci /* Mapped executable memory */ 59bf215546Sopenharmony_ci struct agx_bo *bo; 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci /* Varying descriptor (TODO: is this the right place?) */ 62bf215546Sopenharmony_ci uint64_t varyings; 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci /* Metadata returned from the compiler */ 65bf215546Sopenharmony_ci struct agx_shader_info info; 66bf215546Sopenharmony_ci}; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_cistruct agx_uncompiled_shader { 69bf215546Sopenharmony_ci struct pipe_shader_state base; 70bf215546Sopenharmony_ci struct nir_shader *nir; 71bf215546Sopenharmony_ci struct hash_table *variants; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci /* Set on VS, passed to FS for linkage */ 74bf215546Sopenharmony_ci unsigned base_varying; 75bf215546Sopenharmony_ci}; 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_cistruct agx_stage { 78bf215546Sopenharmony_ci struct agx_uncompiled_shader *shader; 79bf215546Sopenharmony_ci uint32_t dirty; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci struct pipe_constant_buffer cb[PIPE_MAX_CONSTANT_BUFFERS]; 82bf215546Sopenharmony_ci uint32_t cb_mask; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci /* Need full CSOs for u_blitter */ 85bf215546Sopenharmony_ci struct agx_sampler_state *samplers[PIPE_MAX_SAMPLERS]; 86bf215546Sopenharmony_ci struct agx_sampler_view *textures[PIPE_MAX_SHADER_SAMPLER_VIEWS]; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci unsigned sampler_count, texture_count; 89bf215546Sopenharmony_ci}; 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci/* Uploaded scissor or depth bias descriptors */ 92bf215546Sopenharmony_cistruct agx_array { 93bf215546Sopenharmony_ci struct agx_bo *bo; 94bf215546Sopenharmony_ci unsigned count; 95bf215546Sopenharmony_ci}; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_cistruct agx_batch { 98bf215546Sopenharmony_ci unsigned width, height, nr_cbufs; 99bf215546Sopenharmony_ci struct pipe_surface *cbufs[8]; 100bf215546Sopenharmony_ci struct pipe_surface *zsbuf; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci /* PIPE_CLEAR_* bitmask */ 103bf215546Sopenharmony_ci uint32_t clear, draw; 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci float clear_color[4]; 106bf215546Sopenharmony_ci double clear_depth; 107bf215546Sopenharmony_ci unsigned clear_stencil; 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci /* Resource list requirements, represented as a bit set indexed by BO 110bf215546Sopenharmony_ci * handles (GEM handles on Linux, or IOGPU's equivalent on macOS) */ 111bf215546Sopenharmony_ci BITSET_WORD bo_list[256]; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci struct agx_pool pool, pipeline_pool; 114bf215546Sopenharmony_ci struct agx_bo *encoder; 115bf215546Sopenharmony_ci uint8_t *encoder_current; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci struct agx_array scissor, depth_bias; 118bf215546Sopenharmony_ci}; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_cistruct agx_zsa { 121bf215546Sopenharmony_ci struct pipe_depth_stencil_alpha_state base; 122bf215546Sopenharmony_ci struct agx_rasterizer_face_packed front, back; 123bf215546Sopenharmony_ci}; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_cistruct agx_blend { 126bf215546Sopenharmony_ci bool logicop_enable, blend_enable; 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci union { 129bf215546Sopenharmony_ci nir_lower_blend_rt rt[8]; 130bf215546Sopenharmony_ci unsigned logicop_func; 131bf215546Sopenharmony_ci }; 132bf215546Sopenharmony_ci}; 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_cistruct asahi_shader_key { 135bf215546Sopenharmony_ci struct agx_shader_key base; 136bf215546Sopenharmony_ci struct agx_blend blend; 137bf215546Sopenharmony_ci unsigned nr_cbufs; 138bf215546Sopenharmony_ci enum pipe_format rt_formats[PIPE_MAX_COLOR_BUFS]; 139bf215546Sopenharmony_ci}; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_cienum agx_dirty { 142bf215546Sopenharmony_ci AGX_DIRTY_VERTEX = BITFIELD_BIT(0), 143bf215546Sopenharmony_ci AGX_DIRTY_VIEWPORT = BITFIELD_BIT(1), 144bf215546Sopenharmony_ci AGX_DIRTY_SCISSOR_ZBIAS = BITFIELD_BIT(2), 145bf215546Sopenharmony_ci}; 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_cistruct agx_context { 148bf215546Sopenharmony_ci struct pipe_context base; 149bf215546Sopenharmony_ci struct agx_compiled_shader *vs, *fs; 150bf215546Sopenharmony_ci uint32_t dirty; 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci struct agx_batch *batch; 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; 155bf215546Sopenharmony_ci uint32_t vb_mask; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci struct agx_stage stage[PIPE_SHADER_TYPES]; 158bf215546Sopenharmony_ci struct agx_attribute *attributes; 159bf215546Sopenharmony_ci struct agx_rasterizer *rast; 160bf215546Sopenharmony_ci struct agx_zsa zs; 161bf215546Sopenharmony_ci struct agx_blend *blend; 162bf215546Sopenharmony_ci struct pipe_blend_color blend_color; 163bf215546Sopenharmony_ci struct pipe_viewport_state viewport; 164bf215546Sopenharmony_ci struct pipe_scissor_state scissor; 165bf215546Sopenharmony_ci struct pipe_stencil_ref stencil_ref; 166bf215546Sopenharmony_ci struct agx_streamout streamout; 167bf215546Sopenharmony_ci uint16_t sample_mask; 168bf215546Sopenharmony_ci struct pipe_framebuffer_state framebuffer; 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci struct pipe_query *cond_query; 171bf215546Sopenharmony_ci bool cond_cond; 172bf215546Sopenharmony_ci enum pipe_render_cond_flag cond_mode; 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci bool is_noop; 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci uint8_t render_target[8][AGX_RENDER_TARGET_LENGTH]; 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci struct blitter_context *blitter; 179bf215546Sopenharmony_ci}; 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_cistatic inline struct agx_context * 182bf215546Sopenharmony_ciagx_context(struct pipe_context *pctx) 183bf215546Sopenharmony_ci{ 184bf215546Sopenharmony_ci return (struct agx_context *) pctx; 185bf215546Sopenharmony_ci} 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_cistruct agx_rasterizer { 188bf215546Sopenharmony_ci struct pipe_rasterizer_state base; 189bf215546Sopenharmony_ci uint8_t cull[AGX_CULL_LENGTH]; 190bf215546Sopenharmony_ci uint8_t line_width; 191bf215546Sopenharmony_ci}; 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_cistruct agx_query { 194bf215546Sopenharmony_ci unsigned query; 195bf215546Sopenharmony_ci}; 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_cistruct agx_sampler_state { 198bf215546Sopenharmony_ci struct pipe_sampler_state base; 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci /* Prepared descriptor */ 201bf215546Sopenharmony_ci struct agx_bo *desc; 202bf215546Sopenharmony_ci}; 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_cistruct agx_sampler_view { 205bf215546Sopenharmony_ci struct pipe_sampler_view base; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci /* Prepared descriptor */ 208bf215546Sopenharmony_ci struct agx_bo *desc; 209bf215546Sopenharmony_ci}; 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_cistruct agx_screen { 212bf215546Sopenharmony_ci struct pipe_screen pscreen; 213bf215546Sopenharmony_ci struct agx_device dev; 214bf215546Sopenharmony_ci struct sw_winsys *winsys; 215bf215546Sopenharmony_ci}; 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_cistatic inline struct agx_screen * 218bf215546Sopenharmony_ciagx_screen(struct pipe_screen *p) 219bf215546Sopenharmony_ci{ 220bf215546Sopenharmony_ci return (struct agx_screen *)p; 221bf215546Sopenharmony_ci} 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_cistatic inline struct agx_device * 224bf215546Sopenharmony_ciagx_device(struct pipe_screen *p) 225bf215546Sopenharmony_ci{ 226bf215546Sopenharmony_ci return &(agx_screen(p)->dev); 227bf215546Sopenharmony_ci} 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci/* TODO: UABI, fake for macOS */ 230bf215546Sopenharmony_ci#ifndef DRM_FORMAT_MOD_LINEAR 231bf215546Sopenharmony_ci#define DRM_FORMAT_MOD_LINEAR 1 232bf215546Sopenharmony_ci#endif 233bf215546Sopenharmony_ci#define DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER (2) 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_cistruct agx_resource { 236bf215546Sopenharmony_ci struct pipe_resource base; 237bf215546Sopenharmony_ci uint64_t modifier; 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci /* Should probably be part of the modifier. Affects the tiling algorithm, or 240bf215546Sopenharmony_ci * something like that. 241bf215546Sopenharmony_ci */ 242bf215546Sopenharmony_ci bool mipmapped; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci /* Hardware backing */ 245bf215546Sopenharmony_ci struct agx_bo *bo; 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci /* Software backing (XXX) */ 248bf215546Sopenharmony_ci struct sw_displaytarget *dt; 249bf215546Sopenharmony_ci unsigned dt_stride; 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci BITSET_DECLARE(data_valid, PIPE_MAX_TEXTURE_LEVELS); 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci struct { 254bf215546Sopenharmony_ci unsigned offset; 255bf215546Sopenharmony_ci unsigned line_stride; 256bf215546Sopenharmony_ci unsigned size; 257bf215546Sopenharmony_ci } slices[PIPE_MAX_TEXTURE_LEVELS]; 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci /* Bytes from one miptree to the next */ 260bf215546Sopenharmony_ci unsigned array_stride; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci /* Metal does not support packed depth/stencil formats; presumably AGX does 263bf215546Sopenharmony_ci * not either. Instead, we create separate depth and stencil resources, 264bf215546Sopenharmony_ci * managed by u_transfer_helper. We provide the illusion of packed 265bf215546Sopenharmony_ci * resources. 266bf215546Sopenharmony_ci */ 267bf215546Sopenharmony_ci struct agx_resource *separate_stencil; 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci /* Internal format, since many depth/stencil formats are emulated. */ 270bf215546Sopenharmony_ci enum pipe_format internal_format; 271bf215546Sopenharmony_ci}; 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_cistatic inline struct agx_resource * 274bf215546Sopenharmony_ciagx_resource(struct pipe_resource *pctx) 275bf215546Sopenharmony_ci{ 276bf215546Sopenharmony_ci return (struct agx_resource *) pctx; 277bf215546Sopenharmony_ci} 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci/* 280bf215546Sopenharmony_ci * Within a resource containing multiple layers and multiple mip levels, 281bf215546Sopenharmony_ci * returns the offset from the start of the backing BO of a given level/slice. 282bf215546Sopenharmony_ci */ 283bf215546Sopenharmony_cistatic inline uint32_t 284bf215546Sopenharmony_ciagx_texture_offset(struct agx_resource *rsrc, unsigned level, unsigned z) 285bf215546Sopenharmony_ci{ 286bf215546Sopenharmony_ci return rsrc->slices[level].offset + (z * rsrc->array_stride); 287bf215546Sopenharmony_ci} 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_cistatic inline void * 290bf215546Sopenharmony_ciagx_map_texture_cpu(struct agx_resource *rsrc, unsigned level, unsigned z) 291bf215546Sopenharmony_ci{ 292bf215546Sopenharmony_ci return ((uint8_t *) rsrc->bo->ptr.cpu) + agx_texture_offset(rsrc, level, z); 293bf215546Sopenharmony_ci} 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_cistatic inline uint64_t 296bf215546Sopenharmony_ciagx_map_texture_gpu(struct agx_resource *rsrc, unsigned level, unsigned z) 297bf215546Sopenharmony_ci{ 298bf215546Sopenharmony_ci return rsrc->bo->ptr.gpu + (uint64_t) agx_texture_offset(rsrc, level, z); 299bf215546Sopenharmony_ci} 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_cistruct agx_transfer { 302bf215546Sopenharmony_ci struct pipe_transfer base; 303bf215546Sopenharmony_ci void *map; 304bf215546Sopenharmony_ci struct { 305bf215546Sopenharmony_ci struct pipe_resource *rsrc; 306bf215546Sopenharmony_ci struct pipe_box box; 307bf215546Sopenharmony_ci } staging; 308bf215546Sopenharmony_ci}; 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_cistatic inline struct agx_transfer * 311bf215546Sopenharmony_ciagx_transfer(struct pipe_transfer *p) 312bf215546Sopenharmony_ci{ 313bf215546Sopenharmony_ci return (struct agx_transfer *)p; 314bf215546Sopenharmony_ci} 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ciuint64_t 317bf215546Sopenharmony_ciagx_push_location(struct agx_context *ctx, struct agx_push push, 318bf215546Sopenharmony_ci enum pipe_shader_type stage); 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ciuint64_t 321bf215546Sopenharmony_ciagx_build_clear_pipeline(struct agx_context *ctx, uint32_t code, uint64_t clear_buf); 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ciuint64_t 324bf215546Sopenharmony_ciagx_build_store_pipeline(struct agx_context *ctx, uint32_t code, 325bf215546Sopenharmony_ci uint64_t render_target); 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ciuint64_t 328bf215546Sopenharmony_ciagx_build_reload_pipeline(struct agx_context *ctx, uint32_t code, struct pipe_surface *surf); 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci/* Add a BO to a batch. This needs to be amortized O(1) since it's called in 331bf215546Sopenharmony_ci * hot paths. To achieve this we model BO lists by bit sets */ 332bf215546Sopenharmony_ci 333bf215546Sopenharmony_cistatic inline void 334bf215546Sopenharmony_ciagx_batch_add_bo(struct agx_batch *batch, struct agx_bo *bo) 335bf215546Sopenharmony_ci{ 336bf215546Sopenharmony_ci if (unlikely(bo->handle > (sizeof(batch->bo_list) * 8))) 337bf215546Sopenharmony_ci unreachable("todo: growable"); 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci BITSET_SET(batch->bo_list, bo->handle); 340bf215546Sopenharmony_ci} 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci/* Blit shaders */ 343bf215546Sopenharmony_civoid agx_blit(struct pipe_context *pipe, 344bf215546Sopenharmony_ci const struct pipe_blit_info *info); 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_civoid agx_internal_shaders(struct agx_device *dev); 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci#endif 349