Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/intel/isl/isl_emit_depth_stencil.c
4547 views
1
/*
2
* Copyright 2016 Intel Corporation
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
13
* Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
* IN THE SOFTWARE.
22
*/
23
24
#include <stdint.h>
25
26
#define __gen_address_type uint64_t
27
#define __gen_user_data void
28
29
static uint64_t
30
__gen_combine_address(__attribute__((unused)) void *data,
31
__attribute__((unused)) void *loc, uint64_t addr,
32
uint32_t delta)
33
{
34
return addr + delta;
35
}
36
37
#include "genxml/gen_macros.h"
38
#include "genxml/genX_pack.h"
39
40
#include "isl_priv.h"
41
42
static const uint32_t isl_encode_ds_surftype[] = {
43
#if GFX_VER >= 9
44
/* From the SKL PRM, "3DSTATE_DEPTH_STENCIL::SurfaceType":
45
*
46
* "If depth/stencil is enabled with 1D render target, depth/stencil
47
* surface type needs to be set to 2D surface type and height set to 1.
48
* Depth will use (legacy) TileY and stencil will use TileW. For this
49
* case only, the Surface Type of the depth buffer can be 2D while the
50
* Surface Type of the render target(s) are 1D, representing an
51
* exception to a programming note above.
52
*/
53
[ISL_SURF_DIM_1D] = SURFTYPE_2D,
54
#else
55
[ISL_SURF_DIM_1D] = SURFTYPE_1D,
56
#endif
57
[ISL_SURF_DIM_2D] = SURFTYPE_2D,
58
[ISL_SURF_DIM_3D] = SURFTYPE_3D,
59
};
60
61
void
62
isl_genX(emit_depth_stencil_hiz_s)(const struct isl_device *dev, void *batch,
63
const struct isl_depth_stencil_hiz_emit_info *restrict info)
64
{
65
struct GENX(3DSTATE_DEPTH_BUFFER) db = {
66
GENX(3DSTATE_DEPTH_BUFFER_header),
67
};
68
69
if (info->depth_surf) {
70
db.SurfaceType = isl_encode_ds_surftype[info->depth_surf->dim];
71
db.SurfaceFormat = isl_surf_get_depth_format(dev, info->depth_surf);
72
db.Width = info->depth_surf->logical_level0_px.width - 1;
73
db.Height = info->depth_surf->logical_level0_px.height - 1;
74
if (db.SurfaceType == SURFTYPE_3D)
75
db.Depth = info->depth_surf->logical_level0_px.depth - 1;
76
} else if (info->stencil_surf) {
77
db.SurfaceType = isl_encode_ds_surftype[info->stencil_surf->dim];
78
db.SurfaceFormat = D32_FLOAT;
79
db.Width = info->stencil_surf->logical_level0_px.width - 1;
80
db.Height = info->stencil_surf->logical_level0_px.height - 1;
81
if (db.SurfaceType == SURFTYPE_3D)
82
db.Depth = info->stencil_surf->logical_level0_px.depth - 1;
83
} else {
84
db.SurfaceType = SURFTYPE_NULL;
85
db.SurfaceFormat = D32_FLOAT;
86
}
87
88
if (info->depth_surf || info->stencil_surf) {
89
/* These are based entirely on the view */
90
db.RenderTargetViewExtent = info->view->array_len - 1;
91
db.LOD = info->view->base_level;
92
db.MinimumArrayElement = info->view->base_array_layer;
93
94
/* From the Haswell PRM docs for 3DSTATE_DEPTH_BUFFER::Depth
95
*
96
* "This field specifies the total number of levels for a volume
97
* texture or the number of array elements allowed to be accessed
98
* starting at the Minimum Array Element for arrayed surfaces. If the
99
* volume texture is MIP-mapped, this field specifies the depth of
100
* the base MIP level."
101
*
102
* For 3D surfaces, we set it to the correct depth above. For non-3D
103
* surfaces, this is the same as RenderTargetViewExtent.
104
*/
105
if (db.SurfaceType != SURFTYPE_3D)
106
db.Depth = db.RenderTargetViewExtent;
107
}
108
109
if (info->depth_surf) {
110
#if GFX_VER >= 7
111
db.DepthWriteEnable = true;
112
#endif
113
db.SurfaceBaseAddress = info->depth_address;
114
#if GFX_VER >= 6
115
db.MOCS = info->mocs;
116
#endif
117
118
#if GFX_VER <= 6
119
db.TiledSurface = info->depth_surf->tiling != ISL_TILING_LINEAR;
120
db.TileWalk = info->depth_surf->tiling == ISL_TILING_Y0 ? TILEWALK_YMAJOR :
121
TILEWALK_XMAJOR;
122
db.MIPMapLayoutMode = MIPLAYOUT_BELOW;
123
#endif
124
125
db.SurfacePitch = info->depth_surf->row_pitch_B - 1;
126
#if GFX_VER >= 8
127
db.SurfaceQPitch =
128
isl_surf_get_array_pitch_el_rows(info->depth_surf) >> 2;
129
#endif
130
131
#if GFX_VER >= 12
132
db.ControlSurfaceEnable = db.DepthBufferCompressionEnable =
133
isl_aux_usage_has_ccs(info->hiz_usage);
134
#endif
135
}
136
137
#if GFX_VER == 5 || GFX_VER == 6
138
const bool separate_stencil =
139
info->stencil_surf && info->stencil_surf->format == ISL_FORMAT_R8_UINT;
140
if (separate_stencil || info->hiz_usage == ISL_AUX_USAGE_HIZ) {
141
assert(ISL_DEV_USE_SEPARATE_STENCIL(dev));
142
db.SeparateStencilBufferEnable = true;
143
db.HierarchicalDepthBufferEnable = true;
144
}
145
#endif
146
147
#if GFX_VER >= 6
148
struct GENX(3DSTATE_STENCIL_BUFFER) sb = {
149
GENX(3DSTATE_STENCIL_BUFFER_header),
150
};
151
#else
152
# define sb db
153
#endif
154
155
if (info->stencil_surf) {
156
#if GFX_VER >= 7 && GFX_VER < 12
157
db.StencilWriteEnable = true;
158
#endif
159
#if GFX_VER >= 12
160
sb.StencilWriteEnable = true;
161
sb.SurfaceType = SURFTYPE_2D;
162
sb.Width = info->stencil_surf->logical_level0_px.width - 1;
163
sb.Height = info->stencil_surf->logical_level0_px.height - 1;
164
sb.Depth = sb.RenderTargetViewExtent = info->view->array_len - 1;
165
sb.SurfLOD = info->view->base_level;
166
sb.MinimumArrayElement = info->view->base_array_layer;
167
assert(info->stencil_aux_usage == ISL_AUX_USAGE_NONE ||
168
info->stencil_aux_usage == ISL_AUX_USAGE_STC_CCS);
169
sb.StencilCompressionEnable =
170
info->stencil_aux_usage == ISL_AUX_USAGE_STC_CCS;
171
sb.ControlSurfaceEnable = sb.StencilCompressionEnable;
172
#elif GFX_VERx10 >= 75
173
sb.StencilBufferEnable = true;
174
#endif
175
sb.SurfaceBaseAddress = info->stencil_address;
176
#if GFX_VER >= 6
177
sb.MOCS = info->mocs;
178
#endif
179
sb.SurfacePitch = info->stencil_surf->row_pitch_B - 1;
180
#if GFX_VER >= 8
181
sb.SurfaceQPitch =
182
isl_surf_get_array_pitch_el_rows(info->stencil_surf) >> 2;
183
#endif
184
} else {
185
#if GFX_VER >= 12
186
sb.SurfaceType = SURFTYPE_NULL;
187
188
/* The docs seem to indicate that if surf-type is null, then we may need
189
* to match the depth-buffer value for `Depth`. It may be a
190
* documentation bug, since the other fields don't require this.
191
*
192
* TODO: Confirm documentation and remove seeting of `Depth` if not
193
* required.
194
*/
195
sb.Depth = db.Depth;
196
#endif
197
}
198
199
#if GFX_VER >= 6
200
struct GENX(3DSTATE_HIER_DEPTH_BUFFER) hiz = {
201
GENX(3DSTATE_HIER_DEPTH_BUFFER_header),
202
};
203
struct GENX(3DSTATE_CLEAR_PARAMS) clear = {
204
GENX(3DSTATE_CLEAR_PARAMS_header),
205
};
206
207
assert(info->hiz_usage == ISL_AUX_USAGE_NONE ||
208
isl_aux_usage_has_hiz(info->hiz_usage));
209
if (isl_aux_usage_has_hiz(info->hiz_usage)) {
210
assert(GFX_VER >= 12 || info->hiz_usage == ISL_AUX_USAGE_HIZ);
211
db.HierarchicalDepthBufferEnable = true;
212
213
hiz.SurfaceBaseAddress = info->hiz_address;
214
hiz.MOCS = info->mocs;
215
hiz.SurfacePitch = info->hiz_surf->row_pitch_B - 1;
216
#if GFX_VER >= 12
217
hiz.HierarchicalDepthBufferWriteThruEnable =
218
info->hiz_usage == ISL_AUX_USAGE_HIZ_CCS_WT;
219
220
/* The bspec docs for this bit are fairly unclear about exactly what is
221
* and isn't supported with HiZ write-through. It's fairly clear that
222
* you can't sample from a multisampled depth buffer with CCS. This
223
* limitation isn't called out explicitly but the docs for the CCS_E
224
* value of RENDER_SURFACE_STATE::AuxiliarySurfaceMode say:
225
*
226
* "If Number of multisamples > 1, programming this value means MSAA
227
* compression is enabled for that surface. Auxillary surface is MSC
228
* with tile y."
229
*
230
* Since this interpretation ignores whether the surface is
231
* depth/stencil or not and since multisampled depth buffers use
232
* ISL_MSAA_LAYOUT_INTERLEAVED which is incompatible with MCS
233
* compression, this means that we can't even specify MSAA depth CCS in
234
* RENDER_SURFACE_STATE::AuxiliarySurfaceMode. The BSpec also says, for
235
* 3DSTATE_HIER_DEPTH_BUFFER::HierarchicalDepthBufferWriteThruEnable,
236
*
237
* "This bit must NOT be set for >1x MSAA modes, since sampler
238
* doesn't support sampling from >1x MSAA depth buffer."
239
*
240
* Again, this is all focused around what the sampler can do and not
241
* what the depth hardware can do.
242
*
243
* Reading even more internal docs which can't be quoted here makes it
244
* pretty clear that, even if it's not currently called out in the
245
* BSpec, HiZ+CCS write-through isn't intended to work with MSAA and we
246
* shouldn't try to use it. Treat it as if it's disallowed even if the
247
* BSpec doesn't explicitly document that.
248
*/
249
if (hiz.HierarchicalDepthBufferWriteThruEnable)
250
assert(info->depth_surf->samples == 1);
251
#endif
252
253
#if GFX_VER >= 8
254
/* From the SKL PRM Vol2a:
255
*
256
* The interpretation of this field is dependent on Surface Type
257
* as follows:
258
* - SURFTYPE_1D: distance in pixels between array slices
259
* - SURFTYPE_2D/CUBE: distance in rows between array slices
260
* - SURFTYPE_3D: distance in rows between R - slices
261
*
262
* Unfortunately, the docs aren't 100% accurate here. They fail to
263
* mention that the 1-D rule only applies to linear 1-D images.
264
* Since depth and HiZ buffers are always tiled, they are treated as
265
* 2-D images. Prior to Sky Lake, this field is always in rows.
266
*/
267
hiz.SurfaceQPitch =
268
isl_surf_get_array_pitch_sa_rows(info->hiz_surf) >> 2;
269
#endif
270
271
clear.DepthClearValueValid = true;
272
#if GFX_VER >= 8
273
clear.DepthClearValue = info->depth_clear_value;
274
#else
275
switch (info->depth_surf->format) {
276
case ISL_FORMAT_R32_FLOAT: {
277
union { float f; uint32_t u; } fu;
278
fu.f = info->depth_clear_value;
279
clear.DepthClearValue = fu.u;
280
break;
281
}
282
case ISL_FORMAT_R24_UNORM_X8_TYPELESS:
283
clear.DepthClearValue = info->depth_clear_value * ((1u << 24) - 1);
284
break;
285
case ISL_FORMAT_R16_UNORM:
286
clear.DepthClearValue = info->depth_clear_value * ((1u << 16) - 1);
287
break;
288
default:
289
unreachable("Invalid depth type");
290
}
291
#endif
292
}
293
#endif /* GFX_VER >= 6 */
294
295
/* Pack everything into the batch */
296
uint32_t *dw = batch;
297
GENX(3DSTATE_DEPTH_BUFFER_pack)(NULL, dw, &db);
298
dw += GENX(3DSTATE_DEPTH_BUFFER_length);
299
300
#if GFX_VER >= 6
301
GENX(3DSTATE_STENCIL_BUFFER_pack)(NULL, dw, &sb);
302
dw += GENX(3DSTATE_STENCIL_BUFFER_length);
303
304
GENX(3DSTATE_HIER_DEPTH_BUFFER_pack)(NULL, dw, &hiz);
305
dw += GENX(3DSTATE_HIER_DEPTH_BUFFER_length);
306
307
#if GFX_VERx10 == 120
308
/* Wa_14010455700
309
*
310
* To avoid sporadic corruptions “Set 0x7010[9] when Depth Buffer Surface
311
* Format is D16_UNORM , surface type is not NULL & 1X_MSAA”.
312
*/
313
bool enable_14010455700 =
314
info->depth_surf && info->depth_surf->samples == 1 &&
315
db.SurfaceType != SURFTYPE_NULL && db.SurfaceFormat == D16_UNORM;
316
struct GENX(COMMON_SLICE_CHICKEN1) chicken1 = {
317
.HIZPlaneOptimizationdisablebit = enable_14010455700,
318
.HIZPlaneOptimizationdisablebitMask = true,
319
};
320
uint32_t chicken1_dw;
321
GENX(COMMON_SLICE_CHICKEN1_pack)(NULL, &chicken1_dw, &chicken1);
322
323
struct GENX(MI_LOAD_REGISTER_IMM) lri = {
324
GENX(MI_LOAD_REGISTER_IMM_header),
325
.RegisterOffset = GENX(COMMON_SLICE_CHICKEN1_num),
326
.DataDWord = chicken1_dw,
327
};
328
GENX(MI_LOAD_REGISTER_IMM_pack)(NULL, dw, &lri);
329
dw += GENX(MI_LOAD_REGISTER_IMM_length);
330
331
/* Wa_1806527549
332
*
333
* Set HIZ_CHICKEN (7018h) bit 13 = 1 when depth buffer is D16_UNORM.
334
*/
335
struct GENX(HIZ_CHICKEN) hiz_chicken = {
336
.HZDepthTestLEGEOptimizationDisable = db.SurfaceFormat == D16_UNORM,
337
.HZDepthTestLEGEOptimizationDisableMask = true,
338
};
339
uint32_t hiz_chicken_dw;
340
GENX(HIZ_CHICKEN_pack)(NULL, &hiz_chicken_dw, &hiz_chicken);
341
342
struct GENX(MI_LOAD_REGISTER_IMM) lri2 = {
343
GENX(MI_LOAD_REGISTER_IMM_header),
344
.RegisterOffset = GENX(HIZ_CHICKEN_num),
345
.DataDWord = hiz_chicken_dw,
346
};
347
GENX(MI_LOAD_REGISTER_IMM_pack)(NULL, dw, &lri2);
348
dw += GENX(MI_LOAD_REGISTER_IMM_length);
349
#endif
350
351
GENX(3DSTATE_CLEAR_PARAMS_pack)(NULL, dw, &clear);
352
dw += GENX(3DSTATE_CLEAR_PARAMS_length);
353
#endif
354
}
355
356