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