1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2022 Intel Corporation
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker *
11*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker * Software.
14*61046927SAndroid Build Coastguard Worker *
15*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker */
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker #include <anv_private.h>
25*61046927SAndroid Build Coastguard Worker
26*61046927SAndroid Build Coastguard Worker /* Sparse binding handling.
27*61046927SAndroid Build Coastguard Worker *
28*61046927SAndroid Build Coastguard Worker * There is one main structure passed around all over this file:
29*61046927SAndroid Build Coastguard Worker *
30*61046927SAndroid Build Coastguard Worker * - struct anv_sparse_binding_data: every resource (VkBuffer or VkImage) has
31*61046927SAndroid Build Coastguard Worker * a pointer to an instance of this structure. It contains the virtual
32*61046927SAndroid Build Coastguard Worker * memory address (VMA) used by the binding operations (which is different
33*61046927SAndroid Build Coastguard Worker * from the VMA used by the anv_bo it's bound to) and the VMA range size. We
34*61046927SAndroid Build Coastguard Worker * do not keep record of our our list of bindings (which ranges were bound
35*61046927SAndroid Build Coastguard Worker * to which buffers).
36*61046927SAndroid Build Coastguard Worker */
37*61046927SAndroid Build Coastguard Worker
38*61046927SAndroid Build Coastguard Worker __attribute__((format(printf, 1, 2)))
39*61046927SAndroid Build Coastguard Worker static void
sparse_debug(const char * format,...)40*61046927SAndroid Build Coastguard Worker sparse_debug(const char *format, ...)
41*61046927SAndroid Build Coastguard Worker {
42*61046927SAndroid Build Coastguard Worker if (!INTEL_DEBUG(DEBUG_SPARSE))
43*61046927SAndroid Build Coastguard Worker return;
44*61046927SAndroid Build Coastguard Worker
45*61046927SAndroid Build Coastguard Worker va_list args;
46*61046927SAndroid Build Coastguard Worker va_start(args, format);
47*61046927SAndroid Build Coastguard Worker vfprintf(stderr, format, args);
48*61046927SAndroid Build Coastguard Worker va_end(args);
49*61046927SAndroid Build Coastguard Worker }
50*61046927SAndroid Build Coastguard Worker
51*61046927SAndroid Build Coastguard Worker static void
dump_anv_vm_bind(struct anv_device * device,const struct anv_vm_bind * bind)52*61046927SAndroid Build Coastguard Worker dump_anv_vm_bind(struct anv_device *device,
53*61046927SAndroid Build Coastguard Worker const struct anv_vm_bind *bind)
54*61046927SAndroid Build Coastguard Worker {
55*61046927SAndroid Build Coastguard Worker sparse_debug("[%s] ", bind->op == ANV_VM_BIND ? " bind " : "unbind");
56*61046927SAndroid Build Coastguard Worker
57*61046927SAndroid Build Coastguard Worker if (bind->bo)
58*61046927SAndroid Build Coastguard Worker sparse_debug("bo:%04u ", bind->bo->gem_handle);
59*61046927SAndroid Build Coastguard Worker else
60*61046927SAndroid Build Coastguard Worker sparse_debug("bo:---- ");
61*61046927SAndroid Build Coastguard Worker sparse_debug("address:%016"PRIx64" size:%08"PRIx64" "
62*61046927SAndroid Build Coastguard Worker "mem_offset:%08"PRIx64"\n",
63*61046927SAndroid Build Coastguard Worker bind->address, bind->size, bind->bo_offset);
64*61046927SAndroid Build Coastguard Worker }
65*61046927SAndroid Build Coastguard Worker
66*61046927SAndroid Build Coastguard Worker static void
dump_anv_image(struct anv_image * i)67*61046927SAndroid Build Coastguard Worker dump_anv_image(struct anv_image *i)
68*61046927SAndroid Build Coastguard Worker {
69*61046927SAndroid Build Coastguard Worker if (!INTEL_DEBUG(DEBUG_SPARSE))
70*61046927SAndroid Build Coastguard Worker return;
71*61046927SAndroid Build Coastguard Worker
72*61046927SAndroid Build Coastguard Worker sparse_debug("anv_image:\n");
73*61046927SAndroid Build Coastguard Worker sparse_debug("- format: %d\n", i->vk.format);
74*61046927SAndroid Build Coastguard Worker sparse_debug("- extent: [%d, %d, %d]\n",
75*61046927SAndroid Build Coastguard Worker i->vk.extent.width, i->vk.extent.height, i->vk.extent.depth);
76*61046927SAndroid Build Coastguard Worker sparse_debug("- mip_levels: %d array_layers: %d samples: %d\n",
77*61046927SAndroid Build Coastguard Worker i->vk.mip_levels, i->vk.array_layers, i->vk.samples);
78*61046927SAndroid Build Coastguard Worker sparse_debug("- n_planes: %d\n", i->n_planes);
79*61046927SAndroid Build Coastguard Worker sparse_debug("- disjoint: %d\n", i->disjoint);
80*61046927SAndroid Build Coastguard Worker }
81*61046927SAndroid Build Coastguard Worker
82*61046927SAndroid Build Coastguard Worker static void
dump_isl_surf(struct isl_surf * s)83*61046927SAndroid Build Coastguard Worker dump_isl_surf(struct isl_surf *s)
84*61046927SAndroid Build Coastguard Worker {
85*61046927SAndroid Build Coastguard Worker if (!INTEL_DEBUG(DEBUG_SPARSE))
86*61046927SAndroid Build Coastguard Worker return;
87*61046927SAndroid Build Coastguard Worker
88*61046927SAndroid Build Coastguard Worker sparse_debug("isl_surf:\n");
89*61046927SAndroid Build Coastguard Worker
90*61046927SAndroid Build Coastguard Worker const char *dim_s = s->dim == ISL_SURF_DIM_1D ? "1D" :
91*61046927SAndroid Build Coastguard Worker s->dim == ISL_SURF_DIM_2D ? "2D" :
92*61046927SAndroid Build Coastguard Worker s->dim == ISL_SURF_DIM_3D ? "3D" :
93*61046927SAndroid Build Coastguard Worker "(ERROR)";
94*61046927SAndroid Build Coastguard Worker sparse_debug("- dim: %s\n", dim_s);
95*61046927SAndroid Build Coastguard Worker sparse_debug("- tiling: %d (%s)\n", s->tiling,
96*61046927SAndroid Build Coastguard Worker isl_tiling_to_name(s->tiling));
97*61046927SAndroid Build Coastguard Worker sparse_debug("- format: %s\n", isl_format_get_short_name(s->format));
98*61046927SAndroid Build Coastguard Worker sparse_debug("- image_alignment_el: [%d, %d, %d]\n",
99*61046927SAndroid Build Coastguard Worker s->image_alignment_el.w, s->image_alignment_el.h,
100*61046927SAndroid Build Coastguard Worker s->image_alignment_el.d);
101*61046927SAndroid Build Coastguard Worker sparse_debug("- logical_level0_px: [%d, %d, %d, %d]\n",
102*61046927SAndroid Build Coastguard Worker s->logical_level0_px.w,
103*61046927SAndroid Build Coastguard Worker s->logical_level0_px.h,
104*61046927SAndroid Build Coastguard Worker s->logical_level0_px.d,
105*61046927SAndroid Build Coastguard Worker s->logical_level0_px.a);
106*61046927SAndroid Build Coastguard Worker sparse_debug("- phys_level0_sa: [%d, %d, %d, %d]\n",
107*61046927SAndroid Build Coastguard Worker s->phys_level0_sa.w,
108*61046927SAndroid Build Coastguard Worker s->phys_level0_sa.h,
109*61046927SAndroid Build Coastguard Worker s->phys_level0_sa.d,
110*61046927SAndroid Build Coastguard Worker s->phys_level0_sa.a);
111*61046927SAndroid Build Coastguard Worker sparse_debug("- levels: %d samples: %d\n", s->levels, s->samples);
112*61046927SAndroid Build Coastguard Worker sparse_debug("- size_B: %"PRIu64" alignment_B: %u\n",
113*61046927SAndroid Build Coastguard Worker s->size_B, s->alignment_B);
114*61046927SAndroid Build Coastguard Worker sparse_debug("- row_pitch_B: %u\n", s->row_pitch_B);
115*61046927SAndroid Build Coastguard Worker sparse_debug("- array_pitch_el_rows: %u\n", s->array_pitch_el_rows);
116*61046927SAndroid Build Coastguard Worker
117*61046927SAndroid Build Coastguard Worker const struct isl_format_layout *layout = isl_format_get_layout(s->format);
118*61046927SAndroid Build Coastguard Worker sparse_debug("- format layout:\n");
119*61046927SAndroid Build Coastguard Worker sparse_debug(" - format:%d bpb:%d bw:%d bh:%d bd:%d\n",
120*61046927SAndroid Build Coastguard Worker layout->format, layout->bpb, layout->bw, layout->bh,
121*61046927SAndroid Build Coastguard Worker layout->bd);
122*61046927SAndroid Build Coastguard Worker
123*61046927SAndroid Build Coastguard Worker struct isl_tile_info tile_info;
124*61046927SAndroid Build Coastguard Worker isl_surf_get_tile_info(s, &tile_info);
125*61046927SAndroid Build Coastguard Worker
126*61046927SAndroid Build Coastguard Worker sparse_debug("- tile info:\n");
127*61046927SAndroid Build Coastguard Worker sparse_debug(" - format_bpb: %d\n", tile_info.format_bpb);
128*61046927SAndroid Build Coastguard Worker sparse_debug(" - logical_extent_el: [%d, %d, %d, %d]\n",
129*61046927SAndroid Build Coastguard Worker tile_info.logical_extent_el.w,
130*61046927SAndroid Build Coastguard Worker tile_info.logical_extent_el.h,
131*61046927SAndroid Build Coastguard Worker tile_info.logical_extent_el.d,
132*61046927SAndroid Build Coastguard Worker tile_info.logical_extent_el.a);
133*61046927SAndroid Build Coastguard Worker sparse_debug(" - phys_extent_B: [%d, %d]\n",
134*61046927SAndroid Build Coastguard Worker tile_info.phys_extent_B.w,
135*61046927SAndroid Build Coastguard Worker tile_info.phys_extent_B.h);
136*61046927SAndroid Build Coastguard Worker }
137*61046927SAndroid Build Coastguard Worker
138*61046927SAndroid Build Coastguard Worker static VkOffset3D
vk_offset3d_px_to_el(const VkOffset3D offset_px,const struct isl_format_layout * layout)139*61046927SAndroid Build Coastguard Worker vk_offset3d_px_to_el(const VkOffset3D offset_px,
140*61046927SAndroid Build Coastguard Worker const struct isl_format_layout *layout)
141*61046927SAndroid Build Coastguard Worker {
142*61046927SAndroid Build Coastguard Worker return (VkOffset3D) {
143*61046927SAndroid Build Coastguard Worker .x = offset_px.x / layout->bw,
144*61046927SAndroid Build Coastguard Worker .y = offset_px.y / layout->bh,
145*61046927SAndroid Build Coastguard Worker .z = offset_px.z / layout->bd,
146*61046927SAndroid Build Coastguard Worker };
147*61046927SAndroid Build Coastguard Worker }
148*61046927SAndroid Build Coastguard Worker
149*61046927SAndroid Build Coastguard Worker static VkOffset3D
vk_offset3d_el_to_px(const VkOffset3D offset_el,const struct isl_format_layout * layout)150*61046927SAndroid Build Coastguard Worker vk_offset3d_el_to_px(const VkOffset3D offset_el,
151*61046927SAndroid Build Coastguard Worker const struct isl_format_layout *layout)
152*61046927SAndroid Build Coastguard Worker {
153*61046927SAndroid Build Coastguard Worker return (VkOffset3D) {
154*61046927SAndroid Build Coastguard Worker .x = offset_el.x * layout->bw,
155*61046927SAndroid Build Coastguard Worker .y = offset_el.y * layout->bh,
156*61046927SAndroid Build Coastguard Worker .z = offset_el.z * layout->bd,
157*61046927SAndroid Build Coastguard Worker };
158*61046927SAndroid Build Coastguard Worker }
159*61046927SAndroid Build Coastguard Worker
160*61046927SAndroid Build Coastguard Worker static VkExtent3D
vk_extent3d_px_to_el(const VkExtent3D extent_px,const struct isl_format_layout * layout)161*61046927SAndroid Build Coastguard Worker vk_extent3d_px_to_el(const VkExtent3D extent_px,
162*61046927SAndroid Build Coastguard Worker const struct isl_format_layout *layout)
163*61046927SAndroid Build Coastguard Worker {
164*61046927SAndroid Build Coastguard Worker return (VkExtent3D) {
165*61046927SAndroid Build Coastguard Worker .width = extent_px.width / layout->bw,
166*61046927SAndroid Build Coastguard Worker .height = extent_px.height / layout->bh,
167*61046927SAndroid Build Coastguard Worker .depth = extent_px.depth / layout->bd,
168*61046927SAndroid Build Coastguard Worker };
169*61046927SAndroid Build Coastguard Worker }
170*61046927SAndroid Build Coastguard Worker
171*61046927SAndroid Build Coastguard Worker static VkExtent3D
vk_extent3d_el_to_px(const VkExtent3D extent_el,const struct isl_format_layout * layout)172*61046927SAndroid Build Coastguard Worker vk_extent3d_el_to_px(const VkExtent3D extent_el,
173*61046927SAndroid Build Coastguard Worker const struct isl_format_layout *layout)
174*61046927SAndroid Build Coastguard Worker {
175*61046927SAndroid Build Coastguard Worker return (VkExtent3D) {
176*61046927SAndroid Build Coastguard Worker .width = extent_el.width * layout->bw,
177*61046927SAndroid Build Coastguard Worker .height = extent_el.height * layout->bh,
178*61046927SAndroid Build Coastguard Worker .depth = extent_el.depth * layout->bd,
179*61046927SAndroid Build Coastguard Worker };
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker
182*61046927SAndroid Build Coastguard Worker static bool
isl_tiling_supports_standard_block_shapes(enum isl_tiling tiling)183*61046927SAndroid Build Coastguard Worker isl_tiling_supports_standard_block_shapes(enum isl_tiling tiling)
184*61046927SAndroid Build Coastguard Worker {
185*61046927SAndroid Build Coastguard Worker return isl_tiling_is_64(tiling) ||
186*61046927SAndroid Build Coastguard Worker tiling == ISL_TILING_ICL_Ys ||
187*61046927SAndroid Build Coastguard Worker tiling == ISL_TILING_SKL_Ys;
188*61046927SAndroid Build Coastguard Worker }
189*61046927SAndroid Build Coastguard Worker
190*61046927SAndroid Build Coastguard Worker static uint32_t
isl_calc_tile_size(struct isl_tile_info * tile_info)191*61046927SAndroid Build Coastguard Worker isl_calc_tile_size(struct isl_tile_info *tile_info)
192*61046927SAndroid Build Coastguard Worker {
193*61046927SAndroid Build Coastguard Worker uint32_t tile_size = tile_info->phys_extent_B.w *
194*61046927SAndroid Build Coastguard Worker tile_info->phys_extent_B.h;
195*61046927SAndroid Build Coastguard Worker assert(tile_size == 64 * 1024 || tile_size == 4096 || tile_size == 1);
196*61046927SAndroid Build Coastguard Worker return tile_size;
197*61046927SAndroid Build Coastguard Worker }
198*61046927SAndroid Build Coastguard Worker
199*61046927SAndroid Build Coastguard Worker static const VkExtent3D block_shapes_2d_1sample[] = {
200*61046927SAndroid Build Coastguard Worker /* 8 bits: */ { .width = 256, .height = 256, .depth = 1 },
201*61046927SAndroid Build Coastguard Worker /* 16 bits: */ { .width = 256, .height = 128, .depth = 1 },
202*61046927SAndroid Build Coastguard Worker /* 32 bits: */ { .width = 128, .height = 128, .depth = 1 },
203*61046927SAndroid Build Coastguard Worker /* 64 bits: */ { .width = 128, .height = 64, .depth = 1 },
204*61046927SAndroid Build Coastguard Worker /* 128 bits: */ { .width = 64, .height = 64, .depth = 1 },
205*61046927SAndroid Build Coastguard Worker };
206*61046927SAndroid Build Coastguard Worker static const VkExtent3D block_shapes_3d_1sample[] = {
207*61046927SAndroid Build Coastguard Worker /* 8 bits: */ { .width = 64, .height = 32, .depth = 32 },
208*61046927SAndroid Build Coastguard Worker /* 16 bits: */ { .width = 32, .height = 32, .depth = 32 },
209*61046927SAndroid Build Coastguard Worker /* 32 bits: */ { .width = 32, .height = 32, .depth = 16 },
210*61046927SAndroid Build Coastguard Worker /* 64 bits: */ { .width = 32, .height = 16, .depth = 16 },
211*61046927SAndroid Build Coastguard Worker /* 128 bits: */ { .width = 16, .height = 16, .depth = 16 },
212*61046927SAndroid Build Coastguard Worker };
213*61046927SAndroid Build Coastguard Worker static const VkExtent3D block_shapes_2d_2samples[] = {
214*61046927SAndroid Build Coastguard Worker /* 8 bits: */ { .width = 128, .height = 256, .depth = 1 },
215*61046927SAndroid Build Coastguard Worker /* 16 bits: */ { .width = 128, .height = 128, .depth = 1 },
216*61046927SAndroid Build Coastguard Worker /* 32 bits: */ { .width = 64, .height = 128, .depth = 1 },
217*61046927SAndroid Build Coastguard Worker /* 64 bits: */ { .width = 64, .height = 64, .depth = 1 },
218*61046927SAndroid Build Coastguard Worker /* 128 bits: */ { .width = 32, .height = 64, .depth = 1 },
219*61046927SAndroid Build Coastguard Worker };
220*61046927SAndroid Build Coastguard Worker static const VkExtent3D block_shapes_2d_4samples[] = {
221*61046927SAndroid Build Coastguard Worker /* 8 bits: */ { .width = 128, .height = 128, .depth = 1 },
222*61046927SAndroid Build Coastguard Worker /* 16 bits: */ { .width = 128, .height = 64, .depth = 1 },
223*61046927SAndroid Build Coastguard Worker /* 32 bits: */ { .width = 64, .height = 64, .depth = 1 },
224*61046927SAndroid Build Coastguard Worker /* 64 bits: */ { .width = 64, .height = 32, .depth = 1 },
225*61046927SAndroid Build Coastguard Worker /* 128 bits: */ { .width = 32, .height = 32, .depth = 1 },
226*61046927SAndroid Build Coastguard Worker };
227*61046927SAndroid Build Coastguard Worker static const VkExtent3D block_shapes_2d_8samples[] = {
228*61046927SAndroid Build Coastguard Worker /* 8 bits: */ { .width = 64, .height = 128, .depth = 1 },
229*61046927SAndroid Build Coastguard Worker /* 16 bits: */ { .width = 64, .height = 64, .depth = 1 },
230*61046927SAndroid Build Coastguard Worker /* 32 bits: */ { .width = 32, .height = 64, .depth = 1 },
231*61046927SAndroid Build Coastguard Worker /* 64 bits: */ { .width = 32, .height = 32, .depth = 1 },
232*61046927SAndroid Build Coastguard Worker /* 128 bits: */ { .width = 16, .height = 32, .depth = 1 },
233*61046927SAndroid Build Coastguard Worker };
234*61046927SAndroid Build Coastguard Worker static const VkExtent3D block_shapes_2d_16samples[] = {
235*61046927SAndroid Build Coastguard Worker /* 8 bits: */ { .width = 64, .height = 64, .depth = 1 },
236*61046927SAndroid Build Coastguard Worker /* 16 bits: */ { .width = 64, .height = 32, .depth = 1 },
237*61046927SAndroid Build Coastguard Worker /* 32 bits: */ { .width = 32, .height = 32, .depth = 1 },
238*61046927SAndroid Build Coastguard Worker /* 64 bits: */ { .width = 32, .height = 16, .depth = 1 },
239*61046927SAndroid Build Coastguard Worker /* 128 bits: */ { .width = 16, .height = 16, .depth = 1 },
240*61046927SAndroid Build Coastguard Worker };
241*61046927SAndroid Build Coastguard Worker
242*61046927SAndroid Build Coastguard Worker static VkExtent3D
anv_sparse_get_standard_image_block_shape(enum isl_format format,VkImageType image_type,VkSampleCountFlagBits samples,uint16_t texel_size)243*61046927SAndroid Build Coastguard Worker anv_sparse_get_standard_image_block_shape(enum isl_format format,
244*61046927SAndroid Build Coastguard Worker VkImageType image_type,
245*61046927SAndroid Build Coastguard Worker VkSampleCountFlagBits samples,
246*61046927SAndroid Build Coastguard Worker uint16_t texel_size)
247*61046927SAndroid Build Coastguard Worker {
248*61046927SAndroid Build Coastguard Worker const struct isl_format_layout *layout = isl_format_get_layout(format);
249*61046927SAndroid Build Coastguard Worker VkExtent3D block_shape = { .width = 0, .height = 0, .depth = 0 };
250*61046927SAndroid Build Coastguard Worker
251*61046927SAndroid Build Coastguard Worker int table_idx = ffs(texel_size) - 4;
252*61046927SAndroid Build Coastguard Worker
253*61046927SAndroid Build Coastguard Worker switch (samples) {
254*61046927SAndroid Build Coastguard Worker case VK_SAMPLE_COUNT_1_BIT:
255*61046927SAndroid Build Coastguard Worker switch (image_type) {
256*61046927SAndroid Build Coastguard Worker case VK_IMAGE_TYPE_1D:
257*61046927SAndroid Build Coastguard Worker /* 1D images don't have a standard block format. */
258*61046927SAndroid Build Coastguard Worker assert(false);
259*61046927SAndroid Build Coastguard Worker break;
260*61046927SAndroid Build Coastguard Worker case VK_IMAGE_TYPE_2D:
261*61046927SAndroid Build Coastguard Worker block_shape = block_shapes_2d_1sample[table_idx];
262*61046927SAndroid Build Coastguard Worker break;
263*61046927SAndroid Build Coastguard Worker case VK_IMAGE_TYPE_3D:
264*61046927SAndroid Build Coastguard Worker block_shape = block_shapes_3d_1sample[table_idx];
265*61046927SAndroid Build Coastguard Worker break;
266*61046927SAndroid Build Coastguard Worker default:
267*61046927SAndroid Build Coastguard Worker fprintf(stderr, "unexpected image_type %d\n", image_type);
268*61046927SAndroid Build Coastguard Worker assert(false);
269*61046927SAndroid Build Coastguard Worker }
270*61046927SAndroid Build Coastguard Worker break;
271*61046927SAndroid Build Coastguard Worker case VK_SAMPLE_COUNT_2_BIT:
272*61046927SAndroid Build Coastguard Worker block_shape = block_shapes_2d_2samples[table_idx];
273*61046927SAndroid Build Coastguard Worker break;
274*61046927SAndroid Build Coastguard Worker case VK_SAMPLE_COUNT_4_BIT:
275*61046927SAndroid Build Coastguard Worker block_shape = block_shapes_2d_4samples[table_idx];
276*61046927SAndroid Build Coastguard Worker break;
277*61046927SAndroid Build Coastguard Worker case VK_SAMPLE_COUNT_8_BIT:
278*61046927SAndroid Build Coastguard Worker block_shape = block_shapes_2d_8samples[table_idx];
279*61046927SAndroid Build Coastguard Worker break;
280*61046927SAndroid Build Coastguard Worker case VK_SAMPLE_COUNT_16_BIT:
281*61046927SAndroid Build Coastguard Worker block_shape = block_shapes_2d_16samples[table_idx];
282*61046927SAndroid Build Coastguard Worker break;
283*61046927SAndroid Build Coastguard Worker default:
284*61046927SAndroid Build Coastguard Worker fprintf(stderr, "unexpected sample count: %d\n", samples);
285*61046927SAndroid Build Coastguard Worker assert(false);
286*61046927SAndroid Build Coastguard Worker }
287*61046927SAndroid Build Coastguard Worker
288*61046927SAndroid Build Coastguard Worker return vk_extent3d_el_to_px(block_shape, layout);
289*61046927SAndroid Build Coastguard Worker }
290*61046927SAndroid Build Coastguard Worker
291*61046927SAndroid Build Coastguard Worker /* Adds "bind_op" to the list in "submit", while also trying to check if we
292*61046927SAndroid Build Coastguard Worker * can just extend the last operation instead.
293*61046927SAndroid Build Coastguard Worker */
294*61046927SAndroid Build Coastguard Worker static VkResult
anv_sparse_submission_add(struct anv_device * device,struct anv_sparse_submission * submit,struct anv_vm_bind * bind_op)295*61046927SAndroid Build Coastguard Worker anv_sparse_submission_add(struct anv_device *device,
296*61046927SAndroid Build Coastguard Worker struct anv_sparse_submission *submit,
297*61046927SAndroid Build Coastguard Worker struct anv_vm_bind *bind_op)
298*61046927SAndroid Build Coastguard Worker {
299*61046927SAndroid Build Coastguard Worker struct anv_vm_bind *prev_bind = submit->binds_len == 0 ? NULL :
300*61046927SAndroid Build Coastguard Worker &submit->binds[submit->binds_len - 1];
301*61046927SAndroid Build Coastguard Worker
302*61046927SAndroid Build Coastguard Worker if (prev_bind &&
303*61046927SAndroid Build Coastguard Worker bind_op->op == prev_bind->op &&
304*61046927SAndroid Build Coastguard Worker bind_op->bo == prev_bind->bo &&
305*61046927SAndroid Build Coastguard Worker bind_op->address == prev_bind->address + prev_bind->size &&
306*61046927SAndroid Build Coastguard Worker (bind_op->bo_offset == prev_bind->bo_offset + prev_bind->size ||
307*61046927SAndroid Build Coastguard Worker prev_bind->bo == NULL)) {
308*61046927SAndroid Build Coastguard Worker prev_bind->size += bind_op->size;
309*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
310*61046927SAndroid Build Coastguard Worker }
311*61046927SAndroid Build Coastguard Worker
312*61046927SAndroid Build Coastguard Worker if (submit->binds_len < submit->binds_capacity) {
313*61046927SAndroid Build Coastguard Worker submit->binds[submit->binds_len++] = *bind_op;
314*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
315*61046927SAndroid Build Coastguard Worker }
316*61046927SAndroid Build Coastguard Worker
317*61046927SAndroid Build Coastguard Worker int new_capacity = MAX2(32, submit->binds_capacity * 2);
318*61046927SAndroid Build Coastguard Worker struct anv_vm_bind *new_binds =
319*61046927SAndroid Build Coastguard Worker vk_realloc(&device->vk.alloc, submit->binds,
320*61046927SAndroid Build Coastguard Worker new_capacity * sizeof(*new_binds), 8,
321*61046927SAndroid Build Coastguard Worker VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
322*61046927SAndroid Build Coastguard Worker if (!new_binds)
323*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
324*61046927SAndroid Build Coastguard Worker
325*61046927SAndroid Build Coastguard Worker new_binds[submit->binds_len] = *bind_op;
326*61046927SAndroid Build Coastguard Worker
327*61046927SAndroid Build Coastguard Worker submit->binds = new_binds;
328*61046927SAndroid Build Coastguard Worker submit->binds_len++;
329*61046927SAndroid Build Coastguard Worker submit->binds_capacity = new_capacity;
330*61046927SAndroid Build Coastguard Worker
331*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
332*61046927SAndroid Build Coastguard Worker }
333*61046927SAndroid Build Coastguard Worker
334*61046927SAndroid Build Coastguard Worker /* We really want to try to have all the page tables on as few BOs as possible
335*61046927SAndroid Build Coastguard Worker * to benefit from cache locality and to keep the i915.ko relocation lists
336*61046927SAndroid Build Coastguard Worker * small. On the other hand, we don't want to waste memory on unused space.
337*61046927SAndroid Build Coastguard Worker */
338*61046927SAndroid Build Coastguard Worker #define ANV_TRTT_PAGE_TABLE_BO_SIZE (2 * 1024 * 1024)
339*61046927SAndroid Build Coastguard Worker
340*61046927SAndroid Build Coastguard Worker static VkResult
trtt_make_page_table_bo(struct anv_device * device,struct anv_bo ** bo)341*61046927SAndroid Build Coastguard Worker trtt_make_page_table_bo(struct anv_device *device, struct anv_bo **bo)
342*61046927SAndroid Build Coastguard Worker {
343*61046927SAndroid Build Coastguard Worker VkResult result;
344*61046927SAndroid Build Coastguard Worker struct anv_trtt *trtt = &device->trtt;
345*61046927SAndroid Build Coastguard Worker
346*61046927SAndroid Build Coastguard Worker result = anv_device_alloc_bo(device, "trtt-page-table",
347*61046927SAndroid Build Coastguard Worker ANV_TRTT_PAGE_TABLE_BO_SIZE,
348*61046927SAndroid Build Coastguard Worker ANV_BO_ALLOC_INTERNAL,
349*61046927SAndroid Build Coastguard Worker 0 /* explicit_address */, bo);
350*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
351*61046927SAndroid Build Coastguard Worker return result;
352*61046927SAndroid Build Coastguard Worker
353*61046927SAndroid Build Coastguard Worker if (trtt->num_page_table_bos < trtt->page_table_bos_capacity) {
354*61046927SAndroid Build Coastguard Worker trtt->page_table_bos[trtt->num_page_table_bos++] = *bo;
355*61046927SAndroid Build Coastguard Worker } else {
356*61046927SAndroid Build Coastguard Worker
357*61046927SAndroid Build Coastguard Worker int new_capacity = MAX2(8, trtt->page_table_bos_capacity * 2);
358*61046927SAndroid Build Coastguard Worker struct anv_bo **new_page_table_bos =
359*61046927SAndroid Build Coastguard Worker vk_realloc(&device->vk.alloc, trtt->page_table_bos,
360*61046927SAndroid Build Coastguard Worker new_capacity * sizeof(*trtt->page_table_bos), 8,
361*61046927SAndroid Build Coastguard Worker VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
362*61046927SAndroid Build Coastguard Worker if (!new_page_table_bos) {
363*61046927SAndroid Build Coastguard Worker anv_device_release_bo(device, *bo);
364*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
365*61046927SAndroid Build Coastguard Worker }
366*61046927SAndroid Build Coastguard Worker
367*61046927SAndroid Build Coastguard Worker new_page_table_bos[trtt->num_page_table_bos] = *bo;
368*61046927SAndroid Build Coastguard Worker
369*61046927SAndroid Build Coastguard Worker trtt->page_table_bos = new_page_table_bos;
370*61046927SAndroid Build Coastguard Worker trtt->page_table_bos_capacity = new_capacity;
371*61046927SAndroid Build Coastguard Worker trtt->num_page_table_bos++;
372*61046927SAndroid Build Coastguard Worker }
373*61046927SAndroid Build Coastguard Worker
374*61046927SAndroid Build Coastguard Worker trtt->cur_page_table_bo = *bo;
375*61046927SAndroid Build Coastguard Worker trtt->next_page_table_bo_offset = 0;
376*61046927SAndroid Build Coastguard Worker
377*61046927SAndroid Build Coastguard Worker sparse_debug("new number of page table BOs: %d\n",
378*61046927SAndroid Build Coastguard Worker trtt->num_page_table_bos);
379*61046927SAndroid Build Coastguard Worker
380*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
381*61046927SAndroid Build Coastguard Worker }
382*61046927SAndroid Build Coastguard Worker
383*61046927SAndroid Build Coastguard Worker static VkResult
trtt_get_page_table_bo(struct anv_device * device,struct anv_bo ** bo,uint64_t * bo_addr)384*61046927SAndroid Build Coastguard Worker trtt_get_page_table_bo(struct anv_device *device, struct anv_bo **bo,
385*61046927SAndroid Build Coastguard Worker uint64_t *bo_addr)
386*61046927SAndroid Build Coastguard Worker {
387*61046927SAndroid Build Coastguard Worker struct anv_trtt *trtt = &device->trtt;
388*61046927SAndroid Build Coastguard Worker VkResult result;
389*61046927SAndroid Build Coastguard Worker
390*61046927SAndroid Build Coastguard Worker if (!trtt->cur_page_table_bo) {
391*61046927SAndroid Build Coastguard Worker result = trtt_make_page_table_bo(device, bo);
392*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
393*61046927SAndroid Build Coastguard Worker return result;
394*61046927SAndroid Build Coastguard Worker }
395*61046927SAndroid Build Coastguard Worker
396*61046927SAndroid Build Coastguard Worker *bo = trtt->cur_page_table_bo;
397*61046927SAndroid Build Coastguard Worker *bo_addr = trtt->cur_page_table_bo->offset +
398*61046927SAndroid Build Coastguard Worker trtt->next_page_table_bo_offset;
399*61046927SAndroid Build Coastguard Worker
400*61046927SAndroid Build Coastguard Worker trtt->next_page_table_bo_offset += 4096;
401*61046927SAndroid Build Coastguard Worker if (trtt->next_page_table_bo_offset >= ANV_TRTT_PAGE_TABLE_BO_SIZE)
402*61046927SAndroid Build Coastguard Worker trtt->cur_page_table_bo = NULL;
403*61046927SAndroid Build Coastguard Worker
404*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
405*61046927SAndroid Build Coastguard Worker }
406*61046927SAndroid Build Coastguard Worker
407*61046927SAndroid Build Coastguard Worker static VkResult
anv_trtt_init_queues_state(struct anv_device * device)408*61046927SAndroid Build Coastguard Worker anv_trtt_init_queues_state(struct anv_device *device)
409*61046927SAndroid Build Coastguard Worker {
410*61046927SAndroid Build Coastguard Worker struct anv_trtt *trtt = &device->trtt;
411*61046927SAndroid Build Coastguard Worker
412*61046927SAndroid Build Coastguard Worker struct anv_bo *l3_bo;
413*61046927SAndroid Build Coastguard Worker VkResult result = trtt_get_page_table_bo(device, &l3_bo, &trtt->l3_addr);
414*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
415*61046927SAndroid Build Coastguard Worker return result;
416*61046927SAndroid Build Coastguard Worker
417*61046927SAndroid Build Coastguard Worker trtt->l3_mirror = vk_zalloc(&device->vk.alloc, 4096, 8,
418*61046927SAndroid Build Coastguard Worker VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
419*61046927SAndroid Build Coastguard Worker if (!trtt->l3_mirror)
420*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
421*61046927SAndroid Build Coastguard Worker
422*61046927SAndroid Build Coastguard Worker /* L3 has 512 entries, so we can have up to 512 L2 tables. */
423*61046927SAndroid Build Coastguard Worker trtt->l2_mirror = vk_zalloc(&device->vk.alloc, 512 * 4096, 8,
424*61046927SAndroid Build Coastguard Worker VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
425*61046927SAndroid Build Coastguard Worker if (!trtt->l2_mirror) {
426*61046927SAndroid Build Coastguard Worker vk_free(&device->vk.alloc, trtt->l3_mirror);
427*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
428*61046927SAndroid Build Coastguard Worker }
429*61046927SAndroid Build Coastguard Worker
430*61046927SAndroid Build Coastguard Worker struct anv_async_submit submits[device->queue_count];
431*61046927SAndroid Build Coastguard Worker int submits_used = 0;
432*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < device->queue_count; i++) {
433*61046927SAndroid Build Coastguard Worker struct anv_queue *q = &device->queues[i];
434*61046927SAndroid Build Coastguard Worker
435*61046927SAndroid Build Coastguard Worker result = anv_async_submit_init(&submits[submits_used], q,
436*61046927SAndroid Build Coastguard Worker &device->batch_bo_pool, false, true);
437*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
438*61046927SAndroid Build Coastguard Worker break;
439*61046927SAndroid Build Coastguard Worker
440*61046927SAndroid Build Coastguard Worker struct anv_async_submit *submit = &submits[submits_used++];
441*61046927SAndroid Build Coastguard Worker
442*61046927SAndroid Build Coastguard Worker result = anv_genX(device->info, init_trtt_context_state)(submit);
443*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS) {
444*61046927SAndroid Build Coastguard Worker anv_async_submit_fini(submit);
445*61046927SAndroid Build Coastguard Worker submits_used--;
446*61046927SAndroid Build Coastguard Worker break;
447*61046927SAndroid Build Coastguard Worker }
448*61046927SAndroid Build Coastguard Worker
449*61046927SAndroid Build Coastguard Worker anv_genX(device->info, async_submit_end)(submit);
450*61046927SAndroid Build Coastguard Worker
451*61046927SAndroid Build Coastguard Worker result = device->kmd_backend->queue_exec_async(submit, 0, NULL, 1,
452*61046927SAndroid Build Coastguard Worker &submit->signal);
453*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS) {
454*61046927SAndroid Build Coastguard Worker anv_async_submit_fini(submit);
455*61046927SAndroid Build Coastguard Worker submits_used--;
456*61046927SAndroid Build Coastguard Worker break;
457*61046927SAndroid Build Coastguard Worker }
458*61046927SAndroid Build Coastguard Worker }
459*61046927SAndroid Build Coastguard Worker
460*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < submits_used; i++) {
461*61046927SAndroid Build Coastguard Worker anv_async_submit_wait(&submits[i]);
462*61046927SAndroid Build Coastguard Worker anv_async_submit_fini(&submits[i]);
463*61046927SAndroid Build Coastguard Worker }
464*61046927SAndroid Build Coastguard Worker
465*61046927SAndroid Build Coastguard Worker return result;
466*61046927SAndroid Build Coastguard Worker }
467*61046927SAndroid Build Coastguard Worker
468*61046927SAndroid Build Coastguard Worker /* For L3 and L2 pages, null and invalid entries are indicated by bits 1 and 0
469*61046927SAndroid Build Coastguard Worker * respectively. For L1 entries, the hardware compares the addresses against
470*61046927SAndroid Build Coastguard Worker * what we program to the GFX_TRTT_NULL and GFX_TRTT_INVAL registers.
471*61046927SAndroid Build Coastguard Worker */
472*61046927SAndroid Build Coastguard Worker #define ANV_TRTT_L3L2_NULL_ENTRY (1 << 1)
473*61046927SAndroid Build Coastguard Worker #define ANV_TRTT_L3L2_INVALID_ENTRY (1 << 0)
474*61046927SAndroid Build Coastguard Worker
475*61046927SAndroid Build Coastguard Worker static void
anv_trtt_bind_list_add_entry(struct anv_trtt_bind * binds,uint32_t * binds_len,uint64_t pte_addr,uint64_t entry_addr)476*61046927SAndroid Build Coastguard Worker anv_trtt_bind_list_add_entry(struct anv_trtt_bind *binds, uint32_t *binds_len,
477*61046927SAndroid Build Coastguard Worker uint64_t pte_addr, uint64_t entry_addr)
478*61046927SAndroid Build Coastguard Worker {
479*61046927SAndroid Build Coastguard Worker binds[*binds_len] = (struct anv_trtt_bind) {
480*61046927SAndroid Build Coastguard Worker .pte_addr = pte_addr,
481*61046927SAndroid Build Coastguard Worker .entry_addr = entry_addr,
482*61046927SAndroid Build Coastguard Worker };
483*61046927SAndroid Build Coastguard Worker (*binds_len)++;
484*61046927SAndroid Build Coastguard Worker }
485*61046927SAndroid Build Coastguard Worker
486*61046927SAndroid Build Coastguard Worker /* Adds elements to the anv_trtt_bind structs passed. This doesn't write the
487*61046927SAndroid Build Coastguard Worker * entries to the HW yet.
488*61046927SAndroid Build Coastguard Worker */
489*61046927SAndroid Build Coastguard Worker static VkResult
anv_trtt_bind_add(struct anv_device * device,uint64_t trtt_addr,uint64_t dest_addr,struct anv_trtt_bind * l3l2_binds,uint32_t * n_l3l2_binds,struct anv_trtt_bind * l1_binds,uint32_t * n_l1_binds)490*61046927SAndroid Build Coastguard Worker anv_trtt_bind_add(struct anv_device *device,
491*61046927SAndroid Build Coastguard Worker uint64_t trtt_addr, uint64_t dest_addr,
492*61046927SAndroid Build Coastguard Worker struct anv_trtt_bind *l3l2_binds,
493*61046927SAndroid Build Coastguard Worker uint32_t *n_l3l2_binds,
494*61046927SAndroid Build Coastguard Worker struct anv_trtt_bind *l1_binds,
495*61046927SAndroid Build Coastguard Worker uint32_t *n_l1_binds)
496*61046927SAndroid Build Coastguard Worker {
497*61046927SAndroid Build Coastguard Worker VkResult result = VK_SUCCESS;
498*61046927SAndroid Build Coastguard Worker struct anv_trtt *trtt = &device->trtt;
499*61046927SAndroid Build Coastguard Worker bool is_null_bind = dest_addr == ANV_TRTT_L1_NULL_TILE_VAL;
500*61046927SAndroid Build Coastguard Worker
501*61046927SAndroid Build Coastguard Worker int l3_index = (trtt_addr >> 35) & 0x1FF;
502*61046927SAndroid Build Coastguard Worker int l2_index = (trtt_addr >> 26) & 0x1FF;
503*61046927SAndroid Build Coastguard Worker int l1_index = (trtt_addr >> 16) & 0x3FF;
504*61046927SAndroid Build Coastguard Worker
505*61046927SAndroid Build Coastguard Worker uint64_t l2_addr = trtt->l3_mirror[l3_index];
506*61046927SAndroid Build Coastguard Worker if (l2_addr == ANV_TRTT_L3L2_NULL_ENTRY && is_null_bind) {
507*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
508*61046927SAndroid Build Coastguard Worker } else if (l2_addr == 0 || l2_addr == ANV_TRTT_L3L2_NULL_ENTRY) {
509*61046927SAndroid Build Coastguard Worker if (is_null_bind) {
510*61046927SAndroid Build Coastguard Worker trtt->l3_mirror[l3_index] = ANV_TRTT_L3L2_NULL_ENTRY;
511*61046927SAndroid Build Coastguard Worker
512*61046927SAndroid Build Coastguard Worker anv_trtt_bind_list_add_entry(l3l2_binds, n_l3l2_binds,
513*61046927SAndroid Build Coastguard Worker trtt->l3_addr + l3_index *
514*61046927SAndroid Build Coastguard Worker sizeof(uint64_t),
515*61046927SAndroid Build Coastguard Worker ANV_TRTT_L3L2_NULL_ENTRY);
516*61046927SAndroid Build Coastguard Worker
517*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
518*61046927SAndroid Build Coastguard Worker }
519*61046927SAndroid Build Coastguard Worker
520*61046927SAndroid Build Coastguard Worker struct anv_bo *l2_bo;
521*61046927SAndroid Build Coastguard Worker result = trtt_get_page_table_bo(device, &l2_bo, &l2_addr);
522*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
523*61046927SAndroid Build Coastguard Worker return result;
524*61046927SAndroid Build Coastguard Worker
525*61046927SAndroid Build Coastguard Worker trtt->l3_mirror[l3_index] = l2_addr;
526*61046927SAndroid Build Coastguard Worker
527*61046927SAndroid Build Coastguard Worker anv_trtt_bind_list_add_entry(l3l2_binds, n_l3l2_binds,
528*61046927SAndroid Build Coastguard Worker trtt->l3_addr + l3_index *
529*61046927SAndroid Build Coastguard Worker sizeof(uint64_t), l2_addr);
530*61046927SAndroid Build Coastguard Worker }
531*61046927SAndroid Build Coastguard Worker assert(l2_addr != 0 && l2_addr != ANV_TRTT_L3L2_NULL_ENTRY);
532*61046927SAndroid Build Coastguard Worker
533*61046927SAndroid Build Coastguard Worker /* The first page in the l2_mirror corresponds to l3_index=0 and so on. */
534*61046927SAndroid Build Coastguard Worker uint64_t l1_addr = trtt->l2_mirror[l3_index * 512 + l2_index];
535*61046927SAndroid Build Coastguard Worker if (l1_addr == ANV_TRTT_L3L2_NULL_ENTRY && is_null_bind) {
536*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
537*61046927SAndroid Build Coastguard Worker } else if (l1_addr == 0 || l1_addr == ANV_TRTT_L3L2_NULL_ENTRY) {
538*61046927SAndroid Build Coastguard Worker if (is_null_bind) {
539*61046927SAndroid Build Coastguard Worker trtt->l2_mirror[l3_index * 512 + l2_index] =
540*61046927SAndroid Build Coastguard Worker ANV_TRTT_L3L2_NULL_ENTRY;
541*61046927SAndroid Build Coastguard Worker
542*61046927SAndroid Build Coastguard Worker anv_trtt_bind_list_add_entry(l3l2_binds, n_l3l2_binds,
543*61046927SAndroid Build Coastguard Worker l2_addr + l2_index * sizeof(uint64_t),
544*61046927SAndroid Build Coastguard Worker ANV_TRTT_L3L2_NULL_ENTRY);
545*61046927SAndroid Build Coastguard Worker
546*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
547*61046927SAndroid Build Coastguard Worker }
548*61046927SAndroid Build Coastguard Worker
549*61046927SAndroid Build Coastguard Worker struct anv_bo *l1_bo;
550*61046927SAndroid Build Coastguard Worker result = trtt_get_page_table_bo(device, &l1_bo, &l1_addr);
551*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
552*61046927SAndroid Build Coastguard Worker return result;
553*61046927SAndroid Build Coastguard Worker
554*61046927SAndroid Build Coastguard Worker trtt->l2_mirror[l3_index * 512 + l2_index] = l1_addr;
555*61046927SAndroid Build Coastguard Worker
556*61046927SAndroid Build Coastguard Worker anv_trtt_bind_list_add_entry(l3l2_binds, n_l3l2_binds,
557*61046927SAndroid Build Coastguard Worker l2_addr + l2_index * sizeof(uint64_t),
558*61046927SAndroid Build Coastguard Worker l1_addr);
559*61046927SAndroid Build Coastguard Worker }
560*61046927SAndroid Build Coastguard Worker assert(l1_addr != 0 && l1_addr != ANV_TRTT_L3L2_NULL_ENTRY);
561*61046927SAndroid Build Coastguard Worker
562*61046927SAndroid Build Coastguard Worker anv_trtt_bind_list_add_entry(l1_binds, n_l1_binds,
563*61046927SAndroid Build Coastguard Worker l1_addr + l1_index * sizeof(uint32_t),
564*61046927SAndroid Build Coastguard Worker dest_addr);
565*61046927SAndroid Build Coastguard Worker
566*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
567*61046927SAndroid Build Coastguard Worker }
568*61046927SAndroid Build Coastguard Worker
569*61046927SAndroid Build Coastguard Worker VkResult
anv_sparse_trtt_garbage_collect_batches(struct anv_device * device,bool wait_completion)570*61046927SAndroid Build Coastguard Worker anv_sparse_trtt_garbage_collect_batches(struct anv_device *device,
571*61046927SAndroid Build Coastguard Worker bool wait_completion)
572*61046927SAndroid Build Coastguard Worker {
573*61046927SAndroid Build Coastguard Worker struct anv_trtt *trtt = &device->trtt;
574*61046927SAndroid Build Coastguard Worker
575*61046927SAndroid Build Coastguard Worker uint64_t last_value;
576*61046927SAndroid Build Coastguard Worker if (!wait_completion) {
577*61046927SAndroid Build Coastguard Worker VkResult result =
578*61046927SAndroid Build Coastguard Worker vk_sync_get_value(&device->vk, trtt->timeline, &last_value);
579*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
580*61046927SAndroid Build Coastguard Worker return result;
581*61046927SAndroid Build Coastguard Worker } else {
582*61046927SAndroid Build Coastguard Worker last_value = trtt->timeline_val;
583*61046927SAndroid Build Coastguard Worker }
584*61046927SAndroid Build Coastguard Worker
585*61046927SAndroid Build Coastguard Worker list_for_each_entry_safe(struct anv_trtt_submission, submit,
586*61046927SAndroid Build Coastguard Worker &trtt->in_flight_batches, link) {
587*61046927SAndroid Build Coastguard Worker if (submit->base.signal.signal_value <= last_value) {
588*61046927SAndroid Build Coastguard Worker list_del(&submit->link);
589*61046927SAndroid Build Coastguard Worker anv_async_submit_fini(&submit->base);
590*61046927SAndroid Build Coastguard Worker vk_free(&device->vk.alloc, submit);
591*61046927SAndroid Build Coastguard Worker continue;
592*61046927SAndroid Build Coastguard Worker }
593*61046927SAndroid Build Coastguard Worker
594*61046927SAndroid Build Coastguard Worker if (!wait_completion)
595*61046927SAndroid Build Coastguard Worker break;
596*61046927SAndroid Build Coastguard Worker
597*61046927SAndroid Build Coastguard Worker VkResult result = vk_sync_wait(
598*61046927SAndroid Build Coastguard Worker &device->vk,
599*61046927SAndroid Build Coastguard Worker submit->base.signal.sync,
600*61046927SAndroid Build Coastguard Worker submit->base.signal.signal_value,
601*61046927SAndroid Build Coastguard Worker VK_SYNC_WAIT_COMPLETE,
602*61046927SAndroid Build Coastguard Worker os_time_get_absolute_timeout(OS_TIMEOUT_INFINITE));
603*61046927SAndroid Build Coastguard Worker if (result == VK_SUCCESS) {
604*61046927SAndroid Build Coastguard Worker list_del(&submit->link);
605*61046927SAndroid Build Coastguard Worker anv_async_submit_fini(&submit->base);
606*61046927SAndroid Build Coastguard Worker vk_free(&device->vk.alloc, submit);
607*61046927SAndroid Build Coastguard Worker continue;
608*61046927SAndroid Build Coastguard Worker }
609*61046927SAndroid Build Coastguard Worker
610*61046927SAndroid Build Coastguard Worker /* If the wait failed but the caller wanted completion, return the
611*61046927SAndroid Build Coastguard Worker * error.
612*61046927SAndroid Build Coastguard Worker */
613*61046927SAndroid Build Coastguard Worker return result;
614*61046927SAndroid Build Coastguard Worker }
615*61046927SAndroid Build Coastguard Worker
616*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
617*61046927SAndroid Build Coastguard Worker }
618*61046927SAndroid Build Coastguard Worker
619*61046927SAndroid Build Coastguard Worker static VkResult
anv_sparse_bind_trtt(struct anv_device * device,struct anv_sparse_submission * sparse_submit)620*61046927SAndroid Build Coastguard Worker anv_sparse_bind_trtt(struct anv_device *device,
621*61046927SAndroid Build Coastguard Worker struct anv_sparse_submission *sparse_submit)
622*61046927SAndroid Build Coastguard Worker {
623*61046927SAndroid Build Coastguard Worker struct anv_trtt *trtt = &device->trtt;
624*61046927SAndroid Build Coastguard Worker VkResult result;
625*61046927SAndroid Build Coastguard Worker
626*61046927SAndroid Build Coastguard Worker /* TR-TT submission needs a queue even when the API entry point doesn't
627*61046927SAndroid Build Coastguard Worker * provide one, such as resource creation. We pick this queue from the user
628*61046927SAndroid Build Coastguard Worker * created queues at init_device_state() under anv_CreateDevice.
629*61046927SAndroid Build Coastguard Worker *
630*61046927SAndroid Build Coastguard Worker * It is technically possible for the user to create sparse resources even
631*61046927SAndroid Build Coastguard Worker * when they don't have a sparse queue: they won't be able to bind the
632*61046927SAndroid Build Coastguard Worker * resource but they should still be able to use the resource and rely on
633*61046927SAndroid Build Coastguard Worker * its unbound behavior. We haven't spotted any real world application or
634*61046927SAndroid Build Coastguard Worker * even test suite that exercises this behavior.
635*61046927SAndroid Build Coastguard Worker *
636*61046927SAndroid Build Coastguard Worker * For now let's just print an error message and return, which means that
637*61046927SAndroid Build Coastguard Worker * resource creation will succeed but the behavior will be undefined if the
638*61046927SAndroid Build Coastguard Worker * resource is used, which goes against our claim that we support the
639*61046927SAndroid Build Coastguard Worker * sparseResidencyNonResidentStrict property.
640*61046927SAndroid Build Coastguard Worker *
641*61046927SAndroid Build Coastguard Worker * TODO: be fully spec-compliant here. Maybe have a device-internal queue
642*61046927SAndroid Build Coastguard Worker * independent of the application's queues for the TR-TT operations.
643*61046927SAndroid Build Coastguard Worker */
644*61046927SAndroid Build Coastguard Worker if (!trtt->queue) {
645*61046927SAndroid Build Coastguard Worker static bool warned = false;
646*61046927SAndroid Build Coastguard Worker if (unlikely(!warned)) {
647*61046927SAndroid Build Coastguard Worker fprintf(stderr, "FIXME: application has created a sparse resource "
648*61046927SAndroid Build Coastguard Worker "but no queues capable of binding sparse resources were "
649*61046927SAndroid Build Coastguard Worker "created. Using these resources will result in undefined "
650*61046927SAndroid Build Coastguard Worker "behavior.\n");
651*61046927SAndroid Build Coastguard Worker warned = true;
652*61046927SAndroid Build Coastguard Worker }
653*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
654*61046927SAndroid Build Coastguard Worker }
655*61046927SAndroid Build Coastguard Worker if (!sparse_submit->queue)
656*61046927SAndroid Build Coastguard Worker sparse_submit->queue = trtt->queue;
657*61046927SAndroid Build Coastguard Worker
658*61046927SAndroid Build Coastguard Worker struct anv_trtt_submission *submit =
659*61046927SAndroid Build Coastguard Worker vk_zalloc(&device->vk.alloc, sizeof(*submit), 8,
660*61046927SAndroid Build Coastguard Worker VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
661*61046927SAndroid Build Coastguard Worker if (submit == NULL)
662*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
663*61046927SAndroid Build Coastguard Worker
664*61046927SAndroid Build Coastguard Worker result = anv_async_submit_init(&submit->base, sparse_submit->queue,
665*61046927SAndroid Build Coastguard Worker &device->batch_bo_pool,
666*61046927SAndroid Build Coastguard Worker false, false);
667*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
668*61046927SAndroid Build Coastguard Worker goto error_async;
669*61046927SAndroid Build Coastguard Worker
670*61046927SAndroid Build Coastguard Worker simple_mtx_lock(&trtt->mutex);
671*61046927SAndroid Build Coastguard Worker
672*61046927SAndroid Build Coastguard Worker anv_sparse_trtt_garbage_collect_batches(device, false);
673*61046927SAndroid Build Coastguard Worker
674*61046927SAndroid Build Coastguard Worker submit->base.signal = (struct vk_sync_signal) {
675*61046927SAndroid Build Coastguard Worker .sync = trtt->timeline,
676*61046927SAndroid Build Coastguard Worker .signal_value = ++trtt->timeline_val,
677*61046927SAndroid Build Coastguard Worker };
678*61046927SAndroid Build Coastguard Worker
679*61046927SAndroid Build Coastguard Worker /* If the TRTT L3 table was never set, initialize it as part of this
680*61046927SAndroid Build Coastguard Worker * submission.
681*61046927SAndroid Build Coastguard Worker */
682*61046927SAndroid Build Coastguard Worker if (!trtt->l3_addr) {
683*61046927SAndroid Build Coastguard Worker result = anv_trtt_init_queues_state(device);
684*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
685*61046927SAndroid Build Coastguard Worker goto error_add_bind;
686*61046927SAndroid Build Coastguard Worker }
687*61046927SAndroid Build Coastguard Worker assert(trtt->l3_addr);
688*61046927SAndroid Build Coastguard Worker
689*61046927SAndroid Build Coastguard Worker /* These capacities are conservative estimations. For L1 binds the
690*61046927SAndroid Build Coastguard Worker * number will match exactly unless we skip NULL binds due to L2 already
691*61046927SAndroid Build Coastguard Worker * being NULL. For L3/L2 things are harder to estimate, but the resulting
692*61046927SAndroid Build Coastguard Worker * numbers are so small that a little overestimation won't hurt.
693*61046927SAndroid Build Coastguard Worker *
694*61046927SAndroid Build Coastguard Worker * We have assertions below to catch estimation errors.
695*61046927SAndroid Build Coastguard Worker */
696*61046927SAndroid Build Coastguard Worker int l3l2_binds_capacity = 1;
697*61046927SAndroid Build Coastguard Worker int l1_binds_capacity = 0;
698*61046927SAndroid Build Coastguard Worker for (int b = 0; b < sparse_submit->binds_len; b++) {
699*61046927SAndroid Build Coastguard Worker assert(sparse_submit->binds[b].size % (64 * 1024) == 0);
700*61046927SAndroid Build Coastguard Worker int pages = sparse_submit->binds[b].size / (64 * 1024);
701*61046927SAndroid Build Coastguard Worker l1_binds_capacity += pages;
702*61046927SAndroid Build Coastguard Worker l3l2_binds_capacity += (pages / 1024 + 1) * 2;
703*61046927SAndroid Build Coastguard Worker }
704*61046927SAndroid Build Coastguard Worker
705*61046927SAndroid Build Coastguard Worker /* Turn a series of virtual address maps, into a list of L3/L2/L1 TRTT page
706*61046927SAndroid Build Coastguard Worker * table updates.
707*61046927SAndroid Build Coastguard Worker */
708*61046927SAndroid Build Coastguard Worker STACK_ARRAY(struct anv_trtt_bind, l3l2_binds, l3l2_binds_capacity);
709*61046927SAndroid Build Coastguard Worker STACK_ARRAY(struct anv_trtt_bind, l1_binds, l1_binds_capacity);
710*61046927SAndroid Build Coastguard Worker uint32_t n_l3l2_binds = 0, n_l1_binds = 0;
711*61046927SAndroid Build Coastguard Worker for (int b = 0; b < sparse_submit->binds_len && result == VK_SUCCESS; b++) {
712*61046927SAndroid Build Coastguard Worker struct anv_vm_bind *vm_bind = &sparse_submit->binds[b];
713*61046927SAndroid Build Coastguard Worker for (size_t i = 0; i < vm_bind->size && result == VK_SUCCESS; i += 64 * 1024) {
714*61046927SAndroid Build Coastguard Worker uint64_t trtt_addr = vm_bind->address + i;
715*61046927SAndroid Build Coastguard Worker uint64_t dest_addr =
716*61046927SAndroid Build Coastguard Worker (vm_bind->op == ANV_VM_BIND && vm_bind->bo) ?
717*61046927SAndroid Build Coastguard Worker vm_bind->bo->offset + vm_bind->bo_offset + i :
718*61046927SAndroid Build Coastguard Worker ANV_TRTT_L1_NULL_TILE_VAL;
719*61046927SAndroid Build Coastguard Worker
720*61046927SAndroid Build Coastguard Worker result = anv_trtt_bind_add(device, trtt_addr, dest_addr,
721*61046927SAndroid Build Coastguard Worker l3l2_binds, &n_l3l2_binds,
722*61046927SAndroid Build Coastguard Worker l1_binds, &n_l1_binds);
723*61046927SAndroid Build Coastguard Worker }
724*61046927SAndroid Build Coastguard Worker }
725*61046927SAndroid Build Coastguard Worker
726*61046927SAndroid Build Coastguard Worker assert(n_l3l2_binds <= l3l2_binds_capacity);
727*61046927SAndroid Build Coastguard Worker assert(n_l1_binds <= l1_binds_capacity);
728*61046927SAndroid Build Coastguard Worker
729*61046927SAndroid Build Coastguard Worker /* Convert the L3/L2/L1 TRTT page table updates in anv_trtt_bind elements
730*61046927SAndroid Build Coastguard Worker * into MI commands.
731*61046927SAndroid Build Coastguard Worker */
732*61046927SAndroid Build Coastguard Worker if (result == VK_SUCCESS) {
733*61046927SAndroid Build Coastguard Worker sparse_debug("trtt_binds: num_vm_binds:%02d l3l2:%04d l1:%04d\n",
734*61046927SAndroid Build Coastguard Worker sparse_submit->binds_len, n_l3l2_binds, n_l1_binds);
735*61046927SAndroid Build Coastguard Worker
736*61046927SAndroid Build Coastguard Worker if (n_l3l2_binds || n_l1_binds) {
737*61046927SAndroid Build Coastguard Worker anv_genX(device->info, write_trtt_entries)(
738*61046927SAndroid Build Coastguard Worker &submit->base, l3l2_binds, n_l3l2_binds, l1_binds, n_l1_binds);
739*61046927SAndroid Build Coastguard Worker }
740*61046927SAndroid Build Coastguard Worker }
741*61046927SAndroid Build Coastguard Worker
742*61046927SAndroid Build Coastguard Worker STACK_ARRAY_FINISH(l1_binds);
743*61046927SAndroid Build Coastguard Worker STACK_ARRAY_FINISH(l3l2_binds);
744*61046927SAndroid Build Coastguard Worker
745*61046927SAndroid Build Coastguard Worker anv_genX(device->info, async_submit_end)(&submit->base);
746*61046927SAndroid Build Coastguard Worker
747*61046927SAndroid Build Coastguard Worker if (submit->base.batch.status != VK_SUCCESS) {
748*61046927SAndroid Build Coastguard Worker result = submit->base.batch.status;
749*61046927SAndroid Build Coastguard Worker goto error_add_bind;
750*61046927SAndroid Build Coastguard Worker }
751*61046927SAndroid Build Coastguard Worker
752*61046927SAndroid Build Coastguard Worker /* Add all the BOs backing TRTT page tables to the reloc list.
753*61046927SAndroid Build Coastguard Worker *
754*61046927SAndroid Build Coastguard Worker * TODO: we could narrow down the list by using anv_address structures in
755*61046927SAndroid Build Coastguard Worker * anv_trtt_bind for the pte_addr.
756*61046927SAndroid Build Coastguard Worker */
757*61046927SAndroid Build Coastguard Worker if (device->physical->uses_relocs) {
758*61046927SAndroid Build Coastguard Worker for (int i = 0; i < trtt->num_page_table_bos; i++) {
759*61046927SAndroid Build Coastguard Worker result = anv_reloc_list_add_bo(&submit->base.relocs,
760*61046927SAndroid Build Coastguard Worker trtt->page_table_bos[i]);
761*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
762*61046927SAndroid Build Coastguard Worker goto error_add_bind;
763*61046927SAndroid Build Coastguard Worker }
764*61046927SAndroid Build Coastguard Worker }
765*61046927SAndroid Build Coastguard Worker
766*61046927SAndroid Build Coastguard Worker result =
767*61046927SAndroid Build Coastguard Worker device->kmd_backend->queue_exec_async(&submit->base,
768*61046927SAndroid Build Coastguard Worker sparse_submit->wait_count,
769*61046927SAndroid Build Coastguard Worker sparse_submit->waits,
770*61046927SAndroid Build Coastguard Worker sparse_submit->signal_count,
771*61046927SAndroid Build Coastguard Worker sparse_submit->signals);
772*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
773*61046927SAndroid Build Coastguard Worker goto error_add_bind;
774*61046927SAndroid Build Coastguard Worker
775*61046927SAndroid Build Coastguard Worker
776*61046927SAndroid Build Coastguard Worker list_addtail(&submit->link, &trtt->in_flight_batches);
777*61046927SAndroid Build Coastguard Worker
778*61046927SAndroid Build Coastguard Worker simple_mtx_unlock(&trtt->mutex);
779*61046927SAndroid Build Coastguard Worker
780*61046927SAndroid Build Coastguard Worker ANV_RMV(vm_binds, device, sparse_submit->binds, sparse_submit->binds_len);
781*61046927SAndroid Build Coastguard Worker
782*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
783*61046927SAndroid Build Coastguard Worker
784*61046927SAndroid Build Coastguard Worker error_add_bind:
785*61046927SAndroid Build Coastguard Worker simple_mtx_unlock(&trtt->mutex);
786*61046927SAndroid Build Coastguard Worker anv_async_submit_fini(&submit->base);
787*61046927SAndroid Build Coastguard Worker error_async:
788*61046927SAndroid Build Coastguard Worker vk_free(&device->vk.alloc, submit);
789*61046927SAndroid Build Coastguard Worker return result;
790*61046927SAndroid Build Coastguard Worker }
791*61046927SAndroid Build Coastguard Worker
792*61046927SAndroid Build Coastguard Worker static VkResult
anv_sparse_bind_vm_bind(struct anv_device * device,struct anv_sparse_submission * submit)793*61046927SAndroid Build Coastguard Worker anv_sparse_bind_vm_bind(struct anv_device *device,
794*61046927SAndroid Build Coastguard Worker struct anv_sparse_submission *submit)
795*61046927SAndroid Build Coastguard Worker {
796*61046927SAndroid Build Coastguard Worker struct anv_queue *queue = submit->queue;
797*61046927SAndroid Build Coastguard Worker
798*61046927SAndroid Build Coastguard Worker VkResult result = device->kmd_backend->vm_bind(device, submit,
799*61046927SAndroid Build Coastguard Worker ANV_VM_BIND_FLAG_NONE);
800*61046927SAndroid Build Coastguard Worker if (!queue) {
801*61046927SAndroid Build Coastguard Worker assert(submit->wait_count == 0 && submit->signal_count == 0 &&
802*61046927SAndroid Build Coastguard Worker submit->binds_len == 1);
803*61046927SAndroid Build Coastguard Worker return result;
804*61046927SAndroid Build Coastguard Worker }
805*61046927SAndroid Build Coastguard Worker
806*61046927SAndroid Build Coastguard Worker if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
807*61046927SAndroid Build Coastguard Worker /* If we get this, the system is under memory pressure. First we
808*61046927SAndroid Build Coastguard Worker * manually wait for all our dependency syncobjs hoping that some memory
809*61046927SAndroid Build Coastguard Worker * will be released while we wait, then we try to issue each bind
810*61046927SAndroid Build Coastguard Worker * operation in a single ioctl as it requires less Kernel memory and so
811*61046927SAndroid Build Coastguard Worker * we may be able to move things forward, although slowly, while also
812*61046927SAndroid Build Coastguard Worker * waiting for each operation to complete before issuing the next.
813*61046927SAndroid Build Coastguard Worker * Performance isn't a concern at this point: we're just trying to move
814*61046927SAndroid Build Coastguard Worker * progress forward without crashing until whatever is eating too much
815*61046927SAndroid Build Coastguard Worker * memory goes away.
816*61046927SAndroid Build Coastguard Worker */
817*61046927SAndroid Build Coastguard Worker
818*61046927SAndroid Build Coastguard Worker result = vk_sync_wait_many(&device->vk, submit->wait_count,
819*61046927SAndroid Build Coastguard Worker submit->waits, VK_SYNC_WAIT_COMPLETE,
820*61046927SAndroid Build Coastguard Worker INT64_MAX);
821*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
822*61046927SAndroid Build Coastguard Worker return vk_queue_set_lost(&queue->vk, "vk_sync_wait_many failed");
823*61046927SAndroid Build Coastguard Worker
824*61046927SAndroid Build Coastguard Worker struct vk_sync *sync;
825*61046927SAndroid Build Coastguard Worker result = vk_sync_create(&device->vk,
826*61046927SAndroid Build Coastguard Worker &device->physical->sync_syncobj_type,
827*61046927SAndroid Build Coastguard Worker VK_SYNC_IS_TIMELINE, 0 /* initial_value */,
828*61046927SAndroid Build Coastguard Worker &sync);
829*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
830*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
831*61046927SAndroid Build Coastguard Worker
832*61046927SAndroid Build Coastguard Worker for (int b = 0; b < submit->binds_len; b++) {
833*61046927SAndroid Build Coastguard Worker struct vk_sync_signal sync_signal = {
834*61046927SAndroid Build Coastguard Worker .sync = sync,
835*61046927SAndroid Build Coastguard Worker .signal_value = b + 1,
836*61046927SAndroid Build Coastguard Worker };
837*61046927SAndroid Build Coastguard Worker struct anv_sparse_submission s = {
838*61046927SAndroid Build Coastguard Worker .queue = submit->queue,
839*61046927SAndroid Build Coastguard Worker .binds = &submit->binds[b],
840*61046927SAndroid Build Coastguard Worker .binds_len = 1,
841*61046927SAndroid Build Coastguard Worker .binds_capacity = 1,
842*61046927SAndroid Build Coastguard Worker .wait_count = 0,
843*61046927SAndroid Build Coastguard Worker .signal_count = 1,
844*61046927SAndroid Build Coastguard Worker .waits = NULL,
845*61046927SAndroid Build Coastguard Worker .signals = &sync_signal,
846*61046927SAndroid Build Coastguard Worker };
847*61046927SAndroid Build Coastguard Worker result = device->kmd_backend->vm_bind(device, &s,
848*61046927SAndroid Build Coastguard Worker ANV_VM_BIND_FLAG_NONE);
849*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS) {
850*61046927SAndroid Build Coastguard Worker vk_sync_destroy(&device->vk, sync);
851*61046927SAndroid Build Coastguard Worker return vk_error(device, result); /* Well, at least we tried... */
852*61046927SAndroid Build Coastguard Worker }
853*61046927SAndroid Build Coastguard Worker
854*61046927SAndroid Build Coastguard Worker result = vk_sync_wait(&device->vk, sync, sync_signal.signal_value,
855*61046927SAndroid Build Coastguard Worker VK_SYNC_WAIT_COMPLETE, UINT64_MAX);
856*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS) {
857*61046927SAndroid Build Coastguard Worker vk_sync_destroy(&device->vk, sync);
858*61046927SAndroid Build Coastguard Worker return vk_queue_set_lost(&queue->vk, "vk_sync_wait failed");
859*61046927SAndroid Build Coastguard Worker }
860*61046927SAndroid Build Coastguard Worker }
861*61046927SAndroid Build Coastguard Worker
862*61046927SAndroid Build Coastguard Worker vk_sync_destroy(&device->vk, sync);
863*61046927SAndroid Build Coastguard Worker
864*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < submit->signal_count; i++) {
865*61046927SAndroid Build Coastguard Worker struct vk_sync_signal *s = &submit->signals[i];
866*61046927SAndroid Build Coastguard Worker result = vk_sync_signal(&device->vk, s->sync, s->signal_value);
867*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
868*61046927SAndroid Build Coastguard Worker return vk_queue_set_lost(&queue->vk, "vk_sync_signal failed");
869*61046927SAndroid Build Coastguard Worker }
870*61046927SAndroid Build Coastguard Worker }
871*61046927SAndroid Build Coastguard Worker
872*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
873*61046927SAndroid Build Coastguard Worker }
874*61046927SAndroid Build Coastguard Worker
875*61046927SAndroid Build Coastguard Worker VkResult
anv_sparse_bind(struct anv_device * device,struct anv_sparse_submission * submit)876*61046927SAndroid Build Coastguard Worker anv_sparse_bind(struct anv_device *device,
877*61046927SAndroid Build Coastguard Worker struct anv_sparse_submission *submit)
878*61046927SAndroid Build Coastguard Worker {
879*61046927SAndroid Build Coastguard Worker if (INTEL_DEBUG(DEBUG_SPARSE)) {
880*61046927SAndroid Build Coastguard Worker for (int b = 0; b < submit->binds_len; b++)
881*61046927SAndroid Build Coastguard Worker dump_anv_vm_bind(device, &submit->binds[b]);
882*61046927SAndroid Build Coastguard Worker }
883*61046927SAndroid Build Coastguard Worker
884*61046927SAndroid Build Coastguard Worker return device->physical->sparse_type == ANV_SPARSE_TYPE_TRTT ?
885*61046927SAndroid Build Coastguard Worker anv_sparse_bind_trtt(device, submit) :
886*61046927SAndroid Build Coastguard Worker anv_sparse_bind_vm_bind(device, submit);
887*61046927SAndroid Build Coastguard Worker }
888*61046927SAndroid Build Coastguard Worker
889*61046927SAndroid Build Coastguard Worker VkResult
anv_init_sparse_bindings(struct anv_device * device,uint64_t size_,struct anv_sparse_binding_data * sparse,enum anv_bo_alloc_flags alloc_flags,uint64_t client_address,struct anv_address * out_address)890*61046927SAndroid Build Coastguard Worker anv_init_sparse_bindings(struct anv_device *device,
891*61046927SAndroid Build Coastguard Worker uint64_t size_,
892*61046927SAndroid Build Coastguard Worker struct anv_sparse_binding_data *sparse,
893*61046927SAndroid Build Coastguard Worker enum anv_bo_alloc_flags alloc_flags,
894*61046927SAndroid Build Coastguard Worker uint64_t client_address,
895*61046927SAndroid Build Coastguard Worker struct anv_address *out_address)
896*61046927SAndroid Build Coastguard Worker {
897*61046927SAndroid Build Coastguard Worker uint64_t size = align64(size_, ANV_SPARSE_BLOCK_SIZE);
898*61046927SAndroid Build Coastguard Worker
899*61046927SAndroid Build Coastguard Worker if (device->physical->sparse_type == ANV_SPARSE_TYPE_TRTT)
900*61046927SAndroid Build Coastguard Worker alloc_flags |= ANV_BO_ALLOC_TRTT;
901*61046927SAndroid Build Coastguard Worker
902*61046927SAndroid Build Coastguard Worker sparse->address = anv_vma_alloc(device, size, ANV_SPARSE_BLOCK_SIZE,
903*61046927SAndroid Build Coastguard Worker alloc_flags,
904*61046927SAndroid Build Coastguard Worker intel_48b_address(client_address),
905*61046927SAndroid Build Coastguard Worker &sparse->vma_heap);
906*61046927SAndroid Build Coastguard Worker sparse->size = size;
907*61046927SAndroid Build Coastguard Worker
908*61046927SAndroid Build Coastguard Worker out_address->bo = NULL;
909*61046927SAndroid Build Coastguard Worker out_address->offset = sparse->address;
910*61046927SAndroid Build Coastguard Worker
911*61046927SAndroid Build Coastguard Worker struct anv_vm_bind bind = {
912*61046927SAndroid Build Coastguard Worker .bo = NULL, /* That's a NULL binding. */
913*61046927SAndroid Build Coastguard Worker .address = sparse->address,
914*61046927SAndroid Build Coastguard Worker .bo_offset = 0,
915*61046927SAndroid Build Coastguard Worker .size = size,
916*61046927SAndroid Build Coastguard Worker .op = ANV_VM_BIND,
917*61046927SAndroid Build Coastguard Worker };
918*61046927SAndroid Build Coastguard Worker struct anv_sparse_submission submit = {
919*61046927SAndroid Build Coastguard Worker .queue = NULL,
920*61046927SAndroid Build Coastguard Worker .binds = &bind,
921*61046927SAndroid Build Coastguard Worker .binds_len = 1,
922*61046927SAndroid Build Coastguard Worker .binds_capacity = 1,
923*61046927SAndroid Build Coastguard Worker .wait_count = 0,
924*61046927SAndroid Build Coastguard Worker .signal_count = 0,
925*61046927SAndroid Build Coastguard Worker };
926*61046927SAndroid Build Coastguard Worker VkResult res = anv_sparse_bind(device, &submit);
927*61046927SAndroid Build Coastguard Worker if (res != VK_SUCCESS) {
928*61046927SAndroid Build Coastguard Worker anv_vma_free(device, sparse->vma_heap, sparse->address, sparse->size);
929*61046927SAndroid Build Coastguard Worker return res;
930*61046927SAndroid Build Coastguard Worker }
931*61046927SAndroid Build Coastguard Worker
932*61046927SAndroid Build Coastguard Worker p_atomic_inc(&device->num_sparse_resources);
933*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
934*61046927SAndroid Build Coastguard Worker }
935*61046927SAndroid Build Coastguard Worker
936*61046927SAndroid Build Coastguard Worker void
anv_free_sparse_bindings(struct anv_device * device,struct anv_sparse_binding_data * sparse)937*61046927SAndroid Build Coastguard Worker anv_free_sparse_bindings(struct anv_device *device,
938*61046927SAndroid Build Coastguard Worker struct anv_sparse_binding_data *sparse)
939*61046927SAndroid Build Coastguard Worker {
940*61046927SAndroid Build Coastguard Worker if (!sparse->address)
941*61046927SAndroid Build Coastguard Worker return;
942*61046927SAndroid Build Coastguard Worker
943*61046927SAndroid Build Coastguard Worker sparse_debug("%s: address:0x%016"PRIx64" size:0x%08"PRIx64"\n",
944*61046927SAndroid Build Coastguard Worker __func__, sparse->address, sparse->size);
945*61046927SAndroid Build Coastguard Worker
946*61046927SAndroid Build Coastguard Worker p_atomic_dec(&device->num_sparse_resources);
947*61046927SAndroid Build Coastguard Worker
948*61046927SAndroid Build Coastguard Worker struct anv_vm_bind unbind = {
949*61046927SAndroid Build Coastguard Worker .bo = 0,
950*61046927SAndroid Build Coastguard Worker .address = sparse->address,
951*61046927SAndroid Build Coastguard Worker .bo_offset = 0,
952*61046927SAndroid Build Coastguard Worker .size = sparse->size,
953*61046927SAndroid Build Coastguard Worker .op = ANV_VM_UNBIND,
954*61046927SAndroid Build Coastguard Worker };
955*61046927SAndroid Build Coastguard Worker struct anv_sparse_submission submit = {
956*61046927SAndroid Build Coastguard Worker .queue = NULL,
957*61046927SAndroid Build Coastguard Worker .binds = &unbind,
958*61046927SAndroid Build Coastguard Worker .binds_len = 1,
959*61046927SAndroid Build Coastguard Worker .binds_capacity = 1,
960*61046927SAndroid Build Coastguard Worker .wait_count = 0,
961*61046927SAndroid Build Coastguard Worker .signal_count = 0,
962*61046927SAndroid Build Coastguard Worker };
963*61046927SAndroid Build Coastguard Worker VkResult res = anv_sparse_bind(device, &submit);
964*61046927SAndroid Build Coastguard Worker
965*61046927SAndroid Build Coastguard Worker /* Our callers don't have a way to signal failure to the upper layers, so
966*61046927SAndroid Build Coastguard Worker * just keep the vma if we fail to unbind it. Still, let's have an
967*61046927SAndroid Build Coastguard Worker * assertion because this really shouldn't be happening.
968*61046927SAndroid Build Coastguard Worker */
969*61046927SAndroid Build Coastguard Worker assert(res == VK_SUCCESS);
970*61046927SAndroid Build Coastguard Worker if (res != VK_SUCCESS)
971*61046927SAndroid Build Coastguard Worker return;
972*61046927SAndroid Build Coastguard Worker
973*61046927SAndroid Build Coastguard Worker anv_vma_free(device, sparse->vma_heap, sparse->address, sparse->size);
974*61046927SAndroid Build Coastguard Worker }
975*61046927SAndroid Build Coastguard Worker
976*61046927SAndroid Build Coastguard Worker static VkExtent3D
anv_sparse_calc_block_shape(struct anv_physical_device * pdevice,struct isl_surf * surf,const struct isl_tile_info * tile_info)977*61046927SAndroid Build Coastguard Worker anv_sparse_calc_block_shape(struct anv_physical_device *pdevice,
978*61046927SAndroid Build Coastguard Worker struct isl_surf *surf,
979*61046927SAndroid Build Coastguard Worker const struct isl_tile_info *tile_info)
980*61046927SAndroid Build Coastguard Worker {
981*61046927SAndroid Build Coastguard Worker const struct isl_format_layout *layout =
982*61046927SAndroid Build Coastguard Worker isl_format_get_layout(surf->format);
983*61046927SAndroid Build Coastguard Worker
984*61046927SAndroid Build Coastguard Worker VkExtent3D block_shape_el = {
985*61046927SAndroid Build Coastguard Worker .width = tile_info->logical_extent_el.width,
986*61046927SAndroid Build Coastguard Worker .height = tile_info->logical_extent_el.height,
987*61046927SAndroid Build Coastguard Worker .depth = tile_info->logical_extent_el.depth,
988*61046927SAndroid Build Coastguard Worker };
989*61046927SAndroid Build Coastguard Worker VkExtent3D block_shape_px = vk_extent3d_el_to_px(block_shape_el, layout);
990*61046927SAndroid Build Coastguard Worker
991*61046927SAndroid Build Coastguard Worker assert(surf->tiling != ISL_TILING_LINEAR);
992*61046927SAndroid Build Coastguard Worker
993*61046927SAndroid Build Coastguard Worker return block_shape_px;
994*61046927SAndroid Build Coastguard Worker }
995*61046927SAndroid Build Coastguard Worker
996*61046927SAndroid Build Coastguard Worker VkSparseImageFormatProperties
anv_sparse_calc_image_format_properties(struct anv_physical_device * pdevice,VkImageAspectFlags aspect,VkImageType vk_image_type,VkSampleCountFlagBits vk_samples,struct isl_surf * surf)997*61046927SAndroid Build Coastguard Worker anv_sparse_calc_image_format_properties(struct anv_physical_device *pdevice,
998*61046927SAndroid Build Coastguard Worker VkImageAspectFlags aspect,
999*61046927SAndroid Build Coastguard Worker VkImageType vk_image_type,
1000*61046927SAndroid Build Coastguard Worker VkSampleCountFlagBits vk_samples,
1001*61046927SAndroid Build Coastguard Worker struct isl_surf *surf)
1002*61046927SAndroid Build Coastguard Worker {
1003*61046927SAndroid Build Coastguard Worker const struct isl_format_layout *isl_layout =
1004*61046927SAndroid Build Coastguard Worker isl_format_get_layout(surf->format);
1005*61046927SAndroid Build Coastguard Worker struct isl_tile_info tile_info;
1006*61046927SAndroid Build Coastguard Worker isl_surf_get_tile_info(surf, &tile_info);
1007*61046927SAndroid Build Coastguard Worker const int bpb = isl_layout->bpb;
1008*61046927SAndroid Build Coastguard Worker assert(bpb == 8 || bpb == 16 || bpb == 32 || bpb == 64 ||bpb == 128);
1009*61046927SAndroid Build Coastguard Worker
1010*61046927SAndroid Build Coastguard Worker VkExtent3D granularity = anv_sparse_calc_block_shape(pdevice, surf,
1011*61046927SAndroid Build Coastguard Worker &tile_info);
1012*61046927SAndroid Build Coastguard Worker bool is_standard = false;
1013*61046927SAndroid Build Coastguard Worker bool is_known_nonstandard_format = false;
1014*61046927SAndroid Build Coastguard Worker
1015*61046927SAndroid Build Coastguard Worker /* We shouldn't be able to reach this function with a 1D image. */
1016*61046927SAndroid Build Coastguard Worker assert(vk_image_type != VK_IMAGE_TYPE_1D);
1017*61046927SAndroid Build Coastguard Worker
1018*61046927SAndroid Build Coastguard Worker VkExtent3D std_shape =
1019*61046927SAndroid Build Coastguard Worker anv_sparse_get_standard_image_block_shape(surf->format,
1020*61046927SAndroid Build Coastguard Worker vk_image_type, vk_samples,
1021*61046927SAndroid Build Coastguard Worker bpb);
1022*61046927SAndroid Build Coastguard Worker /* YUV formats don't work with Tile64, which is required if we want to
1023*61046927SAndroid Build Coastguard Worker * claim standard block shapes. The spec requires us to support all
1024*61046927SAndroid Build Coastguard Worker * non-compressed color formats that non-sparse supports, so we can't just
1025*61046927SAndroid Build Coastguard Worker * say YUV formats are not supported by Sparse. So we end supporting this
1026*61046927SAndroid Build Coastguard Worker * format and anv_sparse_calc_miptail_properties() will say that everything
1027*61046927SAndroid Build Coastguard Worker * is part of the miptail.
1028*61046927SAndroid Build Coastguard Worker *
1029*61046927SAndroid Build Coastguard Worker * For more details on the hardware restriction, please check
1030*61046927SAndroid Build Coastguard Worker * isl_gfx125_filter_tiling().
1031*61046927SAndroid Build Coastguard Worker */
1032*61046927SAndroid Build Coastguard Worker if (pdevice->info.verx10 >= 125 && isl_format_is_yuv(surf->format))
1033*61046927SAndroid Build Coastguard Worker is_known_nonstandard_format = true;
1034*61046927SAndroid Build Coastguard Worker
1035*61046927SAndroid Build Coastguard Worker /* The standard block shapes (and by extension, the tiling formats they
1036*61046927SAndroid Build Coastguard Worker * require) are simply incompatible with getting a 2D view of a 3D image.
1037*61046927SAndroid Build Coastguard Worker */
1038*61046927SAndroid Build Coastguard Worker if (surf->usage & ISL_SURF_USAGE_2D_3D_COMPATIBLE_BIT)
1039*61046927SAndroid Build Coastguard Worker is_known_nonstandard_format = true;
1040*61046927SAndroid Build Coastguard Worker
1041*61046927SAndroid Build Coastguard Worker is_standard = granularity.width == std_shape.width &&
1042*61046927SAndroid Build Coastguard Worker granularity.height == std_shape.height &&
1043*61046927SAndroid Build Coastguard Worker granularity.depth == std_shape.depth;
1044*61046927SAndroid Build Coastguard Worker
1045*61046927SAndroid Build Coastguard Worker /* TODO: dEQP seems to care about the block shapes being standard even for
1046*61046927SAndroid Build Coastguard Worker * the cases where is_known_nonstandard_format is true. Luckily as of today
1047*61046927SAndroid Build Coastguard Worker * all of those cases are NotSupported but sooner or later we may end up
1048*61046927SAndroid Build Coastguard Worker * getting a failure.
1049*61046927SAndroid Build Coastguard Worker * Notice that in practice we report these cases as having the mip tail
1050*61046927SAndroid Build Coastguard Worker * starting on mip level 0, so the reported block shapes are irrelevant
1051*61046927SAndroid Build Coastguard Worker * since non-opaque binds are not supported. Still, dEQP seems to care.
1052*61046927SAndroid Build Coastguard Worker */
1053*61046927SAndroid Build Coastguard Worker assert(is_standard || is_known_nonstandard_format);
1054*61046927SAndroid Build Coastguard Worker assert(!(is_standard && is_known_nonstandard_format));
1055*61046927SAndroid Build Coastguard Worker
1056*61046927SAndroid Build Coastguard Worker bool wrong_block_size = isl_calc_tile_size(&tile_info) !=
1057*61046927SAndroid Build Coastguard Worker ANV_SPARSE_BLOCK_SIZE;
1058*61046927SAndroid Build Coastguard Worker
1059*61046927SAndroid Build Coastguard Worker return (VkSparseImageFormatProperties) {
1060*61046927SAndroid Build Coastguard Worker .aspectMask = aspect,
1061*61046927SAndroid Build Coastguard Worker .imageGranularity = granularity,
1062*61046927SAndroid Build Coastguard Worker .flags = ((is_standard || is_known_nonstandard_format) ? 0 :
1063*61046927SAndroid Build Coastguard Worker VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT) |
1064*61046927SAndroid Build Coastguard Worker (wrong_block_size ? VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT :
1065*61046927SAndroid Build Coastguard Worker 0),
1066*61046927SAndroid Build Coastguard Worker };
1067*61046927SAndroid Build Coastguard Worker }
1068*61046927SAndroid Build Coastguard Worker
1069*61046927SAndroid Build Coastguard Worker /* The miptail is supposed to be this region where the tiniest mip levels
1070*61046927SAndroid Build Coastguard Worker * are squished together in one single page, which should save us some memory.
1071*61046927SAndroid Build Coastguard Worker * It's a hardware feature which our hardware supports on certain tiling
1072*61046927SAndroid Build Coastguard Worker * formats - the ones we always want to use for sparse resources.
1073*61046927SAndroid Build Coastguard Worker *
1074*61046927SAndroid Build Coastguard Worker * For sparse, the main feature of the miptail is that it only supports opaque
1075*61046927SAndroid Build Coastguard Worker * binds, so you either bind the whole miptail or you bind nothing at all,
1076*61046927SAndroid Build Coastguard Worker * there are no subresources inside it to separately bind. While the idea is
1077*61046927SAndroid Build Coastguard Worker * that the miptail as reported by sparse should match what our hardware does,
1078*61046927SAndroid Build Coastguard Worker * in practice we can say in our sparse functions that certain mip levels are
1079*61046927SAndroid Build Coastguard Worker * part of the miptail while from the point of view of our hardwared they
1080*61046927SAndroid Build Coastguard Worker * aren't.
1081*61046927SAndroid Build Coastguard Worker *
1082*61046927SAndroid Build Coastguard Worker * If we detect we're using the sparse-friendly tiling formats and ISL
1083*61046927SAndroid Build Coastguard Worker * supports miptails for them, we can just trust the miptail level set by ISL
1084*61046927SAndroid Build Coastguard Worker * and things can proceed as The Spec intended.
1085*61046927SAndroid Build Coastguard Worker *
1086*61046927SAndroid Build Coastguard Worker * However, if that's not the case, we have to go on a best-effort policy. We
1087*61046927SAndroid Build Coastguard Worker * could simply declare that every mip level is part of the miptail and be
1088*61046927SAndroid Build Coastguard Worker * done, but since that kinda defeats the purpose of Sparse we try to find
1089*61046927SAndroid Build Coastguard Worker * what level we really should be reporting as the first miptail level based
1090*61046927SAndroid Build Coastguard Worker * on the alignments of the surface subresources.
1091*61046927SAndroid Build Coastguard Worker */
1092*61046927SAndroid Build Coastguard Worker void
anv_sparse_calc_miptail_properties(struct anv_device * device,struct anv_image * image,VkImageAspectFlags vk_aspect,uint32_t * imageMipTailFirstLod,VkDeviceSize * imageMipTailSize,VkDeviceSize * imageMipTailOffset,VkDeviceSize * imageMipTailStride)1093*61046927SAndroid Build Coastguard Worker anv_sparse_calc_miptail_properties(struct anv_device *device,
1094*61046927SAndroid Build Coastguard Worker struct anv_image *image,
1095*61046927SAndroid Build Coastguard Worker VkImageAspectFlags vk_aspect,
1096*61046927SAndroid Build Coastguard Worker uint32_t *imageMipTailFirstLod,
1097*61046927SAndroid Build Coastguard Worker VkDeviceSize *imageMipTailSize,
1098*61046927SAndroid Build Coastguard Worker VkDeviceSize *imageMipTailOffset,
1099*61046927SAndroid Build Coastguard Worker VkDeviceSize *imageMipTailStride)
1100*61046927SAndroid Build Coastguard Worker {
1101*61046927SAndroid Build Coastguard Worker const uint32_t plane = anv_image_aspect_to_plane(image, vk_aspect);
1102*61046927SAndroid Build Coastguard Worker struct isl_surf *surf = &image->planes[plane].primary_surface.isl;
1103*61046927SAndroid Build Coastguard Worker uint64_t binding_plane_offset =
1104*61046927SAndroid Build Coastguard Worker image->planes[plane].primary_surface.memory_range.offset;
1105*61046927SAndroid Build Coastguard Worker struct isl_tile_info tile_info;
1106*61046927SAndroid Build Coastguard Worker isl_surf_get_tile_info(surf, &tile_info);
1107*61046927SAndroid Build Coastguard Worker uint64_t layer1_offset;
1108*61046927SAndroid Build Coastguard Worker uint32_t x_off, y_off;
1109*61046927SAndroid Build Coastguard Worker
1110*61046927SAndroid Build Coastguard Worker /* Treat the whole thing as a single miptail. We should have already
1111*61046927SAndroid Build Coastguard Worker * reported this image as VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT.
1112*61046927SAndroid Build Coastguard Worker *
1113*61046927SAndroid Build Coastguard Worker * In theory we could try to make ISL massage the alignments so that we
1114*61046927SAndroid Build Coastguard Worker * could at least claim mip level 0 to be not part of the miptail, but
1115*61046927SAndroid Build Coastguard Worker * that could end up wasting a lot of memory, so it's better to do
1116*61046927SAndroid Build Coastguard Worker * nothing and focus our efforts into making things use the appropriate
1117*61046927SAndroid Build Coastguard Worker * tiling formats that give us the standard block shapes.
1118*61046927SAndroid Build Coastguard Worker */
1119*61046927SAndroid Build Coastguard Worker if (isl_calc_tile_size(&tile_info) != ANV_SPARSE_BLOCK_SIZE)
1120*61046927SAndroid Build Coastguard Worker goto out_everything_is_miptail;
1121*61046927SAndroid Build Coastguard Worker
1122*61046927SAndroid Build Coastguard Worker assert(surf->tiling != ISL_TILING_LINEAR);
1123*61046927SAndroid Build Coastguard Worker
1124*61046927SAndroid Build Coastguard Worker if (image->vk.array_layers == 1) {
1125*61046927SAndroid Build Coastguard Worker layer1_offset = surf->size_B;
1126*61046927SAndroid Build Coastguard Worker } else {
1127*61046927SAndroid Build Coastguard Worker isl_surf_get_image_offset_B_tile_sa(surf, 0, 1, 0, &layer1_offset,
1128*61046927SAndroid Build Coastguard Worker &x_off, &y_off);
1129*61046927SAndroid Build Coastguard Worker if (x_off || y_off)
1130*61046927SAndroid Build Coastguard Worker goto out_everything_is_miptail;
1131*61046927SAndroid Build Coastguard Worker }
1132*61046927SAndroid Build Coastguard Worker assert(layer1_offset % ANV_SPARSE_BLOCK_SIZE == 0);
1133*61046927SAndroid Build Coastguard Worker
1134*61046927SAndroid Build Coastguard Worker /* We could try to do better here, but there's not really any point since
1135*61046927SAndroid Build Coastguard Worker * we should be supporting the appropriate tiling formats everywhere.
1136*61046927SAndroid Build Coastguard Worker */
1137*61046927SAndroid Build Coastguard Worker if (!isl_tiling_supports_standard_block_shapes(surf->tiling))
1138*61046927SAndroid Build Coastguard Worker goto out_everything_is_miptail;
1139*61046927SAndroid Build Coastguard Worker
1140*61046927SAndroid Build Coastguard Worker int miptail_first_level = surf->miptail_start_level;
1141*61046927SAndroid Build Coastguard Worker if (miptail_first_level >= image->vk.mip_levels)
1142*61046927SAndroid Build Coastguard Worker goto out_no_miptail;
1143*61046927SAndroid Build Coastguard Worker
1144*61046927SAndroid Build Coastguard Worker uint64_t miptail_offset = 0;
1145*61046927SAndroid Build Coastguard Worker isl_surf_get_image_offset_B_tile_sa(surf, miptail_first_level, 0, 0,
1146*61046927SAndroid Build Coastguard Worker &miptail_offset,
1147*61046927SAndroid Build Coastguard Worker &x_off, &y_off);
1148*61046927SAndroid Build Coastguard Worker assert(x_off == 0 && y_off == 0);
1149*61046927SAndroid Build Coastguard Worker assert(miptail_offset % ANV_SPARSE_BLOCK_SIZE == 0);
1150*61046927SAndroid Build Coastguard Worker
1151*61046927SAndroid Build Coastguard Worker *imageMipTailFirstLod = miptail_first_level;
1152*61046927SAndroid Build Coastguard Worker *imageMipTailSize = ANV_SPARSE_BLOCK_SIZE;
1153*61046927SAndroid Build Coastguard Worker *imageMipTailOffset = binding_plane_offset + miptail_offset;
1154*61046927SAndroid Build Coastguard Worker *imageMipTailStride = layer1_offset;
1155*61046927SAndroid Build Coastguard Worker goto out_debug;
1156*61046927SAndroid Build Coastguard Worker
1157*61046927SAndroid Build Coastguard Worker out_no_miptail:
1158*61046927SAndroid Build Coastguard Worker *imageMipTailFirstLod = image->vk.mip_levels;
1159*61046927SAndroid Build Coastguard Worker *imageMipTailSize = 0;
1160*61046927SAndroid Build Coastguard Worker *imageMipTailOffset = 0;
1161*61046927SAndroid Build Coastguard Worker *imageMipTailStride = 0;
1162*61046927SAndroid Build Coastguard Worker goto out_debug;
1163*61046927SAndroid Build Coastguard Worker
1164*61046927SAndroid Build Coastguard Worker out_everything_is_miptail:
1165*61046927SAndroid Build Coastguard Worker *imageMipTailFirstLod = 0;
1166*61046927SAndroid Build Coastguard Worker *imageMipTailSize = surf->size_B;
1167*61046927SAndroid Build Coastguard Worker *imageMipTailOffset = binding_plane_offset;
1168*61046927SAndroid Build Coastguard Worker *imageMipTailStride = 0;
1169*61046927SAndroid Build Coastguard Worker
1170*61046927SAndroid Build Coastguard Worker out_debug:
1171*61046927SAndroid Build Coastguard Worker sparse_debug("miptail first_lod:%d size:%"PRIu64" offset:%"PRIu64" "
1172*61046927SAndroid Build Coastguard Worker "stride:%"PRIu64"\n",
1173*61046927SAndroid Build Coastguard Worker *imageMipTailFirstLod, *imageMipTailSize,
1174*61046927SAndroid Build Coastguard Worker *imageMipTailOffset, *imageMipTailStride);
1175*61046927SAndroid Build Coastguard Worker }
1176*61046927SAndroid Build Coastguard Worker
1177*61046927SAndroid Build Coastguard Worker static struct anv_vm_bind
vk_bind_to_anv_vm_bind(struct anv_sparse_binding_data * sparse,const struct VkSparseMemoryBind * vk_bind)1178*61046927SAndroid Build Coastguard Worker vk_bind_to_anv_vm_bind(struct anv_sparse_binding_data *sparse,
1179*61046927SAndroid Build Coastguard Worker const struct VkSparseMemoryBind *vk_bind)
1180*61046927SAndroid Build Coastguard Worker {
1181*61046927SAndroid Build Coastguard Worker struct anv_vm_bind anv_bind = {
1182*61046927SAndroid Build Coastguard Worker .bo = NULL,
1183*61046927SAndroid Build Coastguard Worker .address = sparse->address + vk_bind->resourceOffset,
1184*61046927SAndroid Build Coastguard Worker .bo_offset = 0,
1185*61046927SAndroid Build Coastguard Worker .size = vk_bind->size,
1186*61046927SAndroid Build Coastguard Worker .op = ANV_VM_BIND,
1187*61046927SAndroid Build Coastguard Worker };
1188*61046927SAndroid Build Coastguard Worker
1189*61046927SAndroid Build Coastguard Worker assert(vk_bind->size);
1190*61046927SAndroid Build Coastguard Worker assert(vk_bind->resourceOffset + vk_bind->size <= sparse->size);
1191*61046927SAndroid Build Coastguard Worker
1192*61046927SAndroid Build Coastguard Worker if (vk_bind->memory != VK_NULL_HANDLE) {
1193*61046927SAndroid Build Coastguard Worker anv_bind.bo = anv_device_memory_from_handle(vk_bind->memory)->bo;
1194*61046927SAndroid Build Coastguard Worker anv_bind.bo_offset = vk_bind->memoryOffset,
1195*61046927SAndroid Build Coastguard Worker assert(vk_bind->memoryOffset + vk_bind->size <= anv_bind.bo->size);
1196*61046927SAndroid Build Coastguard Worker }
1197*61046927SAndroid Build Coastguard Worker
1198*61046927SAndroid Build Coastguard Worker return anv_bind;
1199*61046927SAndroid Build Coastguard Worker }
1200*61046927SAndroid Build Coastguard Worker
1201*61046927SAndroid Build Coastguard Worker static VkResult
anv_sparse_bind_resource_memory(struct anv_device * device,struct anv_sparse_binding_data * sparse,uint64_t resource_size,const VkSparseMemoryBind * vk_bind,struct anv_sparse_submission * submit)1202*61046927SAndroid Build Coastguard Worker anv_sparse_bind_resource_memory(struct anv_device *device,
1203*61046927SAndroid Build Coastguard Worker struct anv_sparse_binding_data *sparse,
1204*61046927SAndroid Build Coastguard Worker uint64_t resource_size,
1205*61046927SAndroid Build Coastguard Worker const VkSparseMemoryBind *vk_bind,
1206*61046927SAndroid Build Coastguard Worker struct anv_sparse_submission *submit)
1207*61046927SAndroid Build Coastguard Worker {
1208*61046927SAndroid Build Coastguard Worker struct anv_vm_bind bind = vk_bind_to_anv_vm_bind(sparse, vk_bind);
1209*61046927SAndroid Build Coastguard Worker uint64_t rem = vk_bind->size % ANV_SPARSE_BLOCK_SIZE;
1210*61046927SAndroid Build Coastguard Worker
1211*61046927SAndroid Build Coastguard Worker if (rem != 0) {
1212*61046927SAndroid Build Coastguard Worker if (vk_bind->resourceOffset + vk_bind->size == resource_size)
1213*61046927SAndroid Build Coastguard Worker bind.size += ANV_SPARSE_BLOCK_SIZE - rem;
1214*61046927SAndroid Build Coastguard Worker else
1215*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_VALIDATION_FAILED_EXT);
1216*61046927SAndroid Build Coastguard Worker }
1217*61046927SAndroid Build Coastguard Worker
1218*61046927SAndroid Build Coastguard Worker return anv_sparse_submission_add(device, submit, &bind);
1219*61046927SAndroid Build Coastguard Worker }
1220*61046927SAndroid Build Coastguard Worker
1221*61046927SAndroid Build Coastguard Worker VkResult
anv_sparse_bind_buffer(struct anv_device * device,struct anv_buffer * buffer,const VkSparseMemoryBind * vk_bind,struct anv_sparse_submission * submit)1222*61046927SAndroid Build Coastguard Worker anv_sparse_bind_buffer(struct anv_device *device,
1223*61046927SAndroid Build Coastguard Worker struct anv_buffer *buffer,
1224*61046927SAndroid Build Coastguard Worker const VkSparseMemoryBind *vk_bind,
1225*61046927SAndroid Build Coastguard Worker struct anv_sparse_submission *submit)
1226*61046927SAndroid Build Coastguard Worker {
1227*61046927SAndroid Build Coastguard Worker return anv_sparse_bind_resource_memory(device, &buffer->sparse_data,
1228*61046927SAndroid Build Coastguard Worker buffer->vk.size,
1229*61046927SAndroid Build Coastguard Worker vk_bind, submit);
1230*61046927SAndroid Build Coastguard Worker }
1231*61046927SAndroid Build Coastguard Worker
1232*61046927SAndroid Build Coastguard Worker VkResult
anv_sparse_bind_image_opaque(struct anv_device * device,struct anv_image * image,const VkSparseMemoryBind * vk_bind,struct anv_sparse_submission * submit)1233*61046927SAndroid Build Coastguard Worker anv_sparse_bind_image_opaque(struct anv_device *device,
1234*61046927SAndroid Build Coastguard Worker struct anv_image *image,
1235*61046927SAndroid Build Coastguard Worker const VkSparseMemoryBind *vk_bind,
1236*61046927SAndroid Build Coastguard Worker struct anv_sparse_submission *submit)
1237*61046927SAndroid Build Coastguard Worker {
1238*61046927SAndroid Build Coastguard Worker struct anv_image_binding *b =
1239*61046927SAndroid Build Coastguard Worker &image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN];
1240*61046927SAndroid Build Coastguard Worker assert(!image->disjoint);
1241*61046927SAndroid Build Coastguard Worker
1242*61046927SAndroid Build Coastguard Worker if (INTEL_DEBUG(DEBUG_SPARSE)) {
1243*61046927SAndroid Build Coastguard Worker sparse_debug("%s:\n", __func__);
1244*61046927SAndroid Build Coastguard Worker dump_anv_image(image);
1245*61046927SAndroid Build Coastguard Worker u_foreach_bit(b, image->vk.aspects) {
1246*61046927SAndroid Build Coastguard Worker VkImageAspectFlagBits aspect = 1 << b;
1247*61046927SAndroid Build Coastguard Worker const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
1248*61046927SAndroid Build Coastguard Worker struct isl_surf *surf = &image->planes[plane].primary_surface.isl;
1249*61046927SAndroid Build Coastguard Worker sparse_debug("aspect 0x%x (plane %d):\n", aspect, plane);
1250*61046927SAndroid Build Coastguard Worker dump_isl_surf(surf);
1251*61046927SAndroid Build Coastguard Worker }
1252*61046927SAndroid Build Coastguard Worker sparse_debug("\n");
1253*61046927SAndroid Build Coastguard Worker }
1254*61046927SAndroid Build Coastguard Worker
1255*61046927SAndroid Build Coastguard Worker return anv_sparse_bind_resource_memory(device, &b->sparse_data,
1256*61046927SAndroid Build Coastguard Worker b->memory_range.size,
1257*61046927SAndroid Build Coastguard Worker vk_bind, submit);
1258*61046927SAndroid Build Coastguard Worker }
1259*61046927SAndroid Build Coastguard Worker
1260*61046927SAndroid Build Coastguard Worker VkResult
anv_sparse_bind_image_memory(struct anv_queue * queue,struct anv_image * image,const VkSparseImageMemoryBind * bind,struct anv_sparse_submission * submit)1261*61046927SAndroid Build Coastguard Worker anv_sparse_bind_image_memory(struct anv_queue *queue,
1262*61046927SAndroid Build Coastguard Worker struct anv_image *image,
1263*61046927SAndroid Build Coastguard Worker const VkSparseImageMemoryBind *bind,
1264*61046927SAndroid Build Coastguard Worker struct anv_sparse_submission *submit)
1265*61046927SAndroid Build Coastguard Worker {
1266*61046927SAndroid Build Coastguard Worker struct anv_device *device = queue->device;
1267*61046927SAndroid Build Coastguard Worker VkImageAspectFlags aspect = bind->subresource.aspectMask;
1268*61046927SAndroid Build Coastguard Worker uint32_t mip_level = bind->subresource.mipLevel;
1269*61046927SAndroid Build Coastguard Worker uint32_t array_layer = bind->subresource.arrayLayer;
1270*61046927SAndroid Build Coastguard Worker
1271*61046927SAndroid Build Coastguard Worker assert(!(bind->flags & VK_SPARSE_MEMORY_BIND_METADATA_BIT));
1272*61046927SAndroid Build Coastguard Worker
1273*61046927SAndroid Build Coastguard Worker struct anv_image_binding *img_binding = image->disjoint ?
1274*61046927SAndroid Build Coastguard Worker anv_image_aspect_to_binding(image, aspect) :
1275*61046927SAndroid Build Coastguard Worker &image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN];
1276*61046927SAndroid Build Coastguard Worker struct anv_sparse_binding_data *sparse_data = &img_binding->sparse_data;
1277*61046927SAndroid Build Coastguard Worker
1278*61046927SAndroid Build Coastguard Worker const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
1279*61046927SAndroid Build Coastguard Worker struct isl_surf *surf = &image->planes[plane].primary_surface.isl;
1280*61046927SAndroid Build Coastguard Worker uint64_t binding_plane_offset =
1281*61046927SAndroid Build Coastguard Worker image->planes[plane].primary_surface.memory_range.offset;
1282*61046927SAndroid Build Coastguard Worker const struct isl_format_layout *layout =
1283*61046927SAndroid Build Coastguard Worker isl_format_get_layout(surf->format);
1284*61046927SAndroid Build Coastguard Worker struct isl_tile_info tile_info;
1285*61046927SAndroid Build Coastguard Worker isl_surf_get_tile_info(surf, &tile_info);
1286*61046927SAndroid Build Coastguard Worker
1287*61046927SAndroid Build Coastguard Worker if (INTEL_DEBUG(DEBUG_SPARSE)) {
1288*61046927SAndroid Build Coastguard Worker sparse_debug("%s:\n", __func__);
1289*61046927SAndroid Build Coastguard Worker sparse_debug("mip_level:%d array_layer:%d\n", mip_level, array_layer);
1290*61046927SAndroid Build Coastguard Worker sparse_debug("aspect:0x%x plane:%d\n", aspect, plane);
1291*61046927SAndroid Build Coastguard Worker sparse_debug("binding offset: [%d, %d, %d] extent: [%d, %d, %d]\n",
1292*61046927SAndroid Build Coastguard Worker bind->offset.x, bind->offset.y, bind->offset.z,
1293*61046927SAndroid Build Coastguard Worker bind->extent.width, bind->extent.height,
1294*61046927SAndroid Build Coastguard Worker bind->extent.depth);
1295*61046927SAndroid Build Coastguard Worker dump_anv_image(image);
1296*61046927SAndroid Build Coastguard Worker dump_isl_surf(surf);
1297*61046927SAndroid Build Coastguard Worker sparse_debug("\n");
1298*61046927SAndroid Build Coastguard Worker }
1299*61046927SAndroid Build Coastguard Worker
1300*61046927SAndroid Build Coastguard Worker VkExtent3D block_shape_px =
1301*61046927SAndroid Build Coastguard Worker anv_sparse_calc_block_shape(device->physical, surf, &tile_info);
1302*61046927SAndroid Build Coastguard Worker VkExtent3D block_shape_el = vk_extent3d_px_to_el(block_shape_px, layout);
1303*61046927SAndroid Build Coastguard Worker
1304*61046927SAndroid Build Coastguard Worker /* Both bind->offset and bind->extent are in pixel units. */
1305*61046927SAndroid Build Coastguard Worker VkOffset3D bind_offset_el = vk_offset3d_px_to_el(bind->offset, layout);
1306*61046927SAndroid Build Coastguard Worker
1307*61046927SAndroid Build Coastguard Worker /* The spec says we only really need to align if for a given coordinate
1308*61046927SAndroid Build Coastguard Worker * offset + extent equals the corresponding dimensions of the image
1309*61046927SAndroid Build Coastguard Worker * subresource, but all the other non-aligned usage is invalid, so just
1310*61046927SAndroid Build Coastguard Worker * align everything.
1311*61046927SAndroid Build Coastguard Worker */
1312*61046927SAndroid Build Coastguard Worker VkExtent3D bind_extent_px = {
1313*61046927SAndroid Build Coastguard Worker .width = ALIGN_NPOT(bind->extent.width, block_shape_px.width),
1314*61046927SAndroid Build Coastguard Worker .height = ALIGN_NPOT(bind->extent.height, block_shape_px.height),
1315*61046927SAndroid Build Coastguard Worker .depth = ALIGN_NPOT(bind->extent.depth, block_shape_px.depth),
1316*61046927SAndroid Build Coastguard Worker };
1317*61046927SAndroid Build Coastguard Worker VkExtent3D bind_extent_el = vk_extent3d_px_to_el(bind_extent_px, layout);
1318*61046927SAndroid Build Coastguard Worker
1319*61046927SAndroid Build Coastguard Worker /* Nothing that has a tile_size different than ANV_SPARSE_BLOCK_SIZE should
1320*61046927SAndroid Build Coastguard Worker * be reaching here, as these cases should be treated as "everything is
1321*61046927SAndroid Build Coastguard Worker * part of the miptail" (see anv_sparse_calc_miptail_properties()).
1322*61046927SAndroid Build Coastguard Worker */
1323*61046927SAndroid Build Coastguard Worker assert(isl_calc_tile_size(&tile_info) == ANV_SPARSE_BLOCK_SIZE);
1324*61046927SAndroid Build Coastguard Worker
1325*61046927SAndroid Build Coastguard Worker /* How many blocks are necessary to form a whole line on this image? */
1326*61046927SAndroid Build Coastguard Worker const uint32_t blocks_per_line = surf->row_pitch_B / (layout->bpb / 8) /
1327*61046927SAndroid Build Coastguard Worker block_shape_el.width;
1328*61046927SAndroid Build Coastguard Worker /* The loop below will try to bind a whole line of blocks at a time as
1329*61046927SAndroid Build Coastguard Worker * they're guaranteed to be contiguous, so we calculate how many blocks
1330*61046927SAndroid Build Coastguard Worker * that is and how big is each block to figure the bind size of a whole
1331*61046927SAndroid Build Coastguard Worker * line.
1332*61046927SAndroid Build Coastguard Worker */
1333*61046927SAndroid Build Coastguard Worker uint64_t line_bind_size_in_blocks = bind_extent_el.width /
1334*61046927SAndroid Build Coastguard Worker block_shape_el.width;
1335*61046927SAndroid Build Coastguard Worker uint64_t line_bind_size = line_bind_size_in_blocks * ANV_SPARSE_BLOCK_SIZE;
1336*61046927SAndroid Build Coastguard Worker assert(line_bind_size_in_blocks != 0);
1337*61046927SAndroid Build Coastguard Worker assert(line_bind_size != 0);
1338*61046927SAndroid Build Coastguard Worker
1339*61046927SAndroid Build Coastguard Worker uint64_t memory_offset = bind->memoryOffset;
1340*61046927SAndroid Build Coastguard Worker for (uint32_t z = bind_offset_el.z;
1341*61046927SAndroid Build Coastguard Worker z < bind_offset_el.z + bind_extent_el.depth;
1342*61046927SAndroid Build Coastguard Worker z += block_shape_el.depth) {
1343*61046927SAndroid Build Coastguard Worker uint64_t subresource_offset_B;
1344*61046927SAndroid Build Coastguard Worker uint32_t subresource_x_offset, subresource_y_offset;
1345*61046927SAndroid Build Coastguard Worker isl_surf_get_image_offset_B_tile_sa(surf, mip_level, array_layer, z,
1346*61046927SAndroid Build Coastguard Worker &subresource_offset_B,
1347*61046927SAndroid Build Coastguard Worker &subresource_x_offset,
1348*61046927SAndroid Build Coastguard Worker &subresource_y_offset);
1349*61046927SAndroid Build Coastguard Worker assert(subresource_x_offset == 0 && subresource_y_offset == 0);
1350*61046927SAndroid Build Coastguard Worker assert(subresource_offset_B % ANV_SPARSE_BLOCK_SIZE == 0);
1351*61046927SAndroid Build Coastguard Worker
1352*61046927SAndroid Build Coastguard Worker for (uint32_t y = bind_offset_el.y;
1353*61046927SAndroid Build Coastguard Worker y < bind_offset_el.y + bind_extent_el.height;
1354*61046927SAndroid Build Coastguard Worker y+= block_shape_el.height) {
1355*61046927SAndroid Build Coastguard Worker uint32_t line_block_offset = y / block_shape_el.height *
1356*61046927SAndroid Build Coastguard Worker blocks_per_line;
1357*61046927SAndroid Build Coastguard Worker uint64_t line_start_B = subresource_offset_B +
1358*61046927SAndroid Build Coastguard Worker line_block_offset * ANV_SPARSE_BLOCK_SIZE;
1359*61046927SAndroid Build Coastguard Worker uint64_t bind_offset_B = line_start_B +
1360*61046927SAndroid Build Coastguard Worker (bind_offset_el.x / block_shape_el.width) *
1361*61046927SAndroid Build Coastguard Worker ANV_SPARSE_BLOCK_SIZE;
1362*61046927SAndroid Build Coastguard Worker
1363*61046927SAndroid Build Coastguard Worker VkSparseMemoryBind opaque_bind = {
1364*61046927SAndroid Build Coastguard Worker .resourceOffset = binding_plane_offset + bind_offset_B,
1365*61046927SAndroid Build Coastguard Worker .size = line_bind_size,
1366*61046927SAndroid Build Coastguard Worker .memory = bind->memory,
1367*61046927SAndroid Build Coastguard Worker .memoryOffset = memory_offset,
1368*61046927SAndroid Build Coastguard Worker .flags = bind->flags,
1369*61046927SAndroid Build Coastguard Worker };
1370*61046927SAndroid Build Coastguard Worker
1371*61046927SAndroid Build Coastguard Worker memory_offset += line_bind_size;
1372*61046927SAndroid Build Coastguard Worker
1373*61046927SAndroid Build Coastguard Worker assert(line_start_B % ANV_SPARSE_BLOCK_SIZE == 0);
1374*61046927SAndroid Build Coastguard Worker assert(opaque_bind.resourceOffset % ANV_SPARSE_BLOCK_SIZE == 0);
1375*61046927SAndroid Build Coastguard Worker assert(opaque_bind.size % ANV_SPARSE_BLOCK_SIZE == 0);
1376*61046927SAndroid Build Coastguard Worker
1377*61046927SAndroid Build Coastguard Worker struct anv_vm_bind anv_bind = vk_bind_to_anv_vm_bind(sparse_data,
1378*61046927SAndroid Build Coastguard Worker &opaque_bind);
1379*61046927SAndroid Build Coastguard Worker VkResult result = anv_sparse_submission_add(device, submit,
1380*61046927SAndroid Build Coastguard Worker &anv_bind);
1381*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
1382*61046927SAndroid Build Coastguard Worker return result;
1383*61046927SAndroid Build Coastguard Worker }
1384*61046927SAndroid Build Coastguard Worker }
1385*61046927SAndroid Build Coastguard Worker
1386*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
1387*61046927SAndroid Build Coastguard Worker }
1388*61046927SAndroid Build Coastguard Worker
1389*61046927SAndroid Build Coastguard Worker VkResult
anv_sparse_image_check_support(struct anv_physical_device * pdevice,VkImageCreateFlags flags,VkImageTiling tiling,VkSampleCountFlagBits samples,VkImageType type,VkFormat vk_format)1390*61046927SAndroid Build Coastguard Worker anv_sparse_image_check_support(struct anv_physical_device *pdevice,
1391*61046927SAndroid Build Coastguard Worker VkImageCreateFlags flags,
1392*61046927SAndroid Build Coastguard Worker VkImageTiling tiling,
1393*61046927SAndroid Build Coastguard Worker VkSampleCountFlagBits samples,
1394*61046927SAndroid Build Coastguard Worker VkImageType type,
1395*61046927SAndroid Build Coastguard Worker VkFormat vk_format)
1396*61046927SAndroid Build Coastguard Worker {
1397*61046927SAndroid Build Coastguard Worker assert(flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT);
1398*61046927SAndroid Build Coastguard Worker
1399*61046927SAndroid Build Coastguard Worker /* The spec says:
1400*61046927SAndroid Build Coastguard Worker * "A sparse image created using VK_IMAGE_CREATE_SPARSE_BINDING_BIT (but
1401*61046927SAndroid Build Coastguard Worker * not VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) supports all formats that
1402*61046927SAndroid Build Coastguard Worker * non-sparse usage supports, and supports both VK_IMAGE_TILING_OPTIMAL
1403*61046927SAndroid Build Coastguard Worker * and VK_IMAGE_TILING_LINEAR tiling."
1404*61046927SAndroid Build Coastguard Worker */
1405*61046927SAndroid Build Coastguard Worker if (!(flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT))
1406*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
1407*61046927SAndroid Build Coastguard Worker
1408*61046927SAndroid Build Coastguard Worker if (type == VK_IMAGE_TYPE_1D)
1409*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1410*61046927SAndroid Build Coastguard Worker
1411*61046927SAndroid Build Coastguard Worker /* From here on, these are the rules:
1412*61046927SAndroid Build Coastguard Worker * "A sparse image created using VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT
1413*61046927SAndroid Build Coastguard Worker * supports all non-compressed color formats with power-of-two element
1414*61046927SAndroid Build Coastguard Worker * size that non-sparse usage supports. Additional formats may also be
1415*61046927SAndroid Build Coastguard Worker * supported and can be queried via
1416*61046927SAndroid Build Coastguard Worker * vkGetPhysicalDeviceSparseImageFormatProperties.
1417*61046927SAndroid Build Coastguard Worker * VK_IMAGE_TILING_LINEAR tiling is not supported."
1418*61046927SAndroid Build Coastguard Worker */
1419*61046927SAndroid Build Coastguard Worker
1420*61046927SAndroid Build Coastguard Worker /* We choose not to support sparse residency on emulated compressed
1421*61046927SAndroid Build Coastguard Worker * formats due to the additional image plane. It would make the
1422*61046927SAndroid Build Coastguard Worker * implementation extremely complicated.
1423*61046927SAndroid Build Coastguard Worker */
1424*61046927SAndroid Build Coastguard Worker if (anv_is_format_emulated(pdevice, vk_format))
1425*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1426*61046927SAndroid Build Coastguard Worker
1427*61046927SAndroid Build Coastguard Worker /* While the spec itself says linear is not supported (see above), deqp-vk
1428*61046927SAndroid Build Coastguard Worker * tries anyway to create linear sparse images, so we have to check for it.
1429*61046927SAndroid Build Coastguard Worker * This is also said in VUID-VkImageCreateInfo-tiling-04121:
1430*61046927SAndroid Build Coastguard Worker * "If tiling is VK_IMAGE_TILING_LINEAR, flags must not contain
1431*61046927SAndroid Build Coastguard Worker * VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT"
1432*61046927SAndroid Build Coastguard Worker */
1433*61046927SAndroid Build Coastguard Worker if (tiling == VK_IMAGE_TILING_LINEAR)
1434*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1435*61046927SAndroid Build Coastguard Worker
1436*61046927SAndroid Build Coastguard Worker if ((samples & VK_SAMPLE_COUNT_2_BIT &&
1437*61046927SAndroid Build Coastguard Worker !pdevice->vk.supported_features.sparseResidency2Samples) ||
1438*61046927SAndroid Build Coastguard Worker (samples & VK_SAMPLE_COUNT_4_BIT &&
1439*61046927SAndroid Build Coastguard Worker !pdevice->vk.supported_features.sparseResidency4Samples) ||
1440*61046927SAndroid Build Coastguard Worker (samples & VK_SAMPLE_COUNT_8_BIT &&
1441*61046927SAndroid Build Coastguard Worker !pdevice->vk.supported_features.sparseResidency8Samples) ||
1442*61046927SAndroid Build Coastguard Worker (samples & VK_SAMPLE_COUNT_16_BIT &&
1443*61046927SAndroid Build Coastguard Worker !pdevice->vk.supported_features.sparseResidency16Samples) ||
1444*61046927SAndroid Build Coastguard Worker samples & VK_SAMPLE_COUNT_32_BIT ||
1445*61046927SAndroid Build Coastguard Worker samples & VK_SAMPLE_COUNT_64_BIT)
1446*61046927SAndroid Build Coastguard Worker return VK_ERROR_FEATURE_NOT_PRESENT;
1447*61046927SAndroid Build Coastguard Worker
1448*61046927SAndroid Build Coastguard Worker /* While the Vulkan spec allows us to support depth/stencil sparse images
1449*61046927SAndroid Build Coastguard Worker * everywhere, sometimes we're not able to have them with the tiling
1450*61046927SAndroid Build Coastguard Worker * formats that give us the standard block shapes. Having standard block
1451*61046927SAndroid Build Coastguard Worker * shapes is higher priority than supporting depth/stencil sparse images.
1452*61046927SAndroid Build Coastguard Worker *
1453*61046927SAndroid Build Coastguard Worker * Please see ISL's filter_tiling() functions for accurate explanations on
1454*61046927SAndroid Build Coastguard Worker * why depth/stencil images are not always supported with the tiling
1455*61046927SAndroid Build Coastguard Worker * formats we want. But in short: depth/stencil support in our HW is
1456*61046927SAndroid Build Coastguard Worker * limited to 2D and we can't build a 2D view of a 3D image with these
1457*61046927SAndroid Build Coastguard Worker * tiling formats due to the address swizzling being different.
1458*61046927SAndroid Build Coastguard Worker */
1459*61046927SAndroid Build Coastguard Worker VkImageAspectFlags aspects = vk_format_aspects(vk_format);
1460*61046927SAndroid Build Coastguard Worker if (aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
1461*61046927SAndroid Build Coastguard Worker /* For multi-sampled images, the image layouts for color and
1462*61046927SAndroid Build Coastguard Worker * depth/stencil are different, and only the color layout is compatible
1463*61046927SAndroid Build Coastguard Worker * with the standard block shapes.
1464*61046927SAndroid Build Coastguard Worker */
1465*61046927SAndroid Build Coastguard Worker if (samples != VK_SAMPLE_COUNT_1_BIT)
1466*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1467*61046927SAndroid Build Coastguard Worker
1468*61046927SAndroid Build Coastguard Worker /* For 125+, isl_gfx125_filter_tiling() claims 3D is not supported.
1469*61046927SAndroid Build Coastguard Worker * For the previous platforms, isl_gfx6_filter_tiling() says only 2D is
1470*61046927SAndroid Build Coastguard Worker * supported.
1471*61046927SAndroid Build Coastguard Worker */
1472*61046927SAndroid Build Coastguard Worker if (pdevice->info.verx10 >= 125) {
1473*61046927SAndroid Build Coastguard Worker if (type == VK_IMAGE_TYPE_3D)
1474*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1475*61046927SAndroid Build Coastguard Worker } else {
1476*61046927SAndroid Build Coastguard Worker if (type != VK_IMAGE_TYPE_2D)
1477*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1478*61046927SAndroid Build Coastguard Worker }
1479*61046927SAndroid Build Coastguard Worker }
1480*61046927SAndroid Build Coastguard Worker
1481*61046927SAndroid Build Coastguard Worker const struct anv_format *anv_format = anv_get_format(vk_format);
1482*61046927SAndroid Build Coastguard Worker if (!anv_format)
1483*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1484*61046927SAndroid Build Coastguard Worker
1485*61046927SAndroid Build Coastguard Worker for (int p = 0; p < anv_format->n_planes; p++) {
1486*61046927SAndroid Build Coastguard Worker enum isl_format isl_format = anv_format->planes[p].isl_format;
1487*61046927SAndroid Build Coastguard Worker
1488*61046927SAndroid Build Coastguard Worker if (isl_format == ISL_FORMAT_UNSUPPORTED)
1489*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1490*61046927SAndroid Build Coastguard Worker
1491*61046927SAndroid Build Coastguard Worker const struct isl_format_layout *isl_layout =
1492*61046927SAndroid Build Coastguard Worker isl_format_get_layout(isl_format);
1493*61046927SAndroid Build Coastguard Worker
1494*61046927SAndroid Build Coastguard Worker /* As quoted above, we only need to support the power-of-two formats.
1495*61046927SAndroid Build Coastguard Worker * The problem with the non-power-of-two formats is that we need an
1496*61046927SAndroid Build Coastguard Worker * integer number of pixels to fit into a sparse block, so we'd need the
1497*61046927SAndroid Build Coastguard Worker * sparse block sizes to be, for example, 192k for 24bpp.
1498*61046927SAndroid Build Coastguard Worker *
1499*61046927SAndroid Build Coastguard Worker * TODO: add support for these formats.
1500*61046927SAndroid Build Coastguard Worker */
1501*61046927SAndroid Build Coastguard Worker if (isl_layout->bpb != 8 && isl_layout->bpb != 16 &&
1502*61046927SAndroid Build Coastguard Worker isl_layout->bpb != 32 && isl_layout->bpb != 64 &&
1503*61046927SAndroid Build Coastguard Worker isl_layout->bpb != 128)
1504*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1505*61046927SAndroid Build Coastguard Worker
1506*61046927SAndroid Build Coastguard Worker /* ISL_TILING_64_XE2_BIT's block shapes are not always Vulkan's standard
1507*61046927SAndroid Build Coastguard Worker * block shapes, so exclude what's non-standard.
1508*61046927SAndroid Build Coastguard Worker */
1509*61046927SAndroid Build Coastguard Worker if (pdevice->info.ver == 20) {
1510*61046927SAndroid Build Coastguard Worker switch (samples) {
1511*61046927SAndroid Build Coastguard Worker case VK_SAMPLE_COUNT_2_BIT:
1512*61046927SAndroid Build Coastguard Worker if (isl_layout->bpb == 128)
1513*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1514*61046927SAndroid Build Coastguard Worker break;
1515*61046927SAndroid Build Coastguard Worker case VK_SAMPLE_COUNT_8_BIT:
1516*61046927SAndroid Build Coastguard Worker if (isl_layout->bpb == 8 || isl_layout->bpb == 32)
1517*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1518*61046927SAndroid Build Coastguard Worker break;
1519*61046927SAndroid Build Coastguard Worker case VK_SAMPLE_COUNT_16_BIT:
1520*61046927SAndroid Build Coastguard Worker if (isl_layout->bpb == 64)
1521*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1522*61046927SAndroid Build Coastguard Worker break;
1523*61046927SAndroid Build Coastguard Worker default:
1524*61046927SAndroid Build Coastguard Worker break;
1525*61046927SAndroid Build Coastguard Worker }
1526*61046927SAndroid Build Coastguard Worker }
1527*61046927SAndroid Build Coastguard Worker }
1528*61046927SAndroid Build Coastguard Worker
1529*61046927SAndroid Build Coastguard Worker /* These YUV formats are considered by Vulkan to be compressed 2x1 blocks.
1530*61046927SAndroid Build Coastguard Worker * We don't need to support them since they're compressed. On Gfx12 we
1531*61046927SAndroid Build Coastguard Worker * can't even have Tile64 for them. Once we do support these formats we'll
1532*61046927SAndroid Build Coastguard Worker * have to report the correct block shapes because dEQP cares about them,
1533*61046927SAndroid Build Coastguard Worker * and we'll have to adjust for the fact that ISL treats these as 16bpp 1x1
1534*61046927SAndroid Build Coastguard Worker * blocks instead of 32bpp 2x1 compressed blocks (as block shapes are
1535*61046927SAndroid Build Coastguard Worker * reported in units of compressed blocks).
1536*61046927SAndroid Build Coastguard Worker */
1537*61046927SAndroid Build Coastguard Worker if (vk_format == VK_FORMAT_G8B8G8R8_422_UNORM ||
1538*61046927SAndroid Build Coastguard Worker vk_format == VK_FORMAT_B8G8R8G8_422_UNORM)
1539*61046927SAndroid Build Coastguard Worker return VK_ERROR_FORMAT_NOT_SUPPORTED;
1540*61046927SAndroid Build Coastguard Worker
1541*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
1542*61046927SAndroid Build Coastguard Worker }
1543