1 /*
2 * Copyright © 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include <assert.h>
8 #include <stdbool.h>
9
10 #include "radv_meta.h"
11 #include "sid.h"
12
13 enum radv_color_op {
14 FAST_CLEAR_ELIMINATE,
15 FMASK_DECOMPRESS,
16 DCC_DECOMPRESS,
17 };
18
19 static nir_shader *
build_dcc_decompress_compute_shader(struct radv_device * dev)20 build_dcc_decompress_compute_shader(struct radv_device *dev)
21 {
22 const struct glsl_type *img_type = glsl_image_type(GLSL_SAMPLER_DIM_2D, false, GLSL_TYPE_FLOAT);
23
24 nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_COMPUTE, "dcc_decompress_compute");
25
26 /* We need at least 16/16/1 to cover an entire DCC block in a single workgroup. */
27 b.shader->info.workgroup_size[0] = 16;
28 b.shader->info.workgroup_size[1] = 16;
29 nir_variable *input_img = nir_variable_create(b.shader, nir_var_image, img_type, "in_img");
30 input_img->data.descriptor_set = 0;
31 input_img->data.binding = 0;
32
33 nir_variable *output_img = nir_variable_create(b.shader, nir_var_image, img_type, "out_img");
34 output_img->data.descriptor_set = 0;
35 output_img->data.binding = 1;
36
37 nir_def *global_id = get_global_ids(&b, 2);
38 nir_def *img_coord = nir_vec4(&b, nir_channel(&b, global_id, 0), nir_channel(&b, global_id, 1), nir_undef(&b, 1, 32),
39 nir_undef(&b, 1, 32));
40
41 nir_def *data = nir_image_deref_load(&b, 4, 32, &nir_build_deref_var(&b, input_img)->def, img_coord,
42 nir_undef(&b, 1, 32), nir_imm_int(&b, 0), .image_dim = GLSL_SAMPLER_DIM_2D);
43
44 /* We need a SCOPE_DEVICE memory_scope because ACO will avoid
45 * creating a vmcnt(0) because it expects the L1 cache to keep memory
46 * operations in-order for the same workgroup. The vmcnt(0) seems
47 * necessary however. */
48 nir_barrier(&b, .execution_scope = SCOPE_WORKGROUP, .memory_scope = SCOPE_DEVICE,
49 .memory_semantics = NIR_MEMORY_ACQ_REL, .memory_modes = nir_var_mem_ssbo);
50
51 nir_image_deref_store(&b, &nir_build_deref_var(&b, output_img)->def, img_coord, nir_undef(&b, 1, 32), data,
52 nir_imm_int(&b, 0), .image_dim = GLSL_SAMPLER_DIM_2D);
53 return b.shader;
54 }
55
56 static VkResult
get_dcc_decompress_compute_pipeline(struct radv_device * device,VkPipeline * pipeline_out,VkPipelineLayout * layout_out)57 get_dcc_decompress_compute_pipeline(struct radv_device *device, VkPipeline *pipeline_out, VkPipelineLayout *layout_out)
58 {
59 enum radv_meta_object_key_type key = RADV_META_OBJECT_KEY_DCC_DECOMPRESS;
60 VkResult result;
61
62 const VkDescriptorSetLayoutBinding bindings[] = {
63 {
64 .binding = 0,
65 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
66 .descriptorCount = 1,
67 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
68 },
69 {
70 .binding = 1,
71 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
72 .descriptorCount = 1,
73 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
74 },
75 };
76
77 const VkDescriptorSetLayoutCreateInfo desc_info = {
78 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
79 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT,
80 .bindingCount = 2,
81 .pBindings = bindings,
82 };
83
84 result = vk_meta_get_pipeline_layout(&device->vk, &device->meta_state.device, &desc_info, NULL, &key, sizeof(key),
85 layout_out);
86 if (result != VK_SUCCESS)
87 return result;
88
89 VkPipeline pipeline_from_cache = vk_meta_lookup_pipeline(&device->meta_state.device, &key, sizeof(key));
90 if (pipeline_from_cache != VK_NULL_HANDLE) {
91 *pipeline_out = pipeline_from_cache;
92 return VK_SUCCESS;
93 }
94
95 nir_shader *cs = build_dcc_decompress_compute_shader(device);
96
97 const VkPipelineShaderStageCreateInfo stage_info = {
98 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
99 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
100 .module = vk_shader_module_handle_from_nir(cs),
101 .pName = "main",
102 .pSpecializationInfo = NULL,
103 };
104
105 const VkComputePipelineCreateInfo pipeline_info = {
106 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
107 .stage = stage_info,
108 .flags = 0,
109 .layout = *layout_out,
110 };
111
112 result = vk_meta_create_compute_pipeline(&device->vk, &device->meta_state.device, &pipeline_info, &key, sizeof(key),
113 pipeline_out);
114
115 ralloc_free(cs);
116 return result;
117 }
118
119 static VkResult
get_pipeline(struct radv_device * device,enum radv_color_op op,VkPipeline * pipeline_out,VkPipelineLayout * layout_out)120 get_pipeline(struct radv_device *device, enum radv_color_op op, VkPipeline *pipeline_out, VkPipelineLayout *layout_out)
121 {
122 const struct radv_physical_device *pdev = radv_device_physical(device);
123 enum radv_meta_object_key_type key = 0;
124 VkResult result;
125
126 switch (op) {
127 case FAST_CLEAR_ELIMINATE:
128 key = RADV_META_OBJECT_KEY_FAST_CLEAR_ELIMINATE;
129 break;
130 case FMASK_DECOMPRESS:
131 key = RADV_META_OBJECT_KEY_FMASK_DECOMPRESS;
132 break;
133 case DCC_DECOMPRESS:
134 key = RADV_META_OBJECT_KEY_DCC_DECOMPRESS;
135 break;
136 }
137
138 result = radv_meta_get_noop_pipeline_layout(device, layout_out);
139 if (result != VK_SUCCESS)
140 return result;
141
142 VkPipeline pipeline_from_cache = vk_meta_lookup_pipeline(&device->meta_state.device, &key, sizeof(key));
143 if (pipeline_from_cache != VK_NULL_HANDLE) {
144 *pipeline_out = pipeline_from_cache;
145 return VK_SUCCESS;
146 }
147
148 nir_shader *vs_module = radv_meta_build_nir_vs_generate_vertices(device);
149 nir_shader *fs_module = radv_meta_build_nir_fs_noop(device);
150
151 VkGraphicsPipelineCreateInfoRADV radv_info = {
152 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO_RADV,
153 };
154
155 switch (op) {
156 case FAST_CLEAR_ELIMINATE:
157 radv_info.custom_blend_mode = V_028808_CB_ELIMINATE_FAST_CLEAR;
158 break;
159 case FMASK_DECOMPRESS:
160 radv_info.custom_blend_mode = V_028808_CB_FMASK_DECOMPRESS;
161 break;
162 case DCC_DECOMPRESS:
163 radv_info.custom_blend_mode =
164 pdev->info.gfx_level >= GFX11 ? V_028808_CB_DCC_DECOMPRESS_GFX11 : V_028808_CB_DCC_DECOMPRESS_GFX8;
165 break;
166 default:
167 unreachable("Invalid color op");
168 }
169
170 const VkGraphicsPipelineCreateInfo pipeline_create_info = {
171 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
172 .pNext = &radv_info,
173 .stageCount = 2,
174 .pStages =
175 (VkPipelineShaderStageCreateInfo[]){
176 {
177 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
178 .stage = VK_SHADER_STAGE_VERTEX_BIT,
179 .module = vk_shader_module_handle_from_nir(vs_module),
180 .pName = "main",
181 },
182 {
183 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
184 .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
185 .module = vk_shader_module_handle_from_nir(fs_module),
186 .pName = "main",
187 },
188 },
189 .pVertexInputState =
190 &(VkPipelineVertexInputStateCreateInfo){
191 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
192 .vertexBindingDescriptionCount = 0,
193 .vertexAttributeDescriptionCount = 0,
194 },
195 .pInputAssemblyState =
196 &(VkPipelineInputAssemblyStateCreateInfo){
197 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
198 .topology = VK_PRIMITIVE_TOPOLOGY_META_RECT_LIST_MESA,
199 .primitiveRestartEnable = false,
200 },
201 .pViewportState =
202 &(VkPipelineViewportStateCreateInfo){
203 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
204 .viewportCount = 1,
205 .scissorCount = 1,
206 },
207 .pRasterizationState =
208 &(VkPipelineRasterizationStateCreateInfo){
209 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
210 .depthClampEnable = false,
211 .rasterizerDiscardEnable = false,
212 .polygonMode = VK_POLYGON_MODE_FILL,
213 .cullMode = VK_CULL_MODE_NONE,
214 .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
215 },
216 .pMultisampleState =
217 &(VkPipelineMultisampleStateCreateInfo){
218 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
219 .rasterizationSamples = 1,
220 .sampleShadingEnable = false,
221 .pSampleMask = NULL,
222 .alphaToCoverageEnable = false,
223 .alphaToOneEnable = false,
224 },
225 .pColorBlendState =
226 &(VkPipelineColorBlendStateCreateInfo){
227 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
228 .logicOpEnable = false,
229 .attachmentCount = 1,
230 .pAttachments =
231 (VkPipelineColorBlendAttachmentState[]){
232 {
233 .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
234 VK_COLOR_COMPONENT_A_BIT,
235 },
236 },
237 },
238 .pDynamicState =
239 &(VkPipelineDynamicStateCreateInfo){
240 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
241 .dynamicStateCount = 2,
242 .pDynamicStates =
243 (VkDynamicState[]){
244 VK_DYNAMIC_STATE_VIEWPORT,
245 VK_DYNAMIC_STATE_SCISSOR,
246 },
247 },
248 .layout = *layout_out,
249 };
250
251 struct vk_meta_rendering_info render = {
252 .color_attachment_count = 1,
253 .color_attachment_formats = {VK_FORMAT_R8_UNORM},
254 };
255
256 result = vk_meta_create_graphics_pipeline(&device->vk, &device->meta_state.device, &pipeline_create_info, &render,
257 &key, sizeof(key), pipeline_out);
258
259 ralloc_free(vs_module);
260 ralloc_free(fs_module);
261 return result;
262 }
263
264 static void
radv_emit_set_predication_state_from_image(struct radv_cmd_buffer * cmd_buffer,struct radv_image * image,uint64_t pred_offset,bool value)265 radv_emit_set_predication_state_from_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
266 uint64_t pred_offset, bool value)
267 {
268 uint64_t va = 0;
269
270 if (value)
271 va = radv_image_get_va(image, 0) + pred_offset;
272
273 radv_emit_set_predication_state(cmd_buffer, true, PREDICATION_OP_BOOL64, va);
274 }
275
276 static void
radv_process_color_image_layer(struct radv_cmd_buffer * cmd_buffer,struct radv_image * image,const VkImageSubresourceRange * range,int level,int layer,bool flush_cb)277 radv_process_color_image_layer(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
278 const VkImageSubresourceRange *range, int level, int layer, bool flush_cb)
279 {
280 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
281 struct radv_image_view iview;
282 uint32_t width, height;
283
284 width = u_minify(image->vk.extent.width, range->baseMipLevel + level);
285 height = u_minify(image->vk.extent.height, range->baseMipLevel + level);
286
287 radv_image_view_init(&iview, device,
288 &(VkImageViewCreateInfo){
289 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
290 .image = radv_image_to_handle(image),
291 .viewType = radv_meta_get_view_type(image),
292 .format = image->vk.format,
293 .subresourceRange =
294 {
295 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
296 .baseMipLevel = range->baseMipLevel + level,
297 .levelCount = 1,
298 .baseArrayLayer = range->baseArrayLayer + layer,
299 .layerCount = 1,
300 },
301 },
302 NULL);
303
304 const VkRenderingAttachmentInfo color_att = {
305 .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
306 .imageView = radv_image_view_to_handle(&iview),
307 .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
308 .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
309 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
310 };
311
312 const VkRenderingInfo rendering_info = {
313 .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
314 .flags = VK_RENDERING_INPUT_ATTACHMENT_NO_CONCURRENT_WRITES_BIT_MESA,
315 .renderArea = {.offset = {0, 0}, .extent = {width, height}},
316 .layerCount = 1,
317 .colorAttachmentCount = 1,
318 .pColorAttachments = &color_att,
319 };
320
321 radv_CmdBeginRendering(radv_cmd_buffer_to_handle(cmd_buffer), &rendering_info);
322
323 if (flush_cb)
324 cmd_buffer->state.flush_bits |= radv_dst_access_flush(cmd_buffer, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
325 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT, 0, image, range);
326
327 radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
328
329 if (flush_cb)
330 cmd_buffer->state.flush_bits |= radv_src_access_flush(cmd_buffer, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
331 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, 0, image, range);
332
333 radv_CmdEndRendering(radv_cmd_buffer_to_handle(cmd_buffer));
334
335 radv_image_view_finish(&iview);
336 }
337
338 static void
radv_process_color_image(struct radv_cmd_buffer * cmd_buffer,struct radv_image * image,const VkImageSubresourceRange * subresourceRange,enum radv_color_op op)339 radv_process_color_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
340 const VkImageSubresourceRange *subresourceRange, enum radv_color_op op)
341 {
342 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
343 struct radv_meta_saved_state saved_state;
344 bool old_predicating = false;
345 bool flush_cb = false;
346 uint64_t pred_offset;
347 VkPipelineLayout layout;
348 VkPipeline pipeline;
349 VkResult result;
350
351 result = get_pipeline(device, op, &pipeline, &layout);
352 if (result != VK_SUCCESS) {
353 vk_command_buffer_set_error(&cmd_buffer->vk, result);
354 return;
355 }
356
357 switch (op) {
358 case FAST_CLEAR_ELIMINATE:
359 pred_offset = image->fce_pred_offset;
360 break;
361 case FMASK_DECOMPRESS:
362 pred_offset = 0; /* FMASK_DECOMPRESS is never predicated. */
363
364 /* Flushing CB is required before and after FMASK_DECOMPRESS. */
365 flush_cb = true;
366 break;
367 case DCC_DECOMPRESS:
368 pred_offset = image->dcc_pred_offset;
369
370 /* Flushing CB is required before and after DCC_DECOMPRESS. */
371 flush_cb = true;
372 break;
373 default:
374 unreachable("Invalid color op");
375 }
376
377 if (radv_dcc_enabled(image, subresourceRange->baseMipLevel) &&
378 (image->vk.array_layers != vk_image_subresource_layer_count(&image->vk, subresourceRange) ||
379 subresourceRange->baseArrayLayer != 0)) {
380 /* Only use predication if the image has DCC with mipmaps or
381 * if the range of layers covers the whole image because the
382 * predication is based on mip level.
383 */
384 pred_offset = 0;
385 }
386
387 radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_RENDER);
388
389 if (pred_offset) {
390 pred_offset += 8 * subresourceRange->baseMipLevel;
391
392 old_predicating = cmd_buffer->state.predicating;
393
394 radv_emit_set_predication_state_from_image(cmd_buffer, image, pred_offset, true);
395 cmd_buffer->state.predicating = true;
396 }
397
398 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
399
400 for (uint32_t l = 0; l < vk_image_subresource_level_count(&image->vk, subresourceRange); ++l) {
401 uint32_t width, height;
402
403 /* Do not decompress levels without DCC. */
404 if (op == DCC_DECOMPRESS && !radv_dcc_enabled(image, subresourceRange->baseMipLevel + l))
405 continue;
406
407 width = u_minify(image->vk.extent.width, subresourceRange->baseMipLevel + l);
408 height = u_minify(image->vk.extent.height, subresourceRange->baseMipLevel + l);
409
410 radv_CmdSetViewport(
411 radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
412 &(VkViewport){.x = 0, .y = 0, .width = width, .height = height, .minDepth = 0.0f, .maxDepth = 1.0f});
413
414 radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
415 &(VkRect2D){
416 .offset = {0, 0},
417 .extent = {width, height},
418 });
419
420 for (uint32_t s = 0; s < vk_image_subresource_layer_count(&image->vk, subresourceRange); s++) {
421 radv_process_color_image_layer(cmd_buffer, image, subresourceRange, l, s, flush_cb);
422 }
423 }
424
425 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB | RADV_CMD_FLAG_FLUSH_AND_INV_CB_META;
426
427 if (pred_offset) {
428 pred_offset += 8 * subresourceRange->baseMipLevel;
429
430 cmd_buffer->state.predicating = old_predicating;
431
432 radv_emit_set_predication_state_from_image(cmd_buffer, image, pred_offset, false);
433
434 if (cmd_buffer->state.predication_type != -1) {
435 /* Restore previous conditional rendering user state. */
436 radv_emit_set_predication_state(cmd_buffer, cmd_buffer->state.predication_type,
437 cmd_buffer->state.predication_op, cmd_buffer->state.predication_va);
438 }
439 }
440
441 radv_meta_restore(&saved_state, cmd_buffer);
442
443 /* Clear the image's fast-clear eliminate predicate because FMASK_DECOMPRESS and DCC_DECOMPRESS
444 * also perform a fast-clear eliminate.
445 */
446 radv_update_fce_metadata(cmd_buffer, image, subresourceRange, false);
447
448 /* Mark the image as being decompressed. */
449 if (op == DCC_DECOMPRESS)
450 radv_update_dcc_metadata(cmd_buffer, image, subresourceRange, false);
451 }
452
453 static void
radv_fast_clear_eliminate(struct radv_cmd_buffer * cmd_buffer,struct radv_image * image,const VkImageSubresourceRange * subresourceRange)454 radv_fast_clear_eliminate(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
455 const VkImageSubresourceRange *subresourceRange)
456 {
457 struct radv_barrier_data barrier = {0};
458
459 barrier.layout_transitions.fast_clear_eliminate = 1;
460 radv_describe_layout_transition(cmd_buffer, &barrier);
461
462 radv_process_color_image(cmd_buffer, image, subresourceRange, FAST_CLEAR_ELIMINATE);
463 }
464
465 static void
radv_fmask_decompress(struct radv_cmd_buffer * cmd_buffer,struct radv_image * image,const VkImageSubresourceRange * subresourceRange)466 radv_fmask_decompress(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
467 const VkImageSubresourceRange *subresourceRange)
468 {
469 struct radv_barrier_data barrier = {0};
470
471 barrier.layout_transitions.fmask_decompress = 1;
472 radv_describe_layout_transition(cmd_buffer, &barrier);
473
474 radv_process_color_image(cmd_buffer, image, subresourceRange, FMASK_DECOMPRESS);
475 }
476
477 void
radv_fast_clear_flush_image_inplace(struct radv_cmd_buffer * cmd_buffer,struct radv_image * image,const VkImageSubresourceRange * subresourceRange)478 radv_fast_clear_flush_image_inplace(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
479 const VkImageSubresourceRange *subresourceRange)
480 {
481 if (radv_image_has_fmask(image) && !image->tc_compatible_cmask) {
482 if (radv_image_has_dcc(image) && radv_image_has_cmask(image)) {
483 /* MSAA images with DCC and CMASK might have been fast-cleared and might require a FCE but
484 * FMASK_DECOMPRESS can't eliminate DCC fast clears.
485 */
486 radv_fast_clear_eliminate(cmd_buffer, image, subresourceRange);
487 }
488
489 radv_fmask_decompress(cmd_buffer, image, subresourceRange);
490 } else {
491 /* Skip fast clear eliminate for images that support comp-to-single fast clears. */
492 if (image->support_comp_to_single)
493 return;
494
495 radv_fast_clear_eliminate(cmd_buffer, image, subresourceRange);
496 }
497 }
498
499 static void
radv_decompress_dcc_compute(struct radv_cmd_buffer * cmd_buffer,struct radv_image * image,const VkImageSubresourceRange * subresourceRange)500 radv_decompress_dcc_compute(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
501 const VkImageSubresourceRange *subresourceRange)
502 {
503 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
504 struct radv_meta_saved_state saved_state;
505 struct radv_image_view load_iview = {0};
506 struct radv_image_view store_iview = {0};
507 VkPipelineLayout layout;
508 VkPipeline pipeline;
509 VkResult result;
510
511 result = get_dcc_decompress_compute_pipeline(device, &pipeline, &layout);
512 if (result != VK_SUCCESS) {
513 vk_command_buffer_set_error(&cmd_buffer->vk, result);
514 return;
515 }
516
517 cmd_buffer->state.flush_bits |= radv_dst_access_flush(cmd_buffer, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
518 VK_ACCESS_2_SHADER_READ_BIT, 0, image, subresourceRange);
519
520 radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_DESCRIPTORS | RADV_META_SAVE_COMPUTE_PIPELINE);
521
522 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
523
524 for (uint32_t l = 0; l < vk_image_subresource_level_count(&image->vk, subresourceRange); l++) {
525 uint32_t width, height;
526
527 /* Do not decompress levels without DCC. */
528 if (!radv_dcc_enabled(image, subresourceRange->baseMipLevel + l))
529 continue;
530
531 width = u_minify(image->vk.extent.width, subresourceRange->baseMipLevel + l);
532 height = u_minify(image->vk.extent.height, subresourceRange->baseMipLevel + l);
533
534 for (uint32_t s = 0; s < vk_image_subresource_layer_count(&image->vk, subresourceRange); s++) {
535 radv_image_view_init(&load_iview, device,
536 &(VkImageViewCreateInfo){
537 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
538 .image = radv_image_to_handle(image),
539 .viewType = VK_IMAGE_VIEW_TYPE_2D,
540 .format = image->vk.format,
541 .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
542 .baseMipLevel = subresourceRange->baseMipLevel + l,
543 .levelCount = 1,
544 .baseArrayLayer = subresourceRange->baseArrayLayer + s,
545 .layerCount = 1},
546 },
547 &(struct radv_image_view_extra_create_info){.enable_compression = true});
548 radv_image_view_init(&store_iview, device,
549 &(VkImageViewCreateInfo){
550 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
551 .image = radv_image_to_handle(image),
552 .viewType = VK_IMAGE_VIEW_TYPE_2D,
553 .format = image->vk.format,
554 .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
555 .baseMipLevel = subresourceRange->baseMipLevel + l,
556 .levelCount = 1,
557 .baseArrayLayer = subresourceRange->baseArrayLayer + s,
558 .layerCount = 1},
559 },
560 &(struct radv_image_view_extra_create_info){.disable_compression = true});
561
562 radv_meta_push_descriptor_set(
563 cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, 2,
564 (VkWriteDescriptorSet[]){{.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
565 .dstBinding = 0,
566 .dstArrayElement = 0,
567 .descriptorCount = 1,
568 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
569 .pImageInfo =
570 (VkDescriptorImageInfo[]){
571 {
572 .sampler = VK_NULL_HANDLE,
573 .imageView = radv_image_view_to_handle(&load_iview),
574 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
575 },
576 }},
577 {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
578 .dstBinding = 1,
579 .dstArrayElement = 0,
580 .descriptorCount = 1,
581 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
582 .pImageInfo = (VkDescriptorImageInfo[]){
583 {
584 .sampler = VK_NULL_HANDLE,
585 .imageView = radv_image_view_to_handle(&store_iview),
586 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
587 },
588 }}});
589
590 radv_unaligned_dispatch(cmd_buffer, width, height, 1);
591
592 radv_image_view_finish(&load_iview);
593 radv_image_view_finish(&store_iview);
594 }
595 }
596
597 /* Mark this image as actually being decompressed. */
598 radv_update_dcc_metadata(cmd_buffer, image, subresourceRange, false);
599
600 radv_meta_restore(&saved_state, cmd_buffer);
601
602 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_CS_PARTIAL_FLUSH | RADV_CMD_FLAG_INV_VCACHE |
603 radv_src_access_flush(cmd_buffer, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
604 VK_ACCESS_2_SHADER_WRITE_BIT, 0, image, subresourceRange);
605
606 /* Initialize the DCC metadata as "fully expanded". */
607 cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, image, subresourceRange, 0xffffffff);
608 }
609
610 void
radv_decompress_dcc(struct radv_cmd_buffer * cmd_buffer,struct radv_image * image,const VkImageSubresourceRange * subresourceRange)611 radv_decompress_dcc(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
612 const VkImageSubresourceRange *subresourceRange)
613 {
614 struct radv_barrier_data barrier = {0};
615
616 barrier.layout_transitions.dcc_decompress = 1;
617 radv_describe_layout_transition(cmd_buffer, &barrier);
618
619 if (cmd_buffer->qf == RADV_QUEUE_GENERAL)
620 radv_process_color_image(cmd_buffer, image, subresourceRange, DCC_DECOMPRESS);
621 else
622 radv_decompress_dcc_compute(cmd_buffer, image, subresourceRange);
623 }
624