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