• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
41 struct agx_streamout_target {
42    struct pipe_stream_output_target base;
43    uint32_t offset;
44 };
45 
46 struct agx_streamout {
47    struct pipe_stream_output_target *targets[PIPE_MAX_SO_BUFFERS];
48    unsigned num_targets;
49 };
50 
51 static inline struct agx_streamout_target *
agx_so_target(struct pipe_stream_output_target * target)52 agx_so_target(struct pipe_stream_output_target *target)
53 {
54    return (struct agx_streamout_target *)target;
55 }
56 
57 struct 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 
68 struct 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 
77 struct 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 or depth bias descriptors */
92 struct agx_array {
93       struct agx_bo *bo;
94       unsigned count;
95 };
96 
97 struct 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    double clear_depth;
107    unsigned clear_stencil;
108 
109    /* Resource list requirements, represented as a bit set indexed by BO
110     * handles (GEM handles on Linux, or IOGPU's equivalent on macOS) */
111    BITSET_WORD bo_list[256];
112 
113    struct agx_pool pool, pipeline_pool;
114    struct agx_bo *encoder;
115    uint8_t *encoder_current;
116 
117    struct agx_array scissor, depth_bias;
118 };
119 
120 struct agx_zsa {
121    struct pipe_depth_stencil_alpha_state base;
122    struct agx_rasterizer_face_packed front, back;
123 };
124 
125 struct agx_blend {
126    bool logicop_enable, blend_enable;
127 
128    union {
129       nir_lower_blend_rt rt[8];
130       unsigned logicop_func;
131    };
132 };
133 
134 struct asahi_shader_key {
135    struct agx_shader_key base;
136    struct agx_blend blend;
137    unsigned nr_cbufs;
138    enum pipe_format rt_formats[PIPE_MAX_COLOR_BUFS];
139 };
140 
141 enum agx_dirty {
142    AGX_DIRTY_VERTEX   = BITFIELD_BIT(0),
143    AGX_DIRTY_VIEWPORT = BITFIELD_BIT(1),
144    AGX_DIRTY_SCISSOR_ZBIAS  = BITFIELD_BIT(2),
145 };
146 
147 struct agx_context {
148    struct pipe_context base;
149    struct agx_compiled_shader *vs, *fs;
150    uint32_t dirty;
151 
152    struct agx_batch *batch;
153 
154    struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
155    uint32_t vb_mask;
156 
157    struct agx_stage stage[PIPE_SHADER_TYPES];
158    struct agx_attribute *attributes;
159    struct agx_rasterizer *rast;
160    struct agx_zsa zs;
161    struct agx_blend *blend;
162    struct pipe_blend_color blend_color;
163    struct pipe_viewport_state viewport;
164    struct pipe_scissor_state scissor;
165    struct pipe_stencil_ref stencil_ref;
166    struct agx_streamout streamout;
167    uint16_t sample_mask;
168    struct pipe_framebuffer_state framebuffer;
169 
170    struct pipe_query *cond_query;
171    bool cond_cond;
172    enum pipe_render_cond_flag cond_mode;
173 
174    bool is_noop;
175 
176    uint8_t render_target[8][AGX_RENDER_TARGET_LENGTH];
177 
178    struct blitter_context *blitter;
179 };
180 
181 static inline struct agx_context *
agx_context(struct pipe_context * pctx)182 agx_context(struct pipe_context *pctx)
183 {
184    return (struct agx_context *) pctx;
185 }
186 
187 struct agx_rasterizer {
188    struct pipe_rasterizer_state base;
189    uint8_t cull[AGX_CULL_LENGTH];
190    uint8_t line_width;
191 };
192 
193 struct agx_query {
194    unsigned	query;
195 };
196 
197 struct agx_sampler_state {
198    struct pipe_sampler_state base;
199 
200    /* Prepared descriptor */
201    struct agx_bo *desc;
202 };
203 
204 struct agx_sampler_view {
205    struct pipe_sampler_view base;
206 
207    /* Prepared descriptor */
208    struct agx_bo *desc;
209 };
210 
211 struct agx_screen {
212    struct pipe_screen pscreen;
213    struct agx_device dev;
214    struct sw_winsys *winsys;
215 };
216 
217 static inline struct agx_screen *
agx_screen(struct pipe_screen * p)218 agx_screen(struct pipe_screen *p)
219 {
220    return (struct agx_screen *)p;
221 }
222 
223 static inline struct agx_device *
agx_device(struct pipe_screen * p)224 agx_device(struct pipe_screen *p)
225 {
226    return &(agx_screen(p)->dev);
227 }
228 
229 /* TODO: UABI, fake for macOS */
230 #ifndef DRM_FORMAT_MOD_LINEAR
231 #define DRM_FORMAT_MOD_LINEAR 1
232 #endif
233 #define DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER (2)
234 
235 struct agx_resource {
236    struct pipe_resource	base;
237    uint64_t modifier;
238 
239    /* Should probably be part of the modifier. Affects the tiling algorithm, or
240     * something like that.
241     */
242    bool mipmapped;
243 
244    /* Hardware backing */
245    struct agx_bo *bo;
246 
247    /* Software backing (XXX) */
248    struct sw_displaytarget	*dt;
249    unsigned dt_stride;
250 
251    BITSET_DECLARE(data_valid, PIPE_MAX_TEXTURE_LEVELS);
252 
253    struct {
254       unsigned offset;
255       unsigned line_stride;
256       unsigned size;
257    } slices[PIPE_MAX_TEXTURE_LEVELS];
258 
259    /* Bytes from one miptree to the next */
260    unsigned array_stride;
261 
262    /* Metal does not support packed depth/stencil formats; presumably AGX does
263     * not either. Instead, we create separate depth and stencil resources,
264     * managed by u_transfer_helper.  We provide the illusion of packed
265     * resources.
266     */
267    struct agx_resource *separate_stencil;
268 
269    /* Internal format, since many depth/stencil formats are emulated. */
270    enum pipe_format internal_format;
271 };
272 
273 static inline struct agx_resource *
agx_resource(struct pipe_resource * pctx)274 agx_resource(struct pipe_resource *pctx)
275 {
276    return (struct agx_resource *) pctx;
277 }
278 
279 /*
280  * Within a resource containing multiple layers and multiple mip levels,
281  * returns the offset from the start of the backing BO of a given level/slice.
282  */
283 static inline uint32_t
agx_texture_offset(struct agx_resource * rsrc,unsigned level,unsigned z)284 agx_texture_offset(struct agx_resource *rsrc, unsigned level, unsigned z)
285 {
286    return rsrc->slices[level].offset + (z * rsrc->array_stride);
287 }
288 
289 static inline void *
agx_map_texture_cpu(struct agx_resource * rsrc,unsigned level,unsigned z)290 agx_map_texture_cpu(struct agx_resource *rsrc, unsigned level, unsigned z)
291 {
292    return ((uint8_t *) rsrc->bo->ptr.cpu) + agx_texture_offset(rsrc, level, z);
293 }
294 
295 static inline uint64_t
agx_map_texture_gpu(struct agx_resource * rsrc,unsigned level,unsigned z)296 agx_map_texture_gpu(struct agx_resource *rsrc, unsigned level, unsigned z)
297 {
298    return rsrc->bo->ptr.gpu + (uint64_t) agx_texture_offset(rsrc, level, z);
299 }
300 
301 struct agx_transfer {
302    struct pipe_transfer base;
303    void *map;
304    struct {
305       struct pipe_resource *rsrc;
306       struct pipe_box box;
307    } staging;
308 };
309 
310 static inline struct agx_transfer *
agx_transfer(struct pipe_transfer * p)311 agx_transfer(struct pipe_transfer *p)
312 {
313    return (struct agx_transfer *)p;
314 }
315 
316 uint64_t
317 agx_push_location(struct agx_context *ctx, struct agx_push push,
318                   enum pipe_shader_type stage);
319 
320 uint64_t
321 agx_build_clear_pipeline(struct agx_context *ctx, uint32_t code, uint64_t clear_buf);
322 
323 uint64_t
324 agx_build_store_pipeline(struct agx_context *ctx, uint32_t code,
325                          uint64_t render_target);
326 
327 uint64_t
328 agx_build_reload_pipeline(struct agx_context *ctx, uint32_t code, struct pipe_surface *surf);
329 
330 /* Add a BO to a batch. This needs to be amortized O(1) since it's called in
331  * hot paths. To achieve this we model BO lists by bit sets */
332 
333 static inline void
agx_batch_add_bo(struct agx_batch * batch,struct agx_bo * bo)334 agx_batch_add_bo(struct agx_batch *batch, struct agx_bo *bo)
335 {
336    if (unlikely(bo->handle > (sizeof(batch->bo_list) * 8)))
337       unreachable("todo: growable");
338 
339    BITSET_SET(batch->bo_list, bo->handle);
340 }
341 
342 /* Blit shaders */
343 void agx_blit(struct pipe_context *pipe,
344               const struct pipe_blit_info *info);
345 
346 void agx_internal_shaders(struct agx_device *dev);
347 
348 #endif
349