• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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