1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 *
5 * SPDX-License-Identifier: MIT
6 */
7 #include "nir/nir_builder.h"
8 #include "radv_entrypoints.h"
9 #include "radv_meta.h"
10 #include "vk_common_entrypoints.h"
11 #include "vk_shader_module.h"
12
13 /*
14 * GFX queue: Compute shader implementation of image->buffer copy
15 * Compute queue: implementation also of buffer->image, image->image, and image clear.
16 */
17
18 static nir_shader *
build_nir_itob_compute_shader(struct radv_device * dev,bool is_3d)19 build_nir_itob_compute_shader(struct radv_device *dev, bool is_3d)
20 {
21 enum glsl_sampler_dim dim = is_3d ? GLSL_SAMPLER_DIM_3D : GLSL_SAMPLER_DIM_2D;
22 const struct glsl_type *sampler_type = glsl_sampler_type(dim, false, false, GLSL_TYPE_FLOAT);
23 const struct glsl_type *img_type = glsl_image_type(GLSL_SAMPLER_DIM_BUF, false, GLSL_TYPE_FLOAT);
24 nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_COMPUTE, is_3d ? "meta_itob_cs_3d" : "meta_itob_cs");
25 b.shader->info.workgroup_size[0] = 8;
26 b.shader->info.workgroup_size[1] = 8;
27 nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform, sampler_type, "s_tex");
28 input_img->data.descriptor_set = 0;
29 input_img->data.binding = 0;
30
31 nir_variable *output_img = nir_variable_create(b.shader, nir_var_image, img_type, "out_img");
32 output_img->data.descriptor_set = 0;
33 output_img->data.binding = 1;
34
35 nir_def *global_id = get_global_ids(&b, is_3d ? 3 : 2);
36
37 nir_def *offset = nir_load_push_constant(&b, is_3d ? 3 : 2, 32, nir_imm_int(&b, 0), .range = is_3d ? 12 : 8);
38 nir_def *stride = nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 12), .range = 16);
39
40 nir_def *img_coord = nir_iadd(&b, global_id, offset);
41 nir_def *outval =
42 nir_txf_deref(&b, nir_build_deref_var(&b, input_img), nir_trim_vector(&b, img_coord, 2 + is_3d), NULL);
43
44 nir_def *pos_x = nir_channel(&b, global_id, 0);
45 nir_def *pos_y = nir_channel(&b, global_id, 1);
46
47 nir_def *tmp = nir_imul(&b, pos_y, stride);
48 tmp = nir_iadd(&b, tmp, pos_x);
49
50 nir_def *coord = nir_replicate(&b, tmp, 4);
51
52 nir_image_deref_store(&b, &nir_build_deref_var(&b, output_img)->def, coord, nir_undef(&b, 1, 32), outval,
53 nir_imm_int(&b, 0), .image_dim = GLSL_SAMPLER_DIM_BUF);
54
55 return b.shader;
56 }
57
58 static VkResult
get_itob_pipeline_layout(struct radv_device * device,VkPipelineLayout * layout_out)59 get_itob_pipeline_layout(struct radv_device *device, VkPipelineLayout *layout_out)
60 {
61 enum radv_meta_object_key_type key = RADV_META_OBJECT_KEY_COPY_IMAGE_TO_BUFFER;
62
63 const VkDescriptorSetLayoutBinding bindings[] = {
64 {
65 .binding = 0,
66 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
67 .descriptorCount = 1,
68 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
69 },
70 {
71 .binding = 1,
72 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
73 .descriptorCount = 1,
74 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
75 },
76 };
77
78 const VkDescriptorSetLayoutCreateInfo desc_info = {
79 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
80 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT,
81 .bindingCount = 2,
82 .pBindings = bindings,
83 };
84
85 const VkPushConstantRange pc_range = {
86 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
87 .size = 16,
88 };
89
90 return vk_meta_get_pipeline_layout(&device->vk, &device->meta_state.device, &desc_info, &pc_range, &key, sizeof(key),
91 layout_out);
92 }
93
94 struct radv_copy_buffer_image_key {
95 enum radv_meta_object_key_type type;
96 bool is_3d;
97 };
98
99 static VkResult
get_itob_pipeline(struct radv_device * device,const struct radv_image * image,VkPipeline * pipeline_out,VkPipelineLayout * layout_out)100 get_itob_pipeline(struct radv_device *device, const struct radv_image *image, VkPipeline *pipeline_out,
101 VkPipelineLayout *layout_out)
102 {
103 const bool is_3d = image->vk.image_type == VK_IMAGE_TYPE_3D;
104 struct radv_copy_buffer_image_key key;
105 VkResult result;
106
107 result = get_itob_pipeline_layout(device, layout_out);
108 if (result != VK_SUCCESS)
109 return result;
110
111 memset(&key, 0, sizeof(key));
112 key.type = RADV_META_OBJECT_KEY_COPY_IMAGE_TO_BUFFER;
113 key.is_3d = is_3d;
114
115 VkPipeline pipeline_from_cache = vk_meta_lookup_pipeline(&device->meta_state.device, &key, sizeof(key));
116 if (pipeline_from_cache != VK_NULL_HANDLE) {
117 *pipeline_out = pipeline_from_cache;
118 return VK_SUCCESS;
119 }
120
121 nir_shader *cs = build_nir_itob_compute_shader(device, is_3d);
122
123 const VkPipelineShaderStageCreateInfo stage_info = {
124 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
125 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
126 .module = vk_shader_module_handle_from_nir(cs),
127 .pName = "main",
128 .pSpecializationInfo = NULL,
129 };
130
131 const VkComputePipelineCreateInfo pipeline_info = {
132 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
133 .stage = stage_info,
134 .flags = 0,
135 .layout = *layout_out,
136 };
137
138 result = vk_meta_create_compute_pipeline(&device->vk, &device->meta_state.device, &pipeline_info, &key, sizeof(key),
139 pipeline_out);
140
141 ralloc_free(cs);
142 return result;
143 }
144
145 static nir_shader *
build_nir_btoi_compute_shader(struct radv_device * dev,bool is_3d)146 build_nir_btoi_compute_shader(struct radv_device *dev, bool is_3d)
147 {
148 enum glsl_sampler_dim dim = is_3d ? GLSL_SAMPLER_DIM_3D : GLSL_SAMPLER_DIM_2D;
149 const struct glsl_type *buf_type = glsl_sampler_type(GLSL_SAMPLER_DIM_BUF, false, false, GLSL_TYPE_FLOAT);
150 const struct glsl_type *img_type = glsl_image_type(dim, false, GLSL_TYPE_FLOAT);
151 nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_COMPUTE, is_3d ? "meta_btoi_cs_3d" : "meta_btoi_cs");
152 b.shader->info.workgroup_size[0] = 8;
153 b.shader->info.workgroup_size[1] = 8;
154 nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform, buf_type, "s_tex");
155 input_img->data.descriptor_set = 0;
156 input_img->data.binding = 0;
157
158 nir_variable *output_img = nir_variable_create(b.shader, nir_var_image, img_type, "out_img");
159 output_img->data.descriptor_set = 0;
160 output_img->data.binding = 1;
161
162 nir_def *global_id = get_global_ids(&b, is_3d ? 3 : 2);
163
164 nir_def *offset = nir_load_push_constant(&b, is_3d ? 3 : 2, 32, nir_imm_int(&b, 0), .range = is_3d ? 12 : 8);
165 nir_def *stride = nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 12), .range = 16);
166
167 nir_def *pos_x = nir_channel(&b, global_id, 0);
168 nir_def *pos_y = nir_channel(&b, global_id, 1);
169
170 nir_def *buf_coord = nir_imul(&b, pos_y, stride);
171 buf_coord = nir_iadd(&b, buf_coord, pos_x);
172
173 nir_def *coord = nir_iadd(&b, global_id, offset);
174 nir_def *outval = nir_txf_deref(&b, nir_build_deref_var(&b, input_img), buf_coord, NULL);
175
176 nir_def *img_coord = nir_vec4(&b, nir_channel(&b, coord, 0), nir_channel(&b, coord, 1),
177 is_3d ? nir_channel(&b, coord, 2) : nir_undef(&b, 1, 32), nir_undef(&b, 1, 32));
178
179 nir_image_deref_store(&b, &nir_build_deref_var(&b, output_img)->def, img_coord, nir_undef(&b, 1, 32), outval,
180 nir_imm_int(&b, 0), .image_dim = dim);
181
182 return b.shader;
183 }
184
185 static VkResult
get_btoi_pipeline_layout(struct radv_device * device,VkPipelineLayout * layout_out)186 get_btoi_pipeline_layout(struct radv_device *device, VkPipelineLayout *layout_out)
187 {
188 enum radv_meta_object_key_type key = RADV_META_OBJECT_KEY_COPY_BUFFER_TO_IMAGE;
189
190 const VkDescriptorSetLayoutBinding bindings[] = {
191 {
192 .binding = 0,
193 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
194 .descriptorCount = 1,
195 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
196 },
197 {
198 .binding = 1,
199 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
200 .descriptorCount = 1,
201 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
202 },
203 };
204
205 const VkDescriptorSetLayoutCreateInfo desc_info = {
206 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
207 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT,
208 .bindingCount = 2,
209 .pBindings = bindings,
210 };
211
212 const VkPushConstantRange pc_range = {
213 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
214 .size = 16,
215 };
216
217 return vk_meta_get_pipeline_layout(&device->vk, &device->meta_state.device, &desc_info, &pc_range, &key, sizeof(key),
218 layout_out);
219 }
220
221 static VkResult
get_btoi_pipeline(struct radv_device * device,const struct radv_image * image,VkPipeline * pipeline_out,VkPipelineLayout * layout_out)222 get_btoi_pipeline(struct radv_device *device, const struct radv_image *image, VkPipeline *pipeline_out,
223 VkPipelineLayout *layout_out)
224 {
225 const bool is_3d = image->vk.image_type == VK_IMAGE_TYPE_3D;
226 struct radv_copy_buffer_image_key key;
227 VkResult result;
228
229 result = get_btoi_pipeline_layout(device, layout_out);
230 if (result != VK_SUCCESS)
231 return result;
232
233 memset(&key, 0, sizeof(key));
234 key.type = RADV_META_OBJECT_KEY_COPY_BUFFER_TO_IMAGE;
235 key.is_3d = is_3d;
236
237 VkPipeline pipeline_from_cache = vk_meta_lookup_pipeline(&device->meta_state.device, &key, sizeof(key));
238 if (pipeline_from_cache != VK_NULL_HANDLE) {
239 *pipeline_out = pipeline_from_cache;
240 return VK_SUCCESS;
241 }
242
243 nir_shader *cs = build_nir_btoi_compute_shader(device, is_3d);
244
245 const VkPipelineShaderStageCreateInfo stage_info = {
246 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
247 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
248 .module = vk_shader_module_handle_from_nir(cs),
249 .pName = "main",
250 .pSpecializationInfo = NULL,
251 };
252
253 const VkComputePipelineCreateInfo pipeline_info = {
254 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
255 .stage = stage_info,
256 .flags = 0,
257 .layout = *layout_out,
258 };
259
260 result = vk_meta_create_compute_pipeline(&device->vk, &device->meta_state.device, &pipeline_info, &key, sizeof(key),
261 pipeline_out);
262
263 ralloc_free(cs);
264 return result;
265 }
266
267 /* Buffer to image - special path for R32G32B32 */
268 static nir_shader *
build_nir_btoi_r32g32b32_compute_shader(struct radv_device * dev)269 build_nir_btoi_r32g32b32_compute_shader(struct radv_device *dev)
270 {
271 const struct glsl_type *buf_type = glsl_sampler_type(GLSL_SAMPLER_DIM_BUF, false, false, GLSL_TYPE_FLOAT);
272 const struct glsl_type *img_type = glsl_image_type(GLSL_SAMPLER_DIM_BUF, false, GLSL_TYPE_FLOAT);
273 nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_COMPUTE, "meta_btoi_r32g32b32_cs");
274 b.shader->info.workgroup_size[0] = 8;
275 b.shader->info.workgroup_size[1] = 8;
276 nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform, buf_type, "s_tex");
277 input_img->data.descriptor_set = 0;
278 input_img->data.binding = 0;
279
280 nir_variable *output_img = nir_variable_create(b.shader, nir_var_image, img_type, "out_img");
281 output_img->data.descriptor_set = 0;
282 output_img->data.binding = 1;
283
284 nir_def *global_id = get_global_ids(&b, 2);
285
286 nir_def *offset = nir_load_push_constant(&b, 2, 32, nir_imm_int(&b, 0), .range = 8);
287 nir_def *pitch = nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 8), .range = 12);
288 nir_def *stride = nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 12), .range = 16);
289
290 nir_def *pos_x = nir_channel(&b, global_id, 0);
291 nir_def *pos_y = nir_channel(&b, global_id, 1);
292
293 nir_def *buf_coord = nir_imul(&b, pos_y, stride);
294 buf_coord = nir_iadd(&b, buf_coord, pos_x);
295
296 nir_def *img_coord = nir_iadd(&b, global_id, offset);
297
298 nir_def *global_pos = nir_iadd(&b, nir_imul(&b, nir_channel(&b, img_coord, 1), pitch),
299 nir_imul_imm(&b, nir_channel(&b, img_coord, 0), 3));
300
301 nir_def *outval = nir_txf_deref(&b, nir_build_deref_var(&b, input_img), buf_coord, NULL);
302
303 for (int chan = 0; chan < 3; chan++) {
304 nir_def *local_pos = nir_iadd_imm(&b, global_pos, chan);
305
306 nir_def *coord = nir_replicate(&b, local_pos, 4);
307
308 nir_image_deref_store(&b, &nir_build_deref_var(&b, output_img)->def, coord, nir_undef(&b, 1, 32),
309 nir_channel(&b, outval, chan), nir_imm_int(&b, 0), .image_dim = GLSL_SAMPLER_DIM_BUF);
310 }
311
312 return b.shader;
313 }
314
315 static VkResult
get_btoi_r32g32b32_pipeline(struct radv_device * device,VkPipeline * pipeline_out,VkPipelineLayout * layout_out)316 get_btoi_r32g32b32_pipeline(struct radv_device *device, VkPipeline *pipeline_out, VkPipelineLayout *layout_out)
317 {
318 enum radv_meta_object_key_type key = RADV_META_OBJECT_KEY_COPY_BUFFER_TO_IMAGE_R32G32B32;
319 VkResult result;
320
321 const VkDescriptorSetLayoutBinding bindings[] = {
322 {
323 .binding = 0,
324 .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
325 .descriptorCount = 1,
326 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
327 },
328 {
329 .binding = 1,
330 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
331 .descriptorCount = 1,
332 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
333 },
334 };
335
336 const VkDescriptorSetLayoutCreateInfo desc_info = {
337 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
338 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT,
339 .bindingCount = 2,
340 .pBindings = bindings,
341 };
342
343 const VkPushConstantRange pc_range = {
344 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
345 .size = 16,
346 };
347
348 result = vk_meta_get_pipeline_layout(&device->vk, &device->meta_state.device, &desc_info, &pc_range, &key,
349 sizeof(key), layout_out);
350 if (result != VK_SUCCESS)
351 return result;
352
353 VkPipeline pipeline_from_cache = vk_meta_lookup_pipeline(&device->meta_state.device, &key, sizeof(key));
354 if (pipeline_from_cache != VK_NULL_HANDLE) {
355 *pipeline_out = pipeline_from_cache;
356 return VK_SUCCESS;
357 }
358
359 nir_shader *cs = build_nir_btoi_r32g32b32_compute_shader(device);
360
361 const VkPipelineShaderStageCreateInfo stage_info = {
362 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
363 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
364 .module = vk_shader_module_handle_from_nir(cs),
365 .pName = "main",
366 .pSpecializationInfo = NULL,
367 };
368
369 const VkComputePipelineCreateInfo pipeline_info = {
370 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
371 .stage = stage_info,
372 .flags = 0,
373 .layout = *layout_out,
374 };
375
376 result = vk_meta_create_compute_pipeline(&device->vk, &device->meta_state.device, &pipeline_info, &key, sizeof(key),
377 pipeline_out);
378
379 ralloc_free(cs);
380 return result;
381 }
382
383 static nir_shader *
build_nir_itoi_compute_shader(struct radv_device * dev,bool src_3d,bool dst_3d,int samples)384 build_nir_itoi_compute_shader(struct radv_device *dev, bool src_3d, bool dst_3d, int samples)
385 {
386 bool is_multisampled = samples > 1;
387 enum glsl_sampler_dim src_dim = src_3d ? GLSL_SAMPLER_DIM_3D
388 : is_multisampled ? GLSL_SAMPLER_DIM_MS
389 : GLSL_SAMPLER_DIM_2D;
390 enum glsl_sampler_dim dst_dim = dst_3d ? GLSL_SAMPLER_DIM_3D
391 : is_multisampled ? GLSL_SAMPLER_DIM_MS
392 : GLSL_SAMPLER_DIM_2D;
393 const struct glsl_type *buf_type = glsl_sampler_type(src_dim, false, false, GLSL_TYPE_FLOAT);
394 const struct glsl_type *img_type = glsl_image_type(dst_dim, false, GLSL_TYPE_FLOAT);
395 nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_COMPUTE, "meta_itoi_cs-%dd-%dd-%d", src_3d ? 3 : 2,
396 dst_3d ? 3 : 2, samples);
397 b.shader->info.workgroup_size[0] = 8;
398 b.shader->info.workgroup_size[1] = 8;
399 nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform, buf_type, "s_tex");
400 input_img->data.descriptor_set = 0;
401 input_img->data.binding = 0;
402
403 nir_variable *output_img = nir_variable_create(b.shader, nir_var_image, img_type, "out_img");
404 output_img->data.descriptor_set = 0;
405 output_img->data.binding = 1;
406
407 nir_def *global_id = get_global_ids(&b, (src_3d || dst_3d) ? 3 : 2);
408
409 nir_def *src_offset = nir_load_push_constant(&b, src_3d ? 3 : 2, 32, nir_imm_int(&b, 0), .range = src_3d ? 12 : 8);
410 nir_def *dst_offset = nir_load_push_constant(&b, dst_3d ? 3 : 2, 32, nir_imm_int(&b, 12), .range = dst_3d ? 24 : 20);
411
412 nir_def *src_coord = nir_iadd(&b, global_id, src_offset);
413 nir_deref_instr *input_img_deref = nir_build_deref_var(&b, input_img);
414
415 nir_def *dst_coord = nir_iadd(&b, global_id, dst_offset);
416
417 nir_def *tex_vals[8];
418 if (is_multisampled) {
419 for (uint32_t i = 0; i < samples; i++) {
420 tex_vals[i] = nir_txf_ms_deref(&b, input_img_deref, nir_trim_vector(&b, src_coord, 2), nir_imm_int(&b, i));
421 }
422 } else {
423 tex_vals[0] = nir_txf_deref(&b, input_img_deref, nir_trim_vector(&b, src_coord, 2 + src_3d), nir_imm_int(&b, 0));
424 }
425
426 nir_def *img_coord = nir_vec4(&b, nir_channel(&b, dst_coord, 0), nir_channel(&b, dst_coord, 1),
427 dst_3d ? nir_channel(&b, dst_coord, 2) : nir_undef(&b, 1, 32), nir_undef(&b, 1, 32));
428
429 for (uint32_t i = 0; i < samples; i++) {
430 nir_image_deref_store(&b, &nir_build_deref_var(&b, output_img)->def, img_coord, nir_imm_int(&b, i), tex_vals[i],
431 nir_imm_int(&b, 0), .image_dim = dst_dim);
432 }
433
434 return b.shader;
435 }
436
437 static VkResult
get_itoi_pipeline_layout(struct radv_device * device,VkPipelineLayout * layout_out)438 get_itoi_pipeline_layout(struct radv_device *device, VkPipelineLayout *layout_out)
439 {
440 enum radv_meta_object_key_type key = RADV_META_OBJECT_KEY_COPY_IMAGE;
441
442 const VkDescriptorSetLayoutBinding bindings[] = {
443 {
444 .binding = 0,
445 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
446 .descriptorCount = 1,
447 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
448 },
449 {
450 .binding = 1,
451 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
452 .descriptorCount = 1,
453 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
454 },
455 };
456
457 const VkDescriptorSetLayoutCreateInfo desc_info = {
458 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
459 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT,
460 .bindingCount = 2,
461 .pBindings = bindings,
462 };
463
464 const VkPushConstantRange pc_range = {
465 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
466 .size = 24,
467 };
468
469 return vk_meta_get_pipeline_layout(&device->vk, &device->meta_state.device, &desc_info, &pc_range, &key, sizeof(key),
470 layout_out);
471 }
472
473 struct radv_copy_image_key {
474 enum radv_meta_object_key_type type;
475 bool src_3d;
476 bool dst_3d;
477 uint8_t samples_log2;
478 };
479
480 static VkResult
get_itoi_pipeline(struct radv_device * device,const struct radv_image * src_image,const struct radv_image * dst_image,int samples,VkPipeline * pipeline_out,VkPipelineLayout * layout_out)481 get_itoi_pipeline(struct radv_device *device, const struct radv_image *src_image, const struct radv_image *dst_image,
482 int samples, VkPipeline *pipeline_out, VkPipelineLayout *layout_out)
483 {
484 const bool src_3d = src_image->vk.image_type == VK_IMAGE_TYPE_3D;
485 const bool dst_3d = dst_image->vk.image_type == VK_IMAGE_TYPE_3D;
486 const uint32_t samples_log2 = ffs(samples) - 1;
487 VkResult result;
488 struct radv_copy_image_key key;
489
490 result = get_itoi_pipeline_layout(device, layout_out);
491 if (result != VK_SUCCESS)
492 return result;
493
494 memset(&key, 0, sizeof(key));
495 key.type = RADV_META_OBJECT_KEY_COPY_IMAGE;
496 key.src_3d = src_3d;
497 key.dst_3d = dst_3d;
498 key.samples_log2 = samples_log2;
499
500 VkPipeline pipeline_from_cache = vk_meta_lookup_pipeline(&device->meta_state.device, &key, sizeof(key));
501 if (pipeline_from_cache != VK_NULL_HANDLE) {
502 *pipeline_out = pipeline_from_cache;
503 return VK_SUCCESS;
504 }
505
506 nir_shader *cs = build_nir_itoi_compute_shader(device, src_3d, dst_3d, samples);
507
508 const VkPipelineShaderStageCreateInfo stage_info = {
509 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
510 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
511 .module = vk_shader_module_handle_from_nir(cs),
512 .pName = "main",
513 .pSpecializationInfo = NULL,
514 };
515
516 const VkComputePipelineCreateInfo pipeline_info = {
517 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
518 .stage = stage_info,
519 .flags = 0,
520 .layout = *layout_out,
521 };
522
523 result = vk_meta_create_compute_pipeline(&device->vk, &device->meta_state.device, &pipeline_info, &key, sizeof(key),
524 pipeline_out);
525
526 ralloc_free(cs);
527 return result;
528 }
529
530 static nir_shader *
build_nir_itoi_r32g32b32_compute_shader(struct radv_device * dev)531 build_nir_itoi_r32g32b32_compute_shader(struct radv_device *dev)
532 {
533 const struct glsl_type *type = glsl_sampler_type(GLSL_SAMPLER_DIM_BUF, false, false, GLSL_TYPE_FLOAT);
534 const struct glsl_type *img_type = glsl_image_type(GLSL_SAMPLER_DIM_BUF, false, GLSL_TYPE_FLOAT);
535 nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_COMPUTE, "meta_itoi_r32g32b32_cs");
536 b.shader->info.workgroup_size[0] = 8;
537 b.shader->info.workgroup_size[1] = 8;
538 nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform, type, "input_img");
539 input_img->data.descriptor_set = 0;
540 input_img->data.binding = 0;
541
542 nir_variable *output_img = nir_variable_create(b.shader, nir_var_image, img_type, "output_img");
543 output_img->data.descriptor_set = 0;
544 output_img->data.binding = 1;
545
546 nir_def *global_id = get_global_ids(&b, 2);
547
548 nir_def *src_offset = nir_load_push_constant(&b, 3, 32, nir_imm_int(&b, 0), .range = 12);
549 nir_def *dst_offset = nir_load_push_constant(&b, 3, 32, nir_imm_int(&b, 12), .range = 24);
550
551 nir_def *src_stride = nir_channel(&b, src_offset, 2);
552 nir_def *dst_stride = nir_channel(&b, dst_offset, 2);
553
554 nir_def *src_img_coord = nir_iadd(&b, global_id, src_offset);
555 nir_def *dst_img_coord = nir_iadd(&b, global_id, dst_offset);
556
557 nir_def *src_global_pos = nir_iadd(&b, nir_imul(&b, nir_channel(&b, src_img_coord, 1), src_stride),
558 nir_imul_imm(&b, nir_channel(&b, src_img_coord, 0), 3));
559
560 nir_def *dst_global_pos = nir_iadd(&b, nir_imul(&b, nir_channel(&b, dst_img_coord, 1), dst_stride),
561 nir_imul_imm(&b, nir_channel(&b, dst_img_coord, 0), 3));
562
563 for (int chan = 0; chan < 3; chan++) {
564 /* src */
565 nir_def *src_local_pos = nir_iadd_imm(&b, src_global_pos, chan);
566 nir_def *outval = nir_txf_deref(&b, nir_build_deref_var(&b, input_img), src_local_pos, NULL);
567
568 /* dst */
569 nir_def *dst_local_pos = nir_iadd_imm(&b, dst_global_pos, chan);
570
571 nir_def *dst_coord = nir_replicate(&b, dst_local_pos, 4);
572
573 nir_image_deref_store(&b, &nir_build_deref_var(&b, output_img)->def, dst_coord, nir_undef(&b, 1, 32),
574 nir_channel(&b, outval, 0), nir_imm_int(&b, 0), .image_dim = GLSL_SAMPLER_DIM_BUF);
575 }
576
577 return b.shader;
578 }
579
580 static VkResult
get_itoi_r32g32b32_pipeline(struct radv_device * device,VkPipeline * pipeline_out,VkPipelineLayout * layout_out)581 get_itoi_r32g32b32_pipeline(struct radv_device *device, VkPipeline *pipeline_out, VkPipelineLayout *layout_out)
582 {
583 enum radv_meta_object_key_type key = RADV_META_OBJECT_KEY_COPY_IMAGE_R32G32B32;
584 VkResult result;
585
586 const VkDescriptorSetLayoutBinding bindings[] = {
587 {
588 .binding = 0,
589 .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
590 .descriptorCount = 1,
591 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
592 },
593 {
594 .binding = 1,
595 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
596 .descriptorCount = 1,
597 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
598 },
599 };
600
601 const VkDescriptorSetLayoutCreateInfo desc_info = {
602 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
603 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT,
604 .bindingCount = 2,
605 .pBindings = bindings,
606 };
607
608 const VkPushConstantRange pc_range = {
609 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
610 .size = 24,
611 };
612
613 result = vk_meta_get_pipeline_layout(&device->vk, &device->meta_state.device, &desc_info, &pc_range, &key,
614 sizeof(key), layout_out);
615 if (result != VK_SUCCESS)
616 return result;
617
618 VkPipeline pipeline_from_cache = vk_meta_lookup_pipeline(&device->meta_state.device, &key, sizeof(key));
619 if (pipeline_from_cache != VK_NULL_HANDLE) {
620 *pipeline_out = pipeline_from_cache;
621 return VK_SUCCESS;
622 }
623
624 nir_shader *cs = build_nir_itoi_r32g32b32_compute_shader(device);
625
626 const VkPipelineShaderStageCreateInfo stage_info = {
627 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
628 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
629 .module = vk_shader_module_handle_from_nir(cs),
630 .pName = "main",
631 .pSpecializationInfo = NULL,
632 };
633
634 const VkComputePipelineCreateInfo pipeline_info = {
635 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
636 .stage = stage_info,
637 .flags = 0,
638 .layout = *layout_out,
639 };
640
641 result = vk_meta_create_compute_pipeline(&device->vk, &device->meta_state.device, &pipeline_info, &key, sizeof(key),
642 pipeline_out);
643
644 ralloc_free(cs);
645 return result;
646 }
647
648 static nir_shader *
build_nir_cleari_compute_shader(struct radv_device * dev,bool is_3d,int samples)649 build_nir_cleari_compute_shader(struct radv_device *dev, bool is_3d, int samples)
650 {
651 bool is_multisampled = samples > 1;
652 enum glsl_sampler_dim dim = is_3d ? GLSL_SAMPLER_DIM_3D
653 : is_multisampled ? GLSL_SAMPLER_DIM_MS
654 : GLSL_SAMPLER_DIM_2D;
655 const struct glsl_type *img_type = glsl_image_type(dim, false, GLSL_TYPE_FLOAT);
656 nir_builder b =
657 radv_meta_init_shader(dev, MESA_SHADER_COMPUTE, is_3d ? "meta_cleari_cs_3d-%d" : "meta_cleari_cs-%d", samples);
658 b.shader->info.workgroup_size[0] = 8;
659 b.shader->info.workgroup_size[1] = 8;
660
661 nir_variable *output_img = nir_variable_create(b.shader, nir_var_image, img_type, "out_img");
662 output_img->data.descriptor_set = 0;
663 output_img->data.binding = 0;
664
665 nir_def *global_id = get_global_ids(&b, 2);
666
667 nir_def *clear_val = nir_load_push_constant(&b, 4, 32, nir_imm_int(&b, 0), .range = 16);
668 nir_def *layer = nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 16), .range = 20);
669
670 nir_def *comps[4];
671 comps[0] = nir_channel(&b, global_id, 0);
672 comps[1] = nir_channel(&b, global_id, 1);
673 comps[2] = layer;
674 comps[3] = nir_undef(&b, 1, 32);
675 global_id = nir_vec(&b, comps, 4);
676
677 for (uint32_t i = 0; i < samples; i++) {
678 nir_image_deref_store(&b, &nir_build_deref_var(&b, output_img)->def, global_id, nir_imm_int(&b, i), clear_val,
679 nir_imm_int(&b, 0), .image_dim = dim);
680 }
681
682 return b.shader;
683 }
684
685 static VkResult
get_cleari_pipeline_layout(struct radv_device * device,VkPipelineLayout * layout_out)686 get_cleari_pipeline_layout(struct radv_device *device, VkPipelineLayout *layout_out)
687 {
688 enum radv_meta_object_key_type key = RADV_META_OBJECT_KEY_CLEAR_CS;
689
690 const VkDescriptorSetLayoutBinding binding = {
691 .binding = 0,
692 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
693 .descriptorCount = 1,
694 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
695 };
696
697 const VkDescriptorSetLayoutCreateInfo desc_info = {
698 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
699 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT,
700 .bindingCount = 1,
701 .pBindings = &binding,
702 };
703
704 const VkPushConstantRange pc_range = {
705 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
706 .size = 20,
707 };
708
709 return vk_meta_get_pipeline_layout(&device->vk, &device->meta_state.device, &desc_info, &pc_range, &key, sizeof(key),
710 layout_out);
711 }
712
713 struct radv_clear_key {
714 enum radv_meta_object_key_type type;
715 bool is_3d;
716 uint8_t samples_log2;
717 };
718
719 static VkResult
get_cleari_pipeline(struct radv_device * device,const struct radv_image * image,VkPipeline * pipeline_out,VkPipelineLayout * layout_out)720 get_cleari_pipeline(struct radv_device *device, const struct radv_image *image, VkPipeline *pipeline_out,
721 VkPipelineLayout *layout_out)
722 {
723 const bool is_3d = image->vk.image_type == VK_IMAGE_TYPE_3D;
724 const uint32_t samples = image->vk.samples;
725 const uint32_t samples_log2 = ffs(samples) - 1;
726 struct radv_clear_key key;
727 VkResult result;
728
729 result = get_cleari_pipeline_layout(device, layout_out);
730 if (result != VK_SUCCESS)
731 return result;
732
733 memset(&key, 0, sizeof(key));
734 key.type = RADV_META_OBJECT_KEY_CLEAR_CS;
735 key.is_3d = is_3d;
736 key.samples_log2 = samples_log2;
737
738 VkPipeline pipeline_from_cache = vk_meta_lookup_pipeline(&device->meta_state.device, &key, sizeof(key));
739 if (pipeline_from_cache != VK_NULL_HANDLE) {
740 *pipeline_out = pipeline_from_cache;
741 return VK_SUCCESS;
742 }
743
744 nir_shader *cs = build_nir_cleari_compute_shader(device, is_3d, samples);
745
746 const VkPipelineShaderStageCreateInfo stage_info = {
747 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
748 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
749 .module = vk_shader_module_handle_from_nir(cs),
750 .pName = "main",
751 .pSpecializationInfo = NULL,
752 };
753
754 const VkComputePipelineCreateInfo pipeline_info = {
755 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
756 .stage = stage_info,
757 .flags = 0,
758 .layout = *layout_out,
759 };
760
761 result = vk_meta_create_compute_pipeline(&device->vk, &device->meta_state.device, &pipeline_info, &key, sizeof(key),
762 pipeline_out);
763
764 ralloc_free(cs);
765 return result;
766 }
767
768 /* Special path for clearing R32G32B32 images using a compute shader. */
769 static nir_shader *
build_nir_cleari_r32g32b32_compute_shader(struct radv_device * dev)770 build_nir_cleari_r32g32b32_compute_shader(struct radv_device *dev)
771 {
772 const struct glsl_type *img_type = glsl_image_type(GLSL_SAMPLER_DIM_BUF, false, GLSL_TYPE_FLOAT);
773 nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_COMPUTE, "meta_cleari_r32g32b32_cs");
774 b.shader->info.workgroup_size[0] = 8;
775 b.shader->info.workgroup_size[1] = 8;
776
777 nir_variable *output_img = nir_variable_create(b.shader, nir_var_image, img_type, "out_img");
778 output_img->data.descriptor_set = 0;
779 output_img->data.binding = 0;
780
781 nir_def *global_id = get_global_ids(&b, 2);
782
783 nir_def *clear_val = nir_load_push_constant(&b, 3, 32, nir_imm_int(&b, 0), .range = 12);
784 nir_def *stride = nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 12), .range = 16);
785
786 nir_def *global_x = nir_channel(&b, global_id, 0);
787 nir_def *global_y = nir_channel(&b, global_id, 1);
788
789 nir_def *global_pos = nir_iadd(&b, nir_imul(&b, global_y, stride), nir_imul_imm(&b, global_x, 3));
790
791 for (unsigned chan = 0; chan < 3; chan++) {
792 nir_def *local_pos = nir_iadd_imm(&b, global_pos, chan);
793
794 nir_def *coord = nir_replicate(&b, local_pos, 4);
795
796 nir_image_deref_store(&b, &nir_build_deref_var(&b, output_img)->def, coord, nir_undef(&b, 1, 32),
797 nir_channel(&b, clear_val, chan), nir_imm_int(&b, 0), .image_dim = GLSL_SAMPLER_DIM_BUF);
798 }
799
800 return b.shader;
801 }
802
803 static VkResult
get_cleari_r32g32b32_pipeline(struct radv_device * device,VkPipeline * pipeline_out,VkPipelineLayout * layout_out)804 get_cleari_r32g32b32_pipeline(struct radv_device *device, VkPipeline *pipeline_out, VkPipelineLayout *layout_out)
805 {
806 enum radv_meta_object_key_type key = RADV_META_OBJECT_KEY_CLEAR_CS_R32G32B32;
807 VkResult result;
808
809 const VkDescriptorSetLayoutBinding binding = {
810 .binding = 0,
811 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
812 .descriptorCount = 1,
813 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
814 };
815
816 const VkDescriptorSetLayoutCreateInfo desc_info = {
817 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
818 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT,
819 .bindingCount = 1,
820 .pBindings = &binding,
821 };
822
823 const VkPushConstantRange pc_range = {
824 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
825 .size = 16,
826 };
827
828 result = vk_meta_get_pipeline_layout(&device->vk, &device->meta_state.device, &desc_info, &pc_range, &key,
829 sizeof(key), layout_out);
830 if (result != VK_SUCCESS)
831 return result;
832
833 VkPipeline pipeline_from_cache = vk_meta_lookup_pipeline(&device->meta_state.device, &key, sizeof(key));
834 if (pipeline_from_cache != VK_NULL_HANDLE) {
835 *pipeline_out = pipeline_from_cache;
836 return VK_SUCCESS;
837 }
838
839 nir_shader *cs = build_nir_cleari_r32g32b32_compute_shader(device);
840
841 const VkPipelineShaderStageCreateInfo stage_info = {
842 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
843 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
844 .module = vk_shader_module_handle_from_nir(cs),
845 .pName = "main",
846 .pSpecializationInfo = NULL,
847 };
848
849 const VkComputePipelineCreateInfo pipeline_info = {
850 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
851 .stage = stage_info,
852 .flags = 0,
853 .layout = *layout_out,
854 };
855
856 result = vk_meta_create_compute_pipeline(&device->vk, &device->meta_state.device, &pipeline_info, &key, sizeof(key),
857 pipeline_out);
858
859 ralloc_free(cs);
860 return result;
861 }
862
863 static void
create_iview(struct radv_cmd_buffer * cmd_buffer,struct radv_meta_blit2d_surf * surf,struct radv_image_view * iview,VkFormat format,VkImageAspectFlagBits aspects)864 create_iview(struct radv_cmd_buffer *cmd_buffer, struct radv_meta_blit2d_surf *surf, struct radv_image_view *iview,
865 VkFormat format, VkImageAspectFlagBits aspects)
866 {
867 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
868
869 if (format == VK_FORMAT_UNDEFINED)
870 format = surf->format;
871
872 radv_image_view_init(iview, device,
873 &(VkImageViewCreateInfo){
874 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
875 .image = radv_image_to_handle(surf->image),
876 .viewType = radv_meta_get_view_type(surf->image),
877 .format = format,
878 .subresourceRange = {.aspectMask = aspects,
879 .baseMipLevel = surf->level,
880 .levelCount = 1,
881 .baseArrayLayer = surf->layer,
882 .layerCount = 1},
883 },
884 &(struct radv_image_view_extra_create_info){
885 .disable_compression = surf->disable_compression,
886 });
887 }
888
889 static void
create_bview(struct radv_cmd_buffer * cmd_buffer,struct radv_buffer * buffer,unsigned offset,VkFormat format,struct radv_buffer_view * bview)890 create_bview(struct radv_cmd_buffer *cmd_buffer, struct radv_buffer *buffer, unsigned offset, VkFormat format,
891 struct radv_buffer_view *bview)
892 {
893 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
894
895 radv_buffer_view_init(bview, device,
896 &(VkBufferViewCreateInfo){
897 .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
898 .flags = 0,
899 .buffer = radv_buffer_to_handle(buffer),
900 .format = format,
901 .offset = offset,
902 .range = VK_WHOLE_SIZE,
903 });
904 }
905
906 static void
create_buffer_from_image(struct radv_cmd_buffer * cmd_buffer,struct radv_meta_blit2d_surf * surf,VkBufferUsageFlagBits2 usage,VkBuffer * buffer)907 create_buffer_from_image(struct radv_cmd_buffer *cmd_buffer, struct radv_meta_blit2d_surf *surf,
908 VkBufferUsageFlagBits2 usage, VkBuffer *buffer)
909 {
910 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
911 struct radv_device_memory mem;
912
913 radv_device_memory_init(&mem, device, surf->image->bindings[0].bo);
914
915 radv_create_buffer(device,
916 &(VkBufferCreateInfo){
917 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
918 .pNext =
919 &(VkBufferUsageFlags2CreateInfo){
920 .sType = VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO,
921 .usage = usage,
922 },
923 .flags = 0,
924 .size = surf->image->size,
925 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
926 },
927 NULL, buffer, true);
928
929 radv_BindBufferMemory2(radv_device_to_handle(device), 1,
930 (VkBindBufferMemoryInfo[]){{
931 .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
932 .buffer = *buffer,
933 .memory = radv_device_memory_to_handle(&mem),
934 .memoryOffset = surf->image->bindings[0].offset,
935 }});
936
937 radv_device_memory_finish(&mem);
938 }
939
940 static void
create_bview_for_r32g32b32(struct radv_cmd_buffer * cmd_buffer,struct radv_buffer * buffer,unsigned offset,VkFormat src_format,struct radv_buffer_view * bview)941 create_bview_for_r32g32b32(struct radv_cmd_buffer *cmd_buffer, struct radv_buffer *buffer, unsigned offset,
942 VkFormat src_format, struct radv_buffer_view *bview)
943 {
944 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
945 VkFormat format;
946
947 switch (src_format) {
948 case VK_FORMAT_R32G32B32_UINT:
949 format = VK_FORMAT_R32_UINT;
950 break;
951 case VK_FORMAT_R32G32B32_SINT:
952 format = VK_FORMAT_R32_SINT;
953 break;
954 case VK_FORMAT_R32G32B32_SFLOAT:
955 format = VK_FORMAT_R32_SFLOAT;
956 break;
957 default:
958 unreachable("invalid R32G32B32 format");
959 }
960
961 radv_buffer_view_init(bview, device,
962 &(VkBufferViewCreateInfo){
963 .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
964 .flags = 0,
965 .buffer = radv_buffer_to_handle(buffer),
966 .format = format,
967 .offset = offset,
968 .range = VK_WHOLE_SIZE,
969 });
970 }
971
972 /* GFX9+ has an issue where the HW does not calculate mipmap degradations
973 * for block-compressed images correctly (see the comment in
974 * radv_image_view_init). Some texels are unaddressable and cannot be copied
975 * to/from by a compute shader. Here we will perform a buffer copy to copy the
976 * texels that the hardware missed.
977 *
978 * GFX10 will not use this workaround because it can be fixed by adjusting its
979 * image view descriptors instead.
980 */
981 static void
fixup_gfx9_cs_copy(struct radv_cmd_buffer * cmd_buffer,const struct radv_meta_blit2d_buffer * buf_bsurf,const struct radv_meta_blit2d_surf * img_bsurf,const struct radv_meta_blit2d_rect * rect,bool to_image)982 fixup_gfx9_cs_copy(struct radv_cmd_buffer *cmd_buffer, const struct radv_meta_blit2d_buffer *buf_bsurf,
983 const struct radv_meta_blit2d_surf *img_bsurf, const struct radv_meta_blit2d_rect *rect,
984 bool to_image)
985 {
986 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
987 const struct radv_physical_device *pdev = radv_device_physical(device);
988 const unsigned mip_level = img_bsurf->level;
989 const struct radv_image *image = img_bsurf->image;
990 const struct radeon_surf *surf = &image->planes[0].surface;
991 const struct radeon_info *gpu_info = &pdev->info;
992 struct ac_surf_info surf_info = radv_get_ac_surf_info(device, image);
993
994 /* GFX10 will use a different workaround unless this is not a 2D image */
995 if (gpu_info->gfx_level < GFX9 || (gpu_info->gfx_level >= GFX10 && image->vk.image_type == VK_IMAGE_TYPE_2D) ||
996 image->vk.mip_levels == 1 || !vk_format_is_block_compressed(image->vk.format))
997 return;
998
999 /* The physical extent of the base mip */
1000 VkExtent2D hw_base_extent = {surf->u.gfx9.base_mip_width, surf->u.gfx9.base_mip_height};
1001
1002 /* The hardware-calculated extent of the selected mip
1003 * (naive divide-by-two integer math)
1004 */
1005 VkExtent2D hw_mip_extent = {u_minify(hw_base_extent.width, mip_level), u_minify(hw_base_extent.height, mip_level)};
1006
1007 /* The actual extent we want to copy */
1008 VkExtent2D mip_extent = {rect->width, rect->height};
1009
1010 VkOffset2D mip_offset = {to_image ? rect->dst_x : rect->src_x, to_image ? rect->dst_y : rect->src_y};
1011
1012 if (hw_mip_extent.width >= mip_offset.x + mip_extent.width &&
1013 hw_mip_extent.height >= mip_offset.y + mip_extent.height)
1014 return;
1015
1016 if (!to_image) {
1017 /* If we are writing to a buffer, then we need to wait for the compute
1018 * shader to finish because it may write over the unaddressable texels
1019 * while we're fixing them. If we're writing to an image, we do not need
1020 * to wait because the compute shader cannot write to those texels
1021 */
1022 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_CS_PARTIAL_FLUSH | RADV_CMD_FLAG_INV_L2 | RADV_CMD_FLAG_INV_VCACHE;
1023 }
1024
1025 for (uint32_t y = 0; y < mip_extent.height; y++) {
1026 uint32_t coordY = y + mip_offset.y;
1027 /* If the default copy algorithm (done previously) has already seen this
1028 * scanline, then we can bias the starting X coordinate over to skip the
1029 * region already copied by the default copy.
1030 */
1031 uint32_t x = (coordY < hw_mip_extent.height) ? hw_mip_extent.width : 0;
1032 for (; x < mip_extent.width; x++) {
1033 uint32_t coordX = x + mip_offset.x;
1034 uint64_t addr = ac_surface_addr_from_coord(pdev->addrlib, gpu_info, surf, &surf_info, mip_level, coordX,
1035 coordY, img_bsurf->layer, image->vk.image_type == VK_IMAGE_TYPE_3D);
1036 struct radeon_winsys_bo *img_bo = image->bindings[0].bo;
1037 struct radeon_winsys_bo *mem_bo = buf_bsurf->buffer->bo;
1038 const uint64_t img_offset = image->bindings[0].offset + addr;
1039 /* buf_bsurf->offset already includes the layer offset */
1040 const uint64_t mem_offset =
1041 buf_bsurf->buffer->offset + buf_bsurf->offset + y * buf_bsurf->pitch * surf->bpe + x * surf->bpe;
1042 if (to_image) {
1043 radv_copy_buffer(cmd_buffer, mem_bo, img_bo, mem_offset, img_offset, surf->bpe);
1044 } else {
1045 radv_copy_buffer(cmd_buffer, img_bo, mem_bo, img_offset, mem_offset, surf->bpe);
1046 }
1047 }
1048 }
1049 }
1050
1051 static unsigned
get_image_stride_for_r32g32b32(struct radv_cmd_buffer * cmd_buffer,struct radv_meta_blit2d_surf * surf)1052 get_image_stride_for_r32g32b32(struct radv_cmd_buffer *cmd_buffer, struct radv_meta_blit2d_surf *surf)
1053 {
1054 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
1055 const struct radv_physical_device *pdev = radv_device_physical(device);
1056 unsigned stride;
1057
1058 if (pdev->info.gfx_level >= GFX9) {
1059 stride = surf->image->planes[0].surface.u.gfx9.surf_pitch;
1060 } else {
1061 stride = surf->image->planes[0].surface.u.legacy.level[0].nblk_x * 3;
1062 }
1063
1064 return stride;
1065 }
1066
1067 void
radv_meta_image_to_buffer(struct radv_cmd_buffer * cmd_buffer,struct radv_meta_blit2d_surf * src,struct radv_meta_blit2d_buffer * dst,struct radv_meta_blit2d_rect * rect)1068 radv_meta_image_to_buffer(struct radv_cmd_buffer *cmd_buffer, struct radv_meta_blit2d_surf *src,
1069 struct radv_meta_blit2d_buffer *dst, struct radv_meta_blit2d_rect *rect)
1070 {
1071 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
1072 struct radv_image_view src_view;
1073 struct radv_buffer_view dst_view;
1074 VkPipelineLayout layout;
1075 VkPipeline pipeline;
1076 VkResult result;
1077
1078 result = get_itob_pipeline(device, src->image, &pipeline, &layout);
1079 if (result != VK_SUCCESS) {
1080 vk_command_buffer_set_error(&cmd_buffer->vk, result);
1081 return;
1082 }
1083
1084 create_iview(cmd_buffer, src, &src_view, VK_FORMAT_UNDEFINED, src->aspect_mask);
1085 create_bview(cmd_buffer, dst->buffer, dst->offset, dst->format, &dst_view);
1086
1087 radv_meta_push_descriptor_set(
1088 cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, 2,
1089 (VkWriteDescriptorSet[]){{.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1090 .dstBinding = 0,
1091 .dstArrayElement = 0,
1092 .descriptorCount = 1,
1093 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
1094 .pImageInfo =
1095 (VkDescriptorImageInfo[]){
1096 {
1097 .sampler = VK_NULL_HANDLE,
1098 .imageView = radv_image_view_to_handle(&src_view),
1099 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
1100 },
1101 }},
1102 {
1103 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1104 .dstBinding = 1,
1105 .dstArrayElement = 0,
1106 .descriptorCount = 1,
1107 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
1108 .pTexelBufferView = (VkBufferView[]){radv_buffer_view_to_handle(&dst_view)},
1109 }});
1110
1111 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
1112
1113 unsigned push_constants[4] = {rect->src_x, rect->src_y, src->layer, dst->pitch};
1114 vk_common_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 16,
1115 push_constants);
1116
1117 radv_unaligned_dispatch(cmd_buffer, rect->width, rect->height, 1);
1118 fixup_gfx9_cs_copy(cmd_buffer, dst, src, rect, false);
1119
1120 radv_image_view_finish(&src_view);
1121 radv_buffer_view_finish(&dst_view);
1122 }
1123
1124 static void
radv_meta_buffer_to_image_cs_r32g32b32(struct radv_cmd_buffer * cmd_buffer,struct radv_meta_blit2d_buffer * src,struct radv_meta_blit2d_surf * dst,struct radv_meta_blit2d_rect * rect)1125 radv_meta_buffer_to_image_cs_r32g32b32(struct radv_cmd_buffer *cmd_buffer, struct radv_meta_blit2d_buffer *src,
1126 struct radv_meta_blit2d_surf *dst, struct radv_meta_blit2d_rect *rect)
1127 {
1128 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
1129 struct radv_buffer_view src_view, dst_view;
1130 unsigned dst_offset = 0;
1131 VkPipelineLayout layout;
1132 VkPipeline pipeline;
1133 unsigned stride;
1134 VkBuffer buffer;
1135 VkResult result;
1136
1137 result = get_btoi_r32g32b32_pipeline(device, &pipeline, &layout);
1138 if (result != VK_SUCCESS) {
1139 vk_command_buffer_set_error(&cmd_buffer->vk, result);
1140 return;
1141 }
1142
1143 /* This special btoi path for R32G32B32 formats will write the linear
1144 * image as a buffer with the same underlying memory. The compute
1145 * shader will copy all components separately using a R32 format.
1146 */
1147 create_buffer_from_image(cmd_buffer, dst, VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT, &buffer);
1148
1149 create_bview(cmd_buffer, src->buffer, src->offset, src->format, &src_view);
1150 create_bview_for_r32g32b32(cmd_buffer, radv_buffer_from_handle(buffer), dst_offset, dst->format, &dst_view);
1151
1152 radv_meta_push_descriptor_set(
1153 cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, 2,
1154 (VkWriteDescriptorSet[]){{
1155 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1156 .dstBinding = 0,
1157 .dstArrayElement = 0,
1158 .descriptorCount = 1,
1159 .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
1160 .pTexelBufferView = (VkBufferView[]){radv_buffer_view_to_handle(&src_view)},
1161 },
1162 {
1163 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1164 .dstBinding = 1,
1165 .dstArrayElement = 0,
1166 .descriptorCount = 1,
1167 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
1168 .pTexelBufferView = (VkBufferView[]){radv_buffer_view_to_handle(&dst_view)},
1169 }});
1170
1171 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
1172
1173 stride = get_image_stride_for_r32g32b32(cmd_buffer, dst);
1174
1175 unsigned push_constants[4] = {
1176 rect->dst_x,
1177 rect->dst_y,
1178 stride,
1179 src->pitch,
1180 };
1181
1182 vk_common_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 16,
1183 push_constants);
1184
1185 radv_unaligned_dispatch(cmd_buffer, rect->width, rect->height, 1);
1186
1187 radv_buffer_view_finish(&src_view);
1188 radv_buffer_view_finish(&dst_view);
1189 radv_DestroyBuffer(radv_device_to_handle(device), buffer, NULL);
1190 }
1191
1192 void
radv_meta_buffer_to_image_cs(struct radv_cmd_buffer * cmd_buffer,struct radv_meta_blit2d_buffer * src,struct radv_meta_blit2d_surf * dst,struct radv_meta_blit2d_rect * rect)1193 radv_meta_buffer_to_image_cs(struct radv_cmd_buffer *cmd_buffer, struct radv_meta_blit2d_buffer *src,
1194 struct radv_meta_blit2d_surf *dst, struct radv_meta_blit2d_rect *rect)
1195 {
1196 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
1197 struct radv_buffer_view src_view;
1198 struct radv_image_view dst_view;
1199 VkPipelineLayout layout;
1200 VkPipeline pipeline;
1201 VkResult result;
1202
1203 if (dst->image->vk.format == VK_FORMAT_R32G32B32_UINT || dst->image->vk.format == VK_FORMAT_R32G32B32_SINT ||
1204 dst->image->vk.format == VK_FORMAT_R32G32B32_SFLOAT) {
1205 radv_meta_buffer_to_image_cs_r32g32b32(cmd_buffer, src, dst, rect);
1206 return;
1207 }
1208
1209 result = get_btoi_pipeline(device, dst->image, &pipeline, &layout);
1210 if (result != VK_SUCCESS) {
1211 vk_command_buffer_set_error(&cmd_buffer->vk, result);
1212 return;
1213 }
1214
1215 create_bview(cmd_buffer, src->buffer, src->offset, src->format, &src_view);
1216 create_iview(cmd_buffer, dst, &dst_view, VK_FORMAT_UNDEFINED, dst->aspect_mask);
1217
1218 radv_meta_push_descriptor_set(
1219 cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, 2,
1220 (VkWriteDescriptorSet[]){{
1221 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1222 .dstBinding = 0,
1223 .dstArrayElement = 0,
1224 .descriptorCount = 1,
1225 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
1226 .pTexelBufferView = (VkBufferView[]){radv_buffer_view_to_handle(&src_view)},
1227 },
1228 {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1229 .dstBinding = 1,
1230 .dstArrayElement = 0,
1231 .descriptorCount = 1,
1232 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
1233 .pImageInfo = (VkDescriptorImageInfo[]){
1234 {
1235 .sampler = VK_NULL_HANDLE,
1236 .imageView = radv_image_view_to_handle(&dst_view),
1237 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
1238 },
1239 }}});
1240
1241 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
1242
1243 unsigned push_constants[4] = {
1244 rect->dst_x,
1245 rect->dst_y,
1246 dst->layer,
1247 src->pitch,
1248 };
1249 vk_common_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 16,
1250 push_constants);
1251
1252 radv_unaligned_dispatch(cmd_buffer, rect->width, rect->height, 1);
1253 fixup_gfx9_cs_copy(cmd_buffer, src, dst, rect, true);
1254
1255 radv_image_view_finish(&dst_view);
1256 radv_buffer_view_finish(&src_view);
1257 }
1258
1259 static void
radv_meta_image_to_image_cs_r32g32b32(struct radv_cmd_buffer * cmd_buffer,struct radv_meta_blit2d_surf * src,struct radv_meta_blit2d_surf * dst,struct radv_meta_blit2d_rect * rect)1260 radv_meta_image_to_image_cs_r32g32b32(struct radv_cmd_buffer *cmd_buffer, struct radv_meta_blit2d_surf *src,
1261 struct radv_meta_blit2d_surf *dst, struct radv_meta_blit2d_rect *rect)
1262 {
1263 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
1264 struct radv_buffer_view src_view, dst_view;
1265 unsigned src_offset = 0, dst_offset = 0;
1266 unsigned src_stride, dst_stride;
1267 VkBuffer src_buffer, dst_buffer;
1268 VkPipelineLayout layout;
1269 VkPipeline pipeline;
1270 VkResult result;
1271
1272 result = get_itoi_r32g32b32_pipeline(device, &pipeline, &layout);
1273 if (result != VK_SUCCESS) {
1274 vk_command_buffer_set_error(&cmd_buffer->vk, result);
1275 return;
1276 }
1277
1278 /* 96-bit formats are only compatible to themselves. */
1279 assert(dst->format == VK_FORMAT_R32G32B32_UINT || dst->format == VK_FORMAT_R32G32B32_SINT ||
1280 dst->format == VK_FORMAT_R32G32B32_SFLOAT);
1281
1282 /* This special itoi path for R32G32B32 formats will write the linear
1283 * image as a buffer with the same underlying memory. The compute
1284 * shader will copy all components separately using a R32 format.
1285 */
1286 create_buffer_from_image(cmd_buffer, src, VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT, &src_buffer);
1287 create_buffer_from_image(cmd_buffer, dst, VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT, &dst_buffer);
1288
1289 create_bview_for_r32g32b32(cmd_buffer, radv_buffer_from_handle(src_buffer), src_offset, src->format, &src_view);
1290 create_bview_for_r32g32b32(cmd_buffer, radv_buffer_from_handle(dst_buffer), dst_offset, dst->format, &dst_view);
1291
1292 radv_meta_push_descriptor_set(
1293 cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, 2,
1294 (VkWriteDescriptorSet[]){{
1295 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1296 .dstBinding = 0,
1297 .dstArrayElement = 0,
1298 .descriptorCount = 1,
1299 .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
1300 .pTexelBufferView = (VkBufferView[]){radv_buffer_view_to_handle(&src_view)},
1301 },
1302 {
1303 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1304 .dstBinding = 1,
1305 .dstArrayElement = 0,
1306 .descriptorCount = 1,
1307 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
1308 .pTexelBufferView = (VkBufferView[]){radv_buffer_view_to_handle(&dst_view)},
1309 }});
1310
1311 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
1312
1313 src_stride = get_image_stride_for_r32g32b32(cmd_buffer, src);
1314 dst_stride = get_image_stride_for_r32g32b32(cmd_buffer, dst);
1315
1316 unsigned push_constants[6] = {
1317 rect->src_x, rect->src_y, src_stride, rect->dst_x, rect->dst_y, dst_stride,
1318 };
1319 vk_common_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 24,
1320 push_constants);
1321
1322 radv_unaligned_dispatch(cmd_buffer, rect->width, rect->height, 1);
1323
1324 radv_buffer_view_finish(&src_view);
1325 radv_buffer_view_finish(&dst_view);
1326 radv_DestroyBuffer(radv_device_to_handle(device), src_buffer, NULL);
1327 radv_DestroyBuffer(radv_device_to_handle(device), dst_buffer, NULL);
1328 }
1329
1330 void
radv_meta_image_to_image_cs(struct radv_cmd_buffer * cmd_buffer,struct radv_meta_blit2d_surf * src,struct radv_meta_blit2d_surf * dst,struct radv_meta_blit2d_rect * rect)1331 radv_meta_image_to_image_cs(struct radv_cmd_buffer *cmd_buffer, struct radv_meta_blit2d_surf *src,
1332 struct radv_meta_blit2d_surf *dst, struct radv_meta_blit2d_rect *rect)
1333 {
1334 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
1335 struct radv_image_view src_view, dst_view;
1336 uint32_t samples = src->image->vk.samples;
1337 VkPipelineLayout layout;
1338 VkPipeline pipeline;
1339 VkResult result;
1340
1341 if (src->format == VK_FORMAT_R32G32B32_UINT || src->format == VK_FORMAT_R32G32B32_SINT ||
1342 src->format == VK_FORMAT_R32G32B32_SFLOAT) {
1343 radv_meta_image_to_image_cs_r32g32b32(cmd_buffer, src, dst, rect);
1344 return;
1345 }
1346
1347 result = get_itoi_pipeline(device, src->image, dst->image, samples, &pipeline, &layout);
1348 if (result != VK_SUCCESS) {
1349 vk_command_buffer_set_error(&cmd_buffer->vk, result);
1350 return;
1351 }
1352
1353 u_foreach_bit (i, dst->aspect_mask) {
1354 unsigned dst_aspect_mask = 1u << i;
1355 unsigned src_aspect_mask = dst_aspect_mask;
1356 VkFormat depth_format = 0;
1357 if (dst_aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT)
1358 depth_format = vk_format_stencil_only(dst->image->vk.format);
1359 else if (dst_aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT)
1360 depth_format = vk_format_depth_only(dst->image->vk.format);
1361 else {
1362 /*
1363 * "Multi-planar images can only be copied on a per-plane basis, and the subresources used in each region when
1364 * copying to or from such images must specify only one plane, though different regions can specify different
1365 * planes."
1366 */
1367 assert((dst->aspect_mask & (dst->aspect_mask - 1)) == 0);
1368 assert((src->aspect_mask & (src->aspect_mask - 1)) == 0);
1369 src_aspect_mask = src->aspect_mask;
1370 }
1371
1372 /* Adjust the aspect for color to depth/stencil image copies. */
1373 if (vk_format_is_color(src->image->vk.format) && vk_format_is_depth_or_stencil(dst->image->vk.format)) {
1374 assert(src->aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT);
1375 src_aspect_mask = src->aspect_mask;
1376 }
1377
1378 create_iview(cmd_buffer, src, &src_view,
1379 (src_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) ? depth_format : 0,
1380 src_aspect_mask);
1381 create_iview(cmd_buffer, dst, &dst_view, depth_format, dst_aspect_mask);
1382
1383 radv_meta_push_descriptor_set(
1384 cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, 2,
1385 (VkWriteDescriptorSet[]){{.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1386 .dstBinding = 0,
1387 .dstArrayElement = 0,
1388 .descriptorCount = 1,
1389 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
1390 .pImageInfo =
1391 (VkDescriptorImageInfo[]){
1392 {
1393 .sampler = VK_NULL_HANDLE,
1394 .imageView = radv_image_view_to_handle(&src_view),
1395 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
1396 },
1397 }},
1398 {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1399 .dstBinding = 1,
1400 .dstArrayElement = 0,
1401 .descriptorCount = 1,
1402 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
1403 .pImageInfo = (VkDescriptorImageInfo[]){
1404 {
1405 .sampler = VK_NULL_HANDLE,
1406 .imageView = radv_image_view_to_handle(&dst_view),
1407 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
1408 },
1409 }}});
1410
1411 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
1412
1413 unsigned push_constants[6] = {
1414 rect->src_x, rect->src_y, src->layer, rect->dst_x, rect->dst_y, dst->layer,
1415 };
1416 vk_common_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 24,
1417 push_constants);
1418
1419 radv_unaligned_dispatch(cmd_buffer, rect->width, rect->height, 1);
1420
1421 radv_image_view_finish(&src_view);
1422 radv_image_view_finish(&dst_view);
1423 }
1424 }
1425
1426 static void
radv_meta_clear_image_cs_r32g32b32(struct radv_cmd_buffer * cmd_buffer,struct radv_meta_blit2d_surf * dst,const VkClearColorValue * clear_color)1427 radv_meta_clear_image_cs_r32g32b32(struct radv_cmd_buffer *cmd_buffer, struct radv_meta_blit2d_surf *dst,
1428 const VkClearColorValue *clear_color)
1429 {
1430 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
1431 struct radv_buffer_view dst_view;
1432 VkPipelineLayout layout;
1433 VkPipeline pipeline;
1434 unsigned stride;
1435 VkBuffer buffer;
1436 VkResult result;
1437
1438 result = get_cleari_r32g32b32_pipeline(device, &pipeline, &layout);
1439 if (result != VK_SUCCESS) {
1440 vk_command_buffer_set_error(&cmd_buffer->vk, result);
1441 return;
1442 }
1443
1444 /* This special clear path for R32G32B32 formats will write the linear
1445 * image as a buffer with the same underlying memory. The compute
1446 * shader will clear all components separately using a R32 format.
1447 */
1448 create_buffer_from_image(cmd_buffer, dst, VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT, &buffer);
1449
1450 create_bview_for_r32g32b32(cmd_buffer, radv_buffer_from_handle(buffer), 0, dst->format, &dst_view);
1451
1452 radv_meta_push_descriptor_set(cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, 1,
1453 (VkWriteDescriptorSet[]){{
1454 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1455 .dstBinding = 0,
1456 .dstArrayElement = 0,
1457 .descriptorCount = 1,
1458 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
1459 .pTexelBufferView = (VkBufferView[]){radv_buffer_view_to_handle(&dst_view)},
1460 }});
1461
1462 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
1463
1464 stride = get_image_stride_for_r32g32b32(cmd_buffer, dst);
1465
1466 unsigned push_constants[4] = {
1467 clear_color->uint32[0],
1468 clear_color->uint32[1],
1469 clear_color->uint32[2],
1470 stride,
1471 };
1472
1473 vk_common_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 16,
1474 push_constants);
1475
1476 radv_unaligned_dispatch(cmd_buffer, dst->image->vk.extent.width, dst->image->vk.extent.height, 1);
1477
1478 radv_buffer_view_finish(&dst_view);
1479 radv_DestroyBuffer(radv_device_to_handle(device), buffer, NULL);
1480 }
1481
1482 void
radv_meta_clear_image_cs(struct radv_cmd_buffer * cmd_buffer,struct radv_meta_blit2d_surf * dst,const VkClearColorValue * clear_color)1483 radv_meta_clear_image_cs(struct radv_cmd_buffer *cmd_buffer, struct radv_meta_blit2d_surf *dst,
1484 const VkClearColorValue *clear_color)
1485 {
1486 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
1487 struct radv_image_view dst_iview;
1488 VkPipelineLayout layout;
1489 VkPipeline pipeline;
1490 VkResult result;
1491
1492 if (dst->format == VK_FORMAT_R32G32B32_UINT || dst->format == VK_FORMAT_R32G32B32_SINT ||
1493 dst->format == VK_FORMAT_R32G32B32_SFLOAT) {
1494 radv_meta_clear_image_cs_r32g32b32(cmd_buffer, dst, clear_color);
1495 return;
1496 }
1497
1498 result = get_cleari_pipeline(device, dst->image, &pipeline, &layout);
1499 if (result != VK_SUCCESS) {
1500 vk_command_buffer_set_error(&cmd_buffer->vk, result);
1501 return;
1502 }
1503
1504 create_iview(cmd_buffer, dst, &dst_iview, VK_FORMAT_UNDEFINED, dst->aspect_mask);
1505
1506 radv_meta_push_descriptor_set(cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, 1,
1507 (VkWriteDescriptorSet[]){
1508 {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1509 .dstBinding = 0,
1510 .dstArrayElement = 0,
1511 .descriptorCount = 1,
1512 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
1513 .pImageInfo =
1514 (VkDescriptorImageInfo[]){
1515 {
1516 .sampler = VK_NULL_HANDLE,
1517 .imageView = radv_image_view_to_handle(&dst_iview),
1518 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
1519 },
1520 }},
1521 });
1522
1523 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
1524
1525 unsigned push_constants[5] = {
1526 clear_color->uint32[0], clear_color->uint32[1], clear_color->uint32[2], clear_color->uint32[3], dst->layer,
1527 };
1528
1529 vk_common_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 20,
1530 push_constants);
1531
1532 radv_unaligned_dispatch(cmd_buffer, dst->image->vk.extent.width, dst->image->vk.extent.height, 1);
1533
1534 radv_image_view_finish(&dst_iview);
1535 }
1536