Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/freedreno/a6xx/fd6_resource.c
4574 views
1
/*
2
* Copyright (C) 2018 Rob Clark <[email protected]>
3
* Copyright © 2018 Google, Inc.
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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
19
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
* SOFTWARE.
23
*
24
* Authors:
25
* Rob Clark <[email protected]>
26
*/
27
28
#include "drm-uapi/drm_fourcc.h"
29
30
#include "fd6_format.h"
31
#include "fd6_resource.h"
32
33
#include "a6xx.xml.h"
34
35
/* A subset of the valid tiled formats can be compressed. We do
36
* already require tiled in order to be compressed, but just because
37
* it can be tiled doesn't mean it can be compressed.
38
*/
39
static bool
40
ok_ubwc_format(struct pipe_screen *pscreen, enum pipe_format pfmt)
41
{
42
const struct fd_dev_info *info = fd_screen(pscreen)->info;
43
44
switch (pfmt) {
45
case PIPE_FORMAT_X24S8_UINT:
46
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
47
/* We can't sample stencil with UBWC on a630, and we may need to be able
48
* to sample stencil at some point. We can't just use
49
* fd_resource_uncompress() at the point of stencil sampling because
50
* that itself uses stencil sampling in the fd_blitter_blit path.
51
*/
52
return info->a6xx.has_z24uint_s8uint;
53
54
case PIPE_FORMAT_R8_G8B8_420_UNORM:
55
return true;
56
57
default:
58
break;
59
}
60
61
switch (fd6_pipe2color(pfmt)) {
62
case FMT6_10_10_10_2_UINT:
63
case FMT6_10_10_10_2_UNORM_DEST:
64
case FMT6_11_11_10_FLOAT:
65
case FMT6_16_FLOAT:
66
case FMT6_16_16_16_16_FLOAT:
67
case FMT6_16_16_16_16_SINT:
68
case FMT6_16_16_16_16_UINT:
69
case FMT6_16_16_FLOAT:
70
case FMT6_16_16_SINT:
71
case FMT6_16_16_UINT:
72
case FMT6_16_SINT:
73
case FMT6_16_UINT:
74
case FMT6_32_32_32_32_SINT:
75
case FMT6_32_32_32_32_UINT:
76
case FMT6_32_32_SINT:
77
case FMT6_32_32_UINT:
78
case FMT6_5_6_5_UNORM:
79
case FMT6_8_8_8_8_SINT:
80
case FMT6_8_8_8_8_UINT:
81
case FMT6_8_8_8_8_UNORM:
82
case FMT6_8_8_8_X8_UNORM:
83
case FMT6_8_8_SINT:
84
case FMT6_8_8_UINT:
85
case FMT6_8_8_UNORM:
86
case FMT6_Z24_UNORM_S8_UINT:
87
case FMT6_Z24_UNORM_S8_UINT_AS_R8G8B8A8:
88
return true;
89
case FMT6_8_UNORM:
90
return info->a6xx.has_8bpp_ubwc;
91
default:
92
return false;
93
}
94
}
95
96
static bool
97
can_do_ubwc(struct pipe_resource *prsc)
98
{
99
/* limit things to simple single level 2d for now: */
100
if ((prsc->depth0 != 1) || (prsc->array_size != 1) ||
101
(prsc->last_level != 0))
102
return false;
103
if (prsc->target != PIPE_TEXTURE_2D)
104
return false;
105
if (!ok_ubwc_format(prsc->screen, prsc->format))
106
return false;
107
return true;
108
}
109
110
static bool
111
is_norm(enum pipe_format format)
112
{
113
const struct util_format_description *desc = util_format_description(format);
114
115
return desc->is_snorm || desc->is_unorm;
116
}
117
118
static bool
119
valid_format_cast(struct fd_resource *rsc, enum pipe_format format)
120
{
121
/* Special case "casting" format in hw: */
122
if (format == PIPE_FORMAT_Z24_UNORM_S8_UINT_AS_R8G8B8A8)
123
return true;
124
125
/* For some color values (just "solid white") compression metadata maps to
126
* different pixel values for uint/sint vs unorm/snorm, so we can't reliably
127
* "cast" u/snorm to u/sint and visa versa:
128
*/
129
if (is_norm(format) != is_norm(rsc->b.b.format))
130
return false;
131
132
/* The UBWC formats can be re-interpreted so long as the components
133
* have the same # of bits
134
*/
135
for (unsigned i = 0; i < 4; i++) {
136
unsigned sb, db;
137
138
sb = util_format_get_component_bits(rsc->b.b.format, UTIL_FORMAT_COLORSPACE_RGB, i);
139
db = util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, i);
140
141
if (sb != db)
142
return false;
143
}
144
145
return true;
146
}
147
148
/**
149
* R8G8 have a different block width/height and height alignment from other
150
* formats that would normally be compatible (like R16), and so if we are
151
* trying to, for example, sample R16 as R8G8 we need to demote to linear.
152
*/
153
static bool
154
is_r8g8(enum pipe_format format)
155
{
156
return (util_format_get_blocksize(format) == 2) &&
157
(util_format_get_nr_components(format) == 2);
158
}
159
160
/**
161
* Ensure the rsc is in an ok state to be used with the specified format.
162
* This handles the case of UBWC buffers used with non-UBWC compatible
163
* formats, by triggering an uncompress.
164
*/
165
void
166
fd6_validate_format(struct fd_context *ctx, struct fd_resource *rsc,
167
enum pipe_format format)
168
{
169
enum pipe_format orig_format = rsc->b.b.format;
170
171
tc_assert_driver_thread(ctx->tc);
172
173
if (orig_format == format)
174
return;
175
176
if (rsc->layout.tile_mode && (is_r8g8(orig_format) != is_r8g8(format))) {
177
perf_debug_ctx(ctx,
178
"%" PRSC_FMT ": demoted to linear+uncompressed due to use as %s",
179
PRSC_ARGS(&rsc->b.b), util_format_short_name(format));
180
181
fd_resource_uncompress(ctx, rsc, true);
182
return;
183
}
184
185
if (!rsc->layout.ubwc)
186
return;
187
188
if (ok_ubwc_format(rsc->b.b.screen, format) && valid_format_cast(rsc, format))
189
return;
190
191
perf_debug_ctx(ctx,
192
"%" PRSC_FMT ": demoted to uncompressed due to use as %s",
193
PRSC_ARGS(&rsc->b.b), util_format_short_name(format));
194
195
fd_resource_uncompress(ctx, rsc, false);
196
}
197
198
static void
199
setup_lrz(struct fd_resource *rsc)
200
{
201
struct fd_screen *screen = fd_screen(rsc->b.b.screen);
202
unsigned width0 = rsc->b.b.width0;
203
unsigned height0 = rsc->b.b.height0;
204
205
/* LRZ buffer is super-sampled: */
206
switch (rsc->b.b.nr_samples) {
207
case 4:
208
width0 *= 2;
209
FALLTHROUGH;
210
case 2:
211
height0 *= 2;
212
}
213
214
unsigned lrz_pitch = align(DIV_ROUND_UP(width0, 8), 32);
215
unsigned lrz_height = align(DIV_ROUND_UP(height0, 8), 16);
216
217
unsigned size = lrz_pitch * lrz_height * 2;
218
219
rsc->lrz_height = lrz_height;
220
rsc->lrz_width = lrz_pitch;
221
rsc->lrz_pitch = lrz_pitch;
222
rsc->lrz = fd_bo_new(screen->dev, size, 0, "lrz");
223
}
224
225
static uint32_t
226
fd6_setup_slices(struct fd_resource *rsc)
227
{
228
struct pipe_resource *prsc = &rsc->b.b;
229
230
if (!FD_DBG(NOLRZ) && has_depth(rsc->b.b.format))
231
setup_lrz(rsc);
232
233
if (rsc->layout.ubwc && !ok_ubwc_format(rsc->b.b.screen, rsc->b.b.format))
234
rsc->layout.ubwc = false;
235
236
fdl6_layout(&rsc->layout, prsc->format, fd_resource_nr_samples(prsc),
237
prsc->width0, prsc->height0, prsc->depth0, prsc->last_level + 1,
238
prsc->array_size, prsc->target == PIPE_TEXTURE_3D, NULL);
239
240
return rsc->layout.size;
241
}
242
243
static int
244
fill_ubwc_buffer_sizes(struct fd_resource *rsc)
245
{
246
struct pipe_resource *prsc = &rsc->b.b;
247
struct fdl_explicit_layout explicit = {
248
.offset = rsc->layout.slices[0].offset,
249
.pitch = rsc->layout.pitch0,
250
};
251
252
if (!can_do_ubwc(prsc))
253
return -1;
254
255
rsc->layout.ubwc = true;
256
rsc->layout.tile_mode = TILE6_3;
257
258
if (!fdl6_layout(&rsc->layout, prsc->format, fd_resource_nr_samples(prsc),
259
prsc->width0, prsc->height0, prsc->depth0,
260
prsc->last_level + 1, prsc->array_size, false, &explicit))
261
return -1;
262
263
if (rsc->layout.size > fd_bo_size(rsc->bo))
264
return -1;
265
266
return 0;
267
}
268
269
static int
270
fd6_layout_resource_for_modifier(struct fd_resource *rsc, uint64_t modifier)
271
{
272
switch (modifier) {
273
case DRM_FORMAT_MOD_QCOM_COMPRESSED:
274
return fill_ubwc_buffer_sizes(rsc);
275
case DRM_FORMAT_MOD_LINEAR:
276
if (can_do_ubwc(&rsc->b.b)) {
277
perf_debug("%" PRSC_FMT
278
": not UBWC: imported with DRM_FORMAT_MOD_LINEAR!",
279
PRSC_ARGS(&rsc->b.b));
280
}
281
return 0;
282
case DRM_FORMAT_MOD_INVALID:
283
if (can_do_ubwc(&rsc->b.b)) {
284
perf_debug("%" PRSC_FMT
285
": not UBWC: imported with DRM_FORMAT_MOD_INVALID!",
286
PRSC_ARGS(&rsc->b.b));
287
}
288
return 0;
289
default:
290
return -1;
291
}
292
}
293
294
static const uint64_t supported_modifiers[] = {
295
DRM_FORMAT_MOD_LINEAR,
296
DRM_FORMAT_MOD_QCOM_COMPRESSED,
297
};
298
299
void
300
fd6_resource_screen_init(struct pipe_screen *pscreen)
301
{
302
struct fd_screen *screen = fd_screen(pscreen);
303
304
screen->setup_slices = fd6_setup_slices;
305
screen->layout_resource_for_modifier = fd6_layout_resource_for_modifier;
306
screen->supported_modifiers = supported_modifiers;
307
screen->num_supported_modifiers = ARRAY_SIZE(supported_modifiers);
308
}
309
310