xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/freedreno/a6xx/fd6_screen.cc (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2016 Rob Clark <[email protected]>
3  * Copyright © 2018 Google, Inc.
4  * SPDX-License-Identifier: MIT
5  *
6  * Authors:
7  *    Rob Clark <[email protected]>
8  */
9 
10 #define FD_BO_NO_HARDPIN 1
11 
12 #include "drm-uapi/drm_fourcc.h"
13 #include "pipe/p_screen.h"
14 #include "util/format/u_format.h"
15 
16 #include "fd6_blitter.h"
17 #include "fd6_context.h"
18 #include "fd6_emit.h"
19 #include "fd6_resource.h"
20 #include "fd6_screen.h"
21 
22 #include "ir3/ir3_compiler.h"
23 
24 static bool
valid_sample_count(unsigned sample_count)25 valid_sample_count(unsigned sample_count)
26 {
27    switch (sample_count) {
28    case 0:
29    case 1:
30    case 2:
31    case 4:
32       // TODO seems 8x works, but increases lrz width or height.. but the
33       // blob I have doesn't seem to expose any egl configs w/ 8x, so
34       // just hide it for now and revisit later.
35       //	case 8:
36       return true;
37    default:
38       return false;
39    }
40 }
41 
42 static bool
fd6_screen_is_format_supported(struct pipe_screen * pscreen,enum pipe_format format,enum pipe_texture_target target,unsigned sample_count,unsigned storage_sample_count,unsigned usage)43 fd6_screen_is_format_supported(struct pipe_screen *pscreen,
44                                enum pipe_format format,
45                                enum pipe_texture_target target,
46                                unsigned sample_count,
47                                unsigned storage_sample_count, unsigned usage)
48 {
49    unsigned retval = 0;
50 
51    if ((target >= PIPE_MAX_TEXTURE_TYPES) ||
52        !valid_sample_count(sample_count)) {
53       DBG("not supported: format=%s, target=%d, sample_count=%d, usage=%x",
54           util_format_name(format), target, sample_count, usage);
55       return false;
56    }
57 
58    if (MAX2(1, sample_count) != MAX2(1, storage_sample_count))
59       return false;
60 
61    if ((usage & PIPE_BIND_VERTEX_BUFFER) &&
62        (fd6_vertex_format(format) != FMT6_NONE)) {
63       retval |= PIPE_BIND_VERTEX_BUFFER;
64    }
65 
66    bool has_color = fd6_color_format(format, TILE6_LINEAR) != FMT6_NONE;
67    bool has_tex = fd6_texture_format(format, TILE6_LINEAR) != FMT6_NONE;
68 
69    if ((usage & (PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_SHADER_IMAGE)) &&
70        has_tex &&
71        (target == PIPE_BUFFER ||
72         util_is_power_of_two_or_zero(util_format_get_blocksize(format)))) {
73       retval |= usage & (PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_SHADER_IMAGE);
74    }
75 
76    if (usage & PIPE_BIND_SHADER_IMAGE) {
77       if (sample_count > 1)
78          return false;
79 
80       /* So, this only matters for image writes but 'usage' doesn't
81        * differentiate.  See f1c1b96
82        */
83       const struct util_format_description *desc = util_format_description(format);
84       if ((desc->nr_channels > 2) && (desc->block.bits == 16))
85          return false;
86    }
87 
88    if ((usage &
89         (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET |
90          PIPE_BIND_SCANOUT | PIPE_BIND_SHARED | PIPE_BIND_COMPUTE_RESOURCE)) &&
91        has_color && has_tex) {
92       retval |= usage & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET |
93                          PIPE_BIND_SCANOUT | PIPE_BIND_SHARED |
94                          PIPE_BIND_COMPUTE_RESOURCE);
95    }
96 
97    /* For ARB_framebuffer_no_attachments: */
98    if ((usage & PIPE_BIND_RENDER_TARGET) && (format == PIPE_FORMAT_NONE)) {
99       retval |= usage & PIPE_BIND_RENDER_TARGET;
100    }
101 
102    if ((usage & PIPE_BIND_DEPTH_STENCIL) &&
103        (fd6_pipe2depth(format) != (enum a6xx_depth_format) ~0) && has_tex) {
104       retval |= PIPE_BIND_DEPTH_STENCIL;
105    }
106 
107    if ((usage & PIPE_BIND_INDEX_BUFFER) &&
108        (fd_pipe2index(format) != (enum pc_di_index_size) ~0)) {
109       retval |= PIPE_BIND_INDEX_BUFFER;
110    }
111 
112    if ((usage & PIPE_BIND_BLENDABLE) && has_color &&
113        !util_format_is_pure_integer(format)) {
114       retval |= PIPE_BIND_BLENDABLE;
115    }
116 
117    if (retval != usage) {
118       DBG("not supported: format=%s, target=%d, sample_count=%d, "
119           "usage=%x, retval=%x",
120           util_format_name(format), target, sample_count, usage, retval);
121    }
122 
123    return retval == usage;
124 }
125 
126 /* clang-format off */
127 static const enum pc_di_primtype primtypes[] = {
128    [MESA_PRIM_POINTS]                      = DI_PT_POINTLIST,
129    [MESA_PRIM_LINES]                       = DI_PT_LINELIST,
130    [MESA_PRIM_LINE_LOOP]                   = DI_PT_LINELOOP,
131    [MESA_PRIM_LINE_STRIP]                  = DI_PT_LINESTRIP,
132    [MESA_PRIM_TRIANGLES]                   = DI_PT_TRILIST,
133    [MESA_PRIM_TRIANGLE_STRIP]              = DI_PT_TRISTRIP,
134    [MESA_PRIM_TRIANGLE_FAN]                = DI_PT_TRIFAN,
135    [MESA_PRIM_QUADS]                       = DI_PT_NONE,   /* unsupported */
136    [MESA_PRIM_QUAD_STRIP]                  = DI_PT_NONE,   /* unsupported */
137    [MESA_PRIM_POLYGON]                     = DI_PT_NONE,   /* unsupported */
138    [MESA_PRIM_LINES_ADJACENCY]             = DI_PT_LINE_ADJ,
139    [MESA_PRIM_LINE_STRIP_ADJACENCY]        = DI_PT_LINESTRIP_ADJ,
140    [MESA_PRIM_TRIANGLES_ADJACENCY]         = DI_PT_TRI_ADJ,
141    [MESA_PRIM_TRIANGLE_STRIP_ADJACENCY]    = DI_PT_TRISTRIP_ADJ,
142    [MESA_PRIM_PATCHES]                     = DI_PT_PATCHES0,
143    [MESA_PRIM_COUNT]                         = DI_PT_RECTLIST,  /* internal clear blits */
144 };
145 /* clang-format on */
146 
147 void
fd6_screen_init(struct pipe_screen * pscreen)148 fd6_screen_init(struct pipe_screen *pscreen)
149 {
150    struct fd_screen *screen = fd_screen(pscreen);
151 
152    screen->max_rts = A6XX_MAX_RENDER_TARGETS;
153 
154    uint32_t depth_cache_size =
155       screen->info->num_ccu * screen->info->a6xx.sysmem_per_ccu_depth_cache_size;
156    uint32_t color_cache_size =
157       (screen->info->num_ccu * screen->info->a6xx.sysmem_per_ccu_color_cache_size) /
158       (1 << screen->info->a6xx.gmem_ccu_color_cache_fraction);
159    uint32_t color_cache_size_gmem =
160       color_cache_size /
161       (1 << screen->info->a6xx.gmem_ccu_color_cache_fraction);
162 
163    struct fd6_gmem_config *gmem = &screen->config_gmem;
164    struct fd6_gmem_config *sysmem = &screen->config_sysmem;
165 
166    sysmem->depth_ccu_offset = 0;
167    sysmem->color_ccu_offset = sysmem->depth_ccu_offset + depth_cache_size;
168 
169    if (screen->info->a7xx.has_gmem_vpc_attr_buf) {
170       sysmem->vpc_attr_buf_size = screen->info->a7xx.sysmem_vpc_attr_buf_size;
171       sysmem->vpc_attr_buf_offset = sysmem->color_ccu_offset + color_cache_size;
172 
173       gmem->vpc_attr_buf_size = screen->info->a7xx.gmem_vpc_attr_buf_size;
174       gmem->vpc_attr_buf_offset = screen->gmemsize_bytes -
175          (gmem->vpc_attr_buf_size * screen->info->num_ccu);
176 
177       gmem->color_ccu_offset = gmem->vpc_attr_buf_offset - color_cache_size_gmem;
178       screen->gmemsize_bytes = gmem->vpc_attr_buf_offset;
179    } else {
180       gmem->depth_ccu_offset = 0;
181       gmem->color_ccu_offset = screen->gmemsize_bytes - color_cache_size_gmem;
182    }
183 
184    /* Currently only FB_READ forces GMEM path, mostly because we'd have to
185     * deal with cmdstream patching otherwise..
186     */
187    screen->gmem_reason_mask = (enum fd_gmem_reason)(
188          FD_GMEM_CLEARS_DEPTH_STENCIL |
189          FD_GMEM_DEPTH_ENABLED | FD_GMEM_STENCIL_ENABLED |
190          FD_GMEM_BLEND_ENABLED | FD_GMEM_LOGICOP_ENABLED);
191 
192    pscreen->context_create = FD_CALLX(screen->info, fd6_context_create);
193    pscreen->is_format_supported = fd6_screen_is_format_supported;
194 
195    screen->tile_mode = fd6_tile_mode;
196 
197    FD_CALLX(screen->info, fd6_resource_screen_init)(pscreen);
198    fd6_emit_init_screen(pscreen);
199    ir3_screen_init(pscreen);
200 
201    screen->primtypes = primtypes;
202 }
203