1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2016 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <assert.h>
25bf215546Sopenharmony_ci#include <stdbool.h>
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "radv_meta.h"
28bf215546Sopenharmony_ci#include "radv_private.h"
29bf215546Sopenharmony_ci#include "sid.h"
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_cienum radv_color_op {
32bf215546Sopenharmony_ci   FAST_CLEAR_ELIMINATE,
33bf215546Sopenharmony_ci   FMASK_DECOMPRESS,
34bf215546Sopenharmony_ci   DCC_DECOMPRESS,
35bf215546Sopenharmony_ci};
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_cistatic nir_shader *
38bf215546Sopenharmony_cibuild_dcc_decompress_compute_shader(struct radv_device *dev)
39bf215546Sopenharmony_ci{
40bf215546Sopenharmony_ci   const struct glsl_type *img_type = glsl_image_type(GLSL_SAMPLER_DIM_2D, false, GLSL_TYPE_FLOAT);
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci   nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_COMPUTE, "dcc_decompress_compute");
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci   /* We need at least 16/16/1 to cover an entire DCC block in a single workgroup. */
45bf215546Sopenharmony_ci   b.shader->info.workgroup_size[0] = 16;
46bf215546Sopenharmony_ci   b.shader->info.workgroup_size[1] = 16;
47bf215546Sopenharmony_ci   nir_variable *input_img = nir_variable_create(b.shader, nir_var_image, img_type, "in_img");
48bf215546Sopenharmony_ci   input_img->data.descriptor_set = 0;
49bf215546Sopenharmony_ci   input_img->data.binding = 0;
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci   nir_variable *output_img = nir_variable_create(b.shader, nir_var_image, img_type, "out_img");
52bf215546Sopenharmony_ci   output_img->data.descriptor_set = 0;
53bf215546Sopenharmony_ci   output_img->data.binding = 1;
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci   nir_ssa_def *global_id = get_global_ids(&b, 2);
56bf215546Sopenharmony_ci   nir_ssa_def *img_coord = nir_vec4(&b, nir_channel(&b, global_id, 0),
57bf215546Sopenharmony_ci                                         nir_channel(&b, global_id, 1),
58bf215546Sopenharmony_ci                                         nir_ssa_undef(&b, 1, 32),
59bf215546Sopenharmony_ci                                         nir_ssa_undef(&b, 1, 32));
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci   nir_ssa_def *data = nir_image_deref_load(
62bf215546Sopenharmony_ci      &b, 4, 32, &nir_build_deref_var(&b, input_img)->dest.ssa, img_coord, nir_ssa_undef(&b, 1, 32),
63bf215546Sopenharmony_ci      nir_imm_int(&b, 0), .image_dim = GLSL_SAMPLER_DIM_2D);
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   /* We need a NIR_SCOPE_DEVICE memory_scope because ACO will avoid
66bf215546Sopenharmony_ci    * creating a vmcnt(0) because it expects the L1 cache to keep memory
67bf215546Sopenharmony_ci    * operations in-order for the same workgroup. The vmcnt(0) seems
68bf215546Sopenharmony_ci    * necessary however. */
69bf215546Sopenharmony_ci   nir_scoped_barrier(&b, .execution_scope = NIR_SCOPE_WORKGROUP, .memory_scope = NIR_SCOPE_DEVICE,
70bf215546Sopenharmony_ci                      .memory_semantics = NIR_MEMORY_ACQ_REL, .memory_modes = nir_var_mem_ssbo);
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   nir_image_deref_store(&b, &nir_build_deref_var(&b, output_img)->dest.ssa, img_coord,
73bf215546Sopenharmony_ci                         nir_ssa_undef(&b, 1, 32), data, nir_imm_int(&b, 0),
74bf215546Sopenharmony_ci                         .image_dim = GLSL_SAMPLER_DIM_2D);
75bf215546Sopenharmony_ci   return b.shader;
76bf215546Sopenharmony_ci}
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_cistatic VkResult
79bf215546Sopenharmony_cicreate_dcc_compress_compute(struct radv_device *device)
80bf215546Sopenharmony_ci{
81bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
82bf215546Sopenharmony_ci   nir_shader *cs = build_dcc_decompress_compute_shader(device);
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   VkDescriptorSetLayoutCreateInfo ds_create_info = {
85bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
86bf215546Sopenharmony_ci      .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
87bf215546Sopenharmony_ci      .bindingCount = 2,
88bf215546Sopenharmony_ci      .pBindings = (VkDescriptorSetLayoutBinding[]){
89bf215546Sopenharmony_ci         {.binding = 0,
90bf215546Sopenharmony_ci          .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
91bf215546Sopenharmony_ci          .descriptorCount = 1,
92bf215546Sopenharmony_ci          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
93bf215546Sopenharmony_ci          .pImmutableSamplers = NULL},
94bf215546Sopenharmony_ci         {.binding = 1,
95bf215546Sopenharmony_ci          .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
96bf215546Sopenharmony_ci          .descriptorCount = 1,
97bf215546Sopenharmony_ci          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
98bf215546Sopenharmony_ci          .pImmutableSamplers = NULL},
99bf215546Sopenharmony_ci      }};
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   result = radv_CreateDescriptorSetLayout(
102bf215546Sopenharmony_ci      radv_device_to_handle(device), &ds_create_info, &device->meta_state.alloc,
103bf215546Sopenharmony_ci      &device->meta_state.fast_clear_flush.dcc_decompress_compute_ds_layout);
104bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
105bf215546Sopenharmony_ci      goto cleanup;
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   VkPipelineLayoutCreateInfo pl_create_info = {
108bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
109bf215546Sopenharmony_ci      .setLayoutCount = 1,
110bf215546Sopenharmony_ci      .pSetLayouts = &device->meta_state.fast_clear_flush.dcc_decompress_compute_ds_layout,
111bf215546Sopenharmony_ci      .pushConstantRangeCount = 0,
112bf215546Sopenharmony_ci      .pPushConstantRanges = NULL,
113bf215546Sopenharmony_ci   };
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci   result = radv_CreatePipelineLayout(
116bf215546Sopenharmony_ci      radv_device_to_handle(device), &pl_create_info, &device->meta_state.alloc,
117bf215546Sopenharmony_ci      &device->meta_state.fast_clear_flush.dcc_decompress_compute_p_layout);
118bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
119bf215546Sopenharmony_ci      goto cleanup;
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci   /* compute shader */
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci   VkPipelineShaderStageCreateInfo pipeline_shader_stage = {
124bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
125bf215546Sopenharmony_ci      .stage = VK_SHADER_STAGE_COMPUTE_BIT,
126bf215546Sopenharmony_ci      .module = vk_shader_module_handle_from_nir(cs),
127bf215546Sopenharmony_ci      .pName = "main",
128bf215546Sopenharmony_ci      .pSpecializationInfo = NULL,
129bf215546Sopenharmony_ci   };
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci   VkComputePipelineCreateInfo vk_pipeline_info = {
132bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
133bf215546Sopenharmony_ci      .stage = pipeline_shader_stage,
134bf215546Sopenharmony_ci      .flags = 0,
135bf215546Sopenharmony_ci      .layout = device->meta_state.fast_clear_flush.dcc_decompress_compute_p_layout,
136bf215546Sopenharmony_ci   };
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   result = radv_CreateComputePipelines(
139bf215546Sopenharmony_ci      radv_device_to_handle(device), radv_pipeline_cache_to_handle(&device->meta_state.cache), 1,
140bf215546Sopenharmony_ci      &vk_pipeline_info, NULL,
141bf215546Sopenharmony_ci      &device->meta_state.fast_clear_flush.dcc_decompress_compute_pipeline);
142bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
143bf215546Sopenharmony_ci      goto cleanup;
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_cicleanup:
146bf215546Sopenharmony_ci   ralloc_free(cs);
147bf215546Sopenharmony_ci   return result;
148bf215546Sopenharmony_ci}
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_cistatic VkResult
151bf215546Sopenharmony_cicreate_pipeline_layout(struct radv_device *device, VkPipelineLayout *layout)
152bf215546Sopenharmony_ci{
153bf215546Sopenharmony_ci   VkPipelineLayoutCreateInfo pl_create_info = {
154bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
155bf215546Sopenharmony_ci      .setLayoutCount = 0,
156bf215546Sopenharmony_ci      .pSetLayouts = NULL,
157bf215546Sopenharmony_ci      .pushConstantRangeCount = 0,
158bf215546Sopenharmony_ci      .pPushConstantRanges = NULL,
159bf215546Sopenharmony_ci   };
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   return radv_CreatePipelineLayout(radv_device_to_handle(device), &pl_create_info,
162bf215546Sopenharmony_ci                                    &device->meta_state.alloc, layout);
163bf215546Sopenharmony_ci}
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_cistatic VkResult
166bf215546Sopenharmony_cicreate_pipeline(struct radv_device *device, VkShaderModule vs_module_h, VkPipelineLayout layout)
167bf215546Sopenharmony_ci{
168bf215546Sopenharmony_ci   VkResult result;
169bf215546Sopenharmony_ci   VkDevice device_h = radv_device_to_handle(device);
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   nir_shader *fs_module = radv_meta_build_nir_fs_noop(device);
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci   if (!fs_module) {
174bf215546Sopenharmony_ci      /* XXX: Need more accurate error */
175bf215546Sopenharmony_ci      result = VK_ERROR_OUT_OF_HOST_MEMORY;
176bf215546Sopenharmony_ci      goto cleanup;
177bf215546Sopenharmony_ci   }
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   const VkPipelineShaderStageCreateInfo stages[2] = {
180bf215546Sopenharmony_ci      {
181bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
182bf215546Sopenharmony_ci         .stage = VK_SHADER_STAGE_VERTEX_BIT,
183bf215546Sopenharmony_ci         .module = vs_module_h,
184bf215546Sopenharmony_ci         .pName = "main",
185bf215546Sopenharmony_ci      },
186bf215546Sopenharmony_ci      {
187bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
188bf215546Sopenharmony_ci         .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
189bf215546Sopenharmony_ci         .module = vk_shader_module_handle_from_nir(fs_module),
190bf215546Sopenharmony_ci         .pName = "main",
191bf215546Sopenharmony_ci      },
192bf215546Sopenharmony_ci   };
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   const VkPipelineVertexInputStateCreateInfo vi_state = {
195bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
196bf215546Sopenharmony_ci      .vertexBindingDescriptionCount = 0,
197bf215546Sopenharmony_ci      .vertexAttributeDescriptionCount = 0,
198bf215546Sopenharmony_ci   };
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   const VkPipelineInputAssemblyStateCreateInfo ia_state = {
201bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
202bf215546Sopenharmony_ci      .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
203bf215546Sopenharmony_ci      .primitiveRestartEnable = false,
204bf215546Sopenharmony_ci   };
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci   const VkPipelineColorBlendStateCreateInfo blend_state = {
207bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
208bf215546Sopenharmony_ci      .logicOpEnable = false,
209bf215546Sopenharmony_ci      .attachmentCount = 1,
210bf215546Sopenharmony_ci      .pAttachments = (VkPipelineColorBlendAttachmentState[]){
211bf215546Sopenharmony_ci         {
212bf215546Sopenharmony_ci            .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
213bf215546Sopenharmony_ci                              VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
214bf215546Sopenharmony_ci         },
215bf215546Sopenharmony_ci      }};
216bf215546Sopenharmony_ci   const VkPipelineRasterizationStateCreateInfo rs_state = {
217bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
218bf215546Sopenharmony_ci      .depthClampEnable = false,
219bf215546Sopenharmony_ci      .rasterizerDiscardEnable = false,
220bf215546Sopenharmony_ci      .polygonMode = VK_POLYGON_MODE_FILL,
221bf215546Sopenharmony_ci      .cullMode = VK_CULL_MODE_NONE,
222bf215546Sopenharmony_ci      .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
223bf215546Sopenharmony_ci   };
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci   const VkFormat color_format = VK_FORMAT_R8_UNORM;
226bf215546Sopenharmony_ci   const VkPipelineRenderingCreateInfo rendering_create_info = {
227bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
228bf215546Sopenharmony_ci      .colorAttachmentCount = 1,
229bf215546Sopenharmony_ci      .pColorAttachmentFormats = &color_format,
230bf215546Sopenharmony_ci   };
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   result = radv_graphics_pipeline_create(
233bf215546Sopenharmony_ci      device_h, radv_pipeline_cache_to_handle(&device->meta_state.cache),
234bf215546Sopenharmony_ci      &(VkGraphicsPipelineCreateInfo){
235bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
236bf215546Sopenharmony_ci         .pNext = &rendering_create_info,
237bf215546Sopenharmony_ci         .stageCount = 2,
238bf215546Sopenharmony_ci         .pStages = stages,
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci         .pVertexInputState = &vi_state,
241bf215546Sopenharmony_ci         .pInputAssemblyState = &ia_state,
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci         .pViewportState =
244bf215546Sopenharmony_ci            &(VkPipelineViewportStateCreateInfo){
245bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
246bf215546Sopenharmony_ci               .viewportCount = 1,
247bf215546Sopenharmony_ci               .scissorCount = 1,
248bf215546Sopenharmony_ci            },
249bf215546Sopenharmony_ci         .pRasterizationState = &rs_state,
250bf215546Sopenharmony_ci         .pMultisampleState =
251bf215546Sopenharmony_ci            &(VkPipelineMultisampleStateCreateInfo){
252bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
253bf215546Sopenharmony_ci               .rasterizationSamples = 1,
254bf215546Sopenharmony_ci               .sampleShadingEnable = false,
255bf215546Sopenharmony_ci               .pSampleMask = NULL,
256bf215546Sopenharmony_ci               .alphaToCoverageEnable = false,
257bf215546Sopenharmony_ci               .alphaToOneEnable = false,
258bf215546Sopenharmony_ci            },
259bf215546Sopenharmony_ci         .pColorBlendState = &blend_state,
260bf215546Sopenharmony_ci         .pDynamicState =
261bf215546Sopenharmony_ci            &(VkPipelineDynamicStateCreateInfo){
262bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
263bf215546Sopenharmony_ci               .dynamicStateCount = 2,
264bf215546Sopenharmony_ci               .pDynamicStates =
265bf215546Sopenharmony_ci                  (VkDynamicState[]){
266bf215546Sopenharmony_ci                     VK_DYNAMIC_STATE_VIEWPORT,
267bf215546Sopenharmony_ci                     VK_DYNAMIC_STATE_SCISSOR,
268bf215546Sopenharmony_ci                  },
269bf215546Sopenharmony_ci            },
270bf215546Sopenharmony_ci         .layout = layout,
271bf215546Sopenharmony_ci         .renderPass = VK_NULL_HANDLE,
272bf215546Sopenharmony_ci         .subpass = 0,
273bf215546Sopenharmony_ci      },
274bf215546Sopenharmony_ci      &(struct radv_graphics_pipeline_create_info){
275bf215546Sopenharmony_ci         .use_rectlist = true,
276bf215546Sopenharmony_ci         .custom_blend_mode = V_028808_CB_ELIMINATE_FAST_CLEAR,
277bf215546Sopenharmony_ci      },
278bf215546Sopenharmony_ci      &device->meta_state.alloc, &device->meta_state.fast_clear_flush.cmask_eliminate_pipeline);
279bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
280bf215546Sopenharmony_ci      goto cleanup;
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci   result = radv_graphics_pipeline_create(
283bf215546Sopenharmony_ci      device_h, radv_pipeline_cache_to_handle(&device->meta_state.cache),
284bf215546Sopenharmony_ci      &(VkGraphicsPipelineCreateInfo){
285bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
286bf215546Sopenharmony_ci         .pNext = &rendering_create_info,
287bf215546Sopenharmony_ci         .stageCount = 2,
288bf215546Sopenharmony_ci         .pStages = stages,
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_ci         .pVertexInputState = &vi_state,
291bf215546Sopenharmony_ci         .pInputAssemblyState = &ia_state,
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci         .pViewportState =
294bf215546Sopenharmony_ci            &(VkPipelineViewportStateCreateInfo){
295bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
296bf215546Sopenharmony_ci               .viewportCount = 1,
297bf215546Sopenharmony_ci               .scissorCount = 1,
298bf215546Sopenharmony_ci            },
299bf215546Sopenharmony_ci         .pRasterizationState = &rs_state,
300bf215546Sopenharmony_ci         .pMultisampleState =
301bf215546Sopenharmony_ci            &(VkPipelineMultisampleStateCreateInfo){
302bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
303bf215546Sopenharmony_ci               .rasterizationSamples = 1,
304bf215546Sopenharmony_ci               .sampleShadingEnable = false,
305bf215546Sopenharmony_ci               .pSampleMask = NULL,
306bf215546Sopenharmony_ci               .alphaToCoverageEnable = false,
307bf215546Sopenharmony_ci               .alphaToOneEnable = false,
308bf215546Sopenharmony_ci            },
309bf215546Sopenharmony_ci         .pColorBlendState = &blend_state,
310bf215546Sopenharmony_ci         .pDynamicState =
311bf215546Sopenharmony_ci            &(VkPipelineDynamicStateCreateInfo){
312bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
313bf215546Sopenharmony_ci               .dynamicStateCount = 2,
314bf215546Sopenharmony_ci               .pDynamicStates =
315bf215546Sopenharmony_ci                  (VkDynamicState[]){
316bf215546Sopenharmony_ci                     VK_DYNAMIC_STATE_VIEWPORT,
317bf215546Sopenharmony_ci                     VK_DYNAMIC_STATE_SCISSOR,
318bf215546Sopenharmony_ci                  },
319bf215546Sopenharmony_ci            },
320bf215546Sopenharmony_ci         .layout = layout,
321bf215546Sopenharmony_ci         .renderPass = VK_NULL_HANDLE,
322bf215546Sopenharmony_ci         .subpass = 0,
323bf215546Sopenharmony_ci      },
324bf215546Sopenharmony_ci      &(struct radv_graphics_pipeline_create_info){
325bf215546Sopenharmony_ci         .use_rectlist = true,
326bf215546Sopenharmony_ci         .custom_blend_mode = V_028808_CB_FMASK_DECOMPRESS,
327bf215546Sopenharmony_ci      },
328bf215546Sopenharmony_ci      &device->meta_state.alloc, &device->meta_state.fast_clear_flush.fmask_decompress_pipeline);
329bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
330bf215546Sopenharmony_ci      goto cleanup;
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_ci   result = radv_graphics_pipeline_create(
333bf215546Sopenharmony_ci      device_h, radv_pipeline_cache_to_handle(&device->meta_state.cache),
334bf215546Sopenharmony_ci      &(VkGraphicsPipelineCreateInfo){
335bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
336bf215546Sopenharmony_ci         .pNext = &rendering_create_info,
337bf215546Sopenharmony_ci         .stageCount = 2,
338bf215546Sopenharmony_ci         .pStages = stages,
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ci         .pVertexInputState = &vi_state,
341bf215546Sopenharmony_ci         .pInputAssemblyState = &ia_state,
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci         .pViewportState =
344bf215546Sopenharmony_ci            &(VkPipelineViewportStateCreateInfo){
345bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
346bf215546Sopenharmony_ci               .viewportCount = 1,
347bf215546Sopenharmony_ci               .scissorCount = 1,
348bf215546Sopenharmony_ci            },
349bf215546Sopenharmony_ci         .pRasterizationState = &rs_state,
350bf215546Sopenharmony_ci         .pMultisampleState =
351bf215546Sopenharmony_ci            &(VkPipelineMultisampleStateCreateInfo){
352bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
353bf215546Sopenharmony_ci               .rasterizationSamples = 1,
354bf215546Sopenharmony_ci               .sampleShadingEnable = false,
355bf215546Sopenharmony_ci               .pSampleMask = NULL,
356bf215546Sopenharmony_ci               .alphaToCoverageEnable = false,
357bf215546Sopenharmony_ci               .alphaToOneEnable = false,
358bf215546Sopenharmony_ci            },
359bf215546Sopenharmony_ci         .pColorBlendState = &blend_state,
360bf215546Sopenharmony_ci         .pDynamicState =
361bf215546Sopenharmony_ci            &(VkPipelineDynamicStateCreateInfo){
362bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
363bf215546Sopenharmony_ci               .dynamicStateCount = 2,
364bf215546Sopenharmony_ci               .pDynamicStates =
365bf215546Sopenharmony_ci                  (VkDynamicState[]){
366bf215546Sopenharmony_ci                     VK_DYNAMIC_STATE_VIEWPORT,
367bf215546Sopenharmony_ci                     VK_DYNAMIC_STATE_SCISSOR,
368bf215546Sopenharmony_ci                  },
369bf215546Sopenharmony_ci            },
370bf215546Sopenharmony_ci         .layout = layout,
371bf215546Sopenharmony_ci         .renderPass = VK_NULL_HANDLE,
372bf215546Sopenharmony_ci         .subpass = 0,
373bf215546Sopenharmony_ci      },
374bf215546Sopenharmony_ci      &(struct radv_graphics_pipeline_create_info){
375bf215546Sopenharmony_ci         .use_rectlist = true,
376bf215546Sopenharmony_ci         .custom_blend_mode = device->physical_device->rad_info.gfx_level >= GFX11
377bf215546Sopenharmony_ci                                 ? V_028808_CB_DCC_DECOMPRESS_GFX11
378bf215546Sopenharmony_ci                                 : V_028808_CB_DCC_DECOMPRESS_GFX8,
379bf215546Sopenharmony_ci      },
380bf215546Sopenharmony_ci      &device->meta_state.alloc, &device->meta_state.fast_clear_flush.dcc_decompress_pipeline);
381bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
382bf215546Sopenharmony_ci      goto cleanup;
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_cicleanup:
385bf215546Sopenharmony_ci   ralloc_free(fs_module);
386bf215546Sopenharmony_ci   return result;
387bf215546Sopenharmony_ci}
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_civoid
390bf215546Sopenharmony_ciradv_device_finish_meta_fast_clear_flush_state(struct radv_device *device)
391bf215546Sopenharmony_ci{
392bf215546Sopenharmony_ci   struct radv_meta_state *state = &device->meta_state;
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci   radv_DestroyPipeline(radv_device_to_handle(device),
395bf215546Sopenharmony_ci                        state->fast_clear_flush.dcc_decompress_pipeline, &state->alloc);
396bf215546Sopenharmony_ci   radv_DestroyPipeline(radv_device_to_handle(device),
397bf215546Sopenharmony_ci                        state->fast_clear_flush.fmask_decompress_pipeline, &state->alloc);
398bf215546Sopenharmony_ci   radv_DestroyPipeline(radv_device_to_handle(device),
399bf215546Sopenharmony_ci                        state->fast_clear_flush.cmask_eliminate_pipeline, &state->alloc);
400bf215546Sopenharmony_ci   radv_DestroyPipelineLayout(radv_device_to_handle(device), state->fast_clear_flush.p_layout,
401bf215546Sopenharmony_ci                              &state->alloc);
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci   radv_DestroyPipeline(radv_device_to_handle(device),
404bf215546Sopenharmony_ci                        state->fast_clear_flush.dcc_decompress_compute_pipeline, &state->alloc);
405bf215546Sopenharmony_ci   radv_DestroyPipelineLayout(radv_device_to_handle(device),
406bf215546Sopenharmony_ci                              state->fast_clear_flush.dcc_decompress_compute_p_layout,
407bf215546Sopenharmony_ci                              &state->alloc);
408bf215546Sopenharmony_ci   device->vk.dispatch_table.DestroyDescriptorSetLayout(
409bf215546Sopenharmony_ci      radv_device_to_handle(device), state->fast_clear_flush.dcc_decompress_compute_ds_layout,
410bf215546Sopenharmony_ci      &state->alloc);
411bf215546Sopenharmony_ci}
412bf215546Sopenharmony_ci
413bf215546Sopenharmony_cistatic VkResult
414bf215546Sopenharmony_ciradv_device_init_meta_fast_clear_flush_state_internal(struct radv_device *device)
415bf215546Sopenharmony_ci{
416bf215546Sopenharmony_ci   VkResult res = VK_SUCCESS;
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci   mtx_lock(&device->meta_state.mtx);
419bf215546Sopenharmony_ci   if (device->meta_state.fast_clear_flush.cmask_eliminate_pipeline) {
420bf215546Sopenharmony_ci      mtx_unlock(&device->meta_state.mtx);
421bf215546Sopenharmony_ci      return VK_SUCCESS;
422bf215546Sopenharmony_ci   }
423bf215546Sopenharmony_ci
424bf215546Sopenharmony_ci   nir_shader *vs_module = radv_meta_build_nir_vs_generate_vertices(device);
425bf215546Sopenharmony_ci   if (!vs_module) {
426bf215546Sopenharmony_ci      /* XXX: Need more accurate error */
427bf215546Sopenharmony_ci      res = VK_ERROR_OUT_OF_HOST_MEMORY;
428bf215546Sopenharmony_ci      goto cleanup;
429bf215546Sopenharmony_ci   }
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_ci   res = create_pipeline_layout(device, &device->meta_state.fast_clear_flush.p_layout);
432bf215546Sopenharmony_ci   if (res != VK_SUCCESS)
433bf215546Sopenharmony_ci      goto cleanup;
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_ci   VkShaderModule vs_module_h = vk_shader_module_handle_from_nir(vs_module);
436bf215546Sopenharmony_ci   res = create_pipeline(device, vs_module_h, device->meta_state.fast_clear_flush.p_layout);
437bf215546Sopenharmony_ci   if (res != VK_SUCCESS)
438bf215546Sopenharmony_ci      goto cleanup;
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   res = create_dcc_compress_compute(device);
441bf215546Sopenharmony_ci   if (res != VK_SUCCESS)
442bf215546Sopenharmony_ci      goto cleanup;
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_cicleanup:
445bf215546Sopenharmony_ci   ralloc_free(vs_module);
446bf215546Sopenharmony_ci   mtx_unlock(&device->meta_state.mtx);
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci   return res;
449bf215546Sopenharmony_ci}
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ciVkResult
452bf215546Sopenharmony_ciradv_device_init_meta_fast_clear_flush_state(struct radv_device *device, bool on_demand)
453bf215546Sopenharmony_ci{
454bf215546Sopenharmony_ci   if (on_demand)
455bf215546Sopenharmony_ci      return VK_SUCCESS;
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci   return radv_device_init_meta_fast_clear_flush_state_internal(device);
458bf215546Sopenharmony_ci}
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_cistatic void
461bf215546Sopenharmony_ciradv_emit_set_predication_state_from_image(struct radv_cmd_buffer *cmd_buffer,
462bf215546Sopenharmony_ci                                           struct radv_image *image, uint64_t pred_offset,
463bf215546Sopenharmony_ci                                           bool value)
464bf215546Sopenharmony_ci{
465bf215546Sopenharmony_ci   uint64_t va = 0;
466bf215546Sopenharmony_ci
467bf215546Sopenharmony_ci   if (value) {
468bf215546Sopenharmony_ci      va = radv_buffer_get_va(image->bindings[0].bo) + image->bindings[0].offset;
469bf215546Sopenharmony_ci      va += pred_offset;
470bf215546Sopenharmony_ci   }
471bf215546Sopenharmony_ci
472bf215546Sopenharmony_ci   si_emit_set_predication_state(cmd_buffer, true, PREDICATION_OP_BOOL64, va);
473bf215546Sopenharmony_ci}
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_cistatic void
476bf215546Sopenharmony_ciradv_process_color_image_layer(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
477bf215546Sopenharmony_ci                               const VkImageSubresourceRange *range, int level, int layer,
478bf215546Sopenharmony_ci                               bool flush_cb)
479bf215546Sopenharmony_ci{
480bf215546Sopenharmony_ci   struct radv_device *device = cmd_buffer->device;
481bf215546Sopenharmony_ci   struct radv_image_view iview;
482bf215546Sopenharmony_ci   uint32_t width, height;
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci   width = radv_minify(image->info.width, range->baseMipLevel + level);
485bf215546Sopenharmony_ci   height = radv_minify(image->info.height, range->baseMipLevel + level);
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci   radv_image_view_init(&iview, device,
488bf215546Sopenharmony_ci                        &(VkImageViewCreateInfo){
489bf215546Sopenharmony_ci                           .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
490bf215546Sopenharmony_ci                           .image = radv_image_to_handle(image),
491bf215546Sopenharmony_ci                           .viewType = radv_meta_get_view_type(image),
492bf215546Sopenharmony_ci                           .format = image->vk.format,
493bf215546Sopenharmony_ci                           .subresourceRange =
494bf215546Sopenharmony_ci                              {
495bf215546Sopenharmony_ci                                 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
496bf215546Sopenharmony_ci                                 .baseMipLevel = range->baseMipLevel + level,
497bf215546Sopenharmony_ci                                 .levelCount = 1,
498bf215546Sopenharmony_ci                                 .baseArrayLayer = range->baseArrayLayer + layer,
499bf215546Sopenharmony_ci                                 .layerCount = 1,
500bf215546Sopenharmony_ci                              },
501bf215546Sopenharmony_ci                        },
502bf215546Sopenharmony_ci                        0, NULL);
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci   const VkRenderingAttachmentInfo color_att = {
505bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
506bf215546Sopenharmony_ci      .imageView = radv_image_view_to_handle(&iview),
507bf215546Sopenharmony_ci      .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
508bf215546Sopenharmony_ci      .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
509bf215546Sopenharmony_ci      .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
510bf215546Sopenharmony_ci   };
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_ci   const VkRenderingInfo rendering_info = {
513bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
514bf215546Sopenharmony_ci      .renderArea = {
515bf215546Sopenharmony_ci         .offset = { 0, 0 },
516bf215546Sopenharmony_ci         .extent = { width, height }
517bf215546Sopenharmony_ci      },
518bf215546Sopenharmony_ci      .layerCount = 1,
519bf215546Sopenharmony_ci      .colorAttachmentCount = 1,
520bf215546Sopenharmony_ci      .pColorAttachments = &color_att,
521bf215546Sopenharmony_ci   };
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci   radv_CmdBeginRendering(radv_cmd_buffer_to_handle(cmd_buffer), &rendering_info);
524bf215546Sopenharmony_ci
525bf215546Sopenharmony_ci   if (flush_cb)
526bf215546Sopenharmony_ci      cmd_buffer->state.flush_bits |=
527bf215546Sopenharmony_ci         radv_dst_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, image);
528bf215546Sopenharmony_ci
529bf215546Sopenharmony_ci   radv_CmdDraw(radv_cmd_buffer_to_handle(cmd_buffer), 3, 1, 0, 0);
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci   if (flush_cb)
532bf215546Sopenharmony_ci      cmd_buffer->state.flush_bits |=
533bf215546Sopenharmony_ci         radv_src_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, image);
534bf215546Sopenharmony_ci
535bf215546Sopenharmony_ci   radv_CmdEndRendering(radv_cmd_buffer_to_handle(cmd_buffer));
536bf215546Sopenharmony_ci
537bf215546Sopenharmony_ci   radv_image_view_finish(&iview);
538bf215546Sopenharmony_ci}
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_cistatic void
541bf215546Sopenharmony_ciradv_process_color_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
542bf215546Sopenharmony_ci                         const VkImageSubresourceRange *subresourceRange, enum radv_color_op op)
543bf215546Sopenharmony_ci{
544bf215546Sopenharmony_ci   struct radv_device *device = cmd_buffer->device;
545bf215546Sopenharmony_ci   struct radv_meta_saved_state saved_state;
546bf215546Sopenharmony_ci   bool old_predicating = false;
547bf215546Sopenharmony_ci   bool flush_cb = false;
548bf215546Sopenharmony_ci   uint64_t pred_offset;
549bf215546Sopenharmony_ci   VkPipeline *pipeline;
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci   switch (op) {
552bf215546Sopenharmony_ci   case FAST_CLEAR_ELIMINATE:
553bf215546Sopenharmony_ci      pipeline = &device->meta_state.fast_clear_flush.cmask_eliminate_pipeline;
554bf215546Sopenharmony_ci      pred_offset = image->fce_pred_offset;
555bf215546Sopenharmony_ci      break;
556bf215546Sopenharmony_ci   case FMASK_DECOMPRESS:
557bf215546Sopenharmony_ci      pipeline = &device->meta_state.fast_clear_flush.fmask_decompress_pipeline;
558bf215546Sopenharmony_ci      pred_offset = 0; /* FMASK_DECOMPRESS is never predicated. */
559bf215546Sopenharmony_ci
560bf215546Sopenharmony_ci      /* Flushing CB is required before and after FMASK_DECOMPRESS. */
561bf215546Sopenharmony_ci      flush_cb = true;
562bf215546Sopenharmony_ci      break;
563bf215546Sopenharmony_ci   case DCC_DECOMPRESS:
564bf215546Sopenharmony_ci      pipeline = &device->meta_state.fast_clear_flush.dcc_decompress_pipeline;
565bf215546Sopenharmony_ci      pred_offset = image->dcc_pred_offset;
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_ci      /* Flushing CB is required before and after DCC_DECOMPRESS. */
568bf215546Sopenharmony_ci      flush_cb = true;
569bf215546Sopenharmony_ci      break;
570bf215546Sopenharmony_ci   default:
571bf215546Sopenharmony_ci      unreachable("Invalid color op");
572bf215546Sopenharmony_ci   }
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci   if (radv_dcc_enabled(image, subresourceRange->baseMipLevel) &&
575bf215546Sopenharmony_ci       (image->info.array_size != radv_get_layerCount(image, subresourceRange) ||
576bf215546Sopenharmony_ci        subresourceRange->baseArrayLayer != 0)) {
577bf215546Sopenharmony_ci      /* Only use predication if the image has DCC with mipmaps or
578bf215546Sopenharmony_ci       * if the range of layers covers the whole image because the
579bf215546Sopenharmony_ci       * predication is based on mip level.
580bf215546Sopenharmony_ci       */
581bf215546Sopenharmony_ci      pred_offset = 0;
582bf215546Sopenharmony_ci   }
583bf215546Sopenharmony_ci
584bf215546Sopenharmony_ci   if (!*pipeline) {
585bf215546Sopenharmony_ci      VkResult ret;
586bf215546Sopenharmony_ci
587bf215546Sopenharmony_ci      ret = radv_device_init_meta_fast_clear_flush_state_internal(device);
588bf215546Sopenharmony_ci      if (ret != VK_SUCCESS) {
589bf215546Sopenharmony_ci         cmd_buffer->record_result = ret;
590bf215546Sopenharmony_ci         return;
591bf215546Sopenharmony_ci      }
592bf215546Sopenharmony_ci   }
593bf215546Sopenharmony_ci
594bf215546Sopenharmony_ci   radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_PASS);
595bf215546Sopenharmony_ci
596bf215546Sopenharmony_ci   if (pred_offset) {
597bf215546Sopenharmony_ci      pred_offset += 8 * subresourceRange->baseMipLevel;
598bf215546Sopenharmony_ci
599bf215546Sopenharmony_ci      old_predicating = cmd_buffer->state.predicating;
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci      radv_emit_set_predication_state_from_image(cmd_buffer, image, pred_offset, true);
602bf215546Sopenharmony_ci      cmd_buffer->state.predicating = true;
603bf215546Sopenharmony_ci   }
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci   radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_GRAPHICS,
606bf215546Sopenharmony_ci                        *pipeline);
607bf215546Sopenharmony_ci
608bf215546Sopenharmony_ci   for (uint32_t l = 0; l < radv_get_levelCount(image, subresourceRange); ++l) {
609bf215546Sopenharmony_ci      uint32_t width, height;
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_ci      /* Do not decompress levels without DCC. */
612bf215546Sopenharmony_ci      if (op == DCC_DECOMPRESS && !radv_dcc_enabled(image, subresourceRange->baseMipLevel + l))
613bf215546Sopenharmony_ci         continue;
614bf215546Sopenharmony_ci
615bf215546Sopenharmony_ci      width = radv_minify(image->info.width, subresourceRange->baseMipLevel + l);
616bf215546Sopenharmony_ci      height = radv_minify(image->info.height, subresourceRange->baseMipLevel + l);
617bf215546Sopenharmony_ci
618bf215546Sopenharmony_ci      radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
619bf215546Sopenharmony_ci                          &(VkViewport){.x = 0,
620bf215546Sopenharmony_ci                                        .y = 0,
621bf215546Sopenharmony_ci                                        .width = width,
622bf215546Sopenharmony_ci                                        .height = height,
623bf215546Sopenharmony_ci                                        .minDepth = 0.0f,
624bf215546Sopenharmony_ci                                        .maxDepth = 1.0f});
625bf215546Sopenharmony_ci
626bf215546Sopenharmony_ci      radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
627bf215546Sopenharmony_ci                         &(VkRect2D){
628bf215546Sopenharmony_ci                            .offset = {0, 0},
629bf215546Sopenharmony_ci                            .extent = {width, height},
630bf215546Sopenharmony_ci                         });
631bf215546Sopenharmony_ci
632bf215546Sopenharmony_ci      for (uint32_t s = 0; s < radv_get_layerCount(image, subresourceRange); s++) {
633bf215546Sopenharmony_ci         radv_process_color_image_layer(cmd_buffer, image, subresourceRange, l, s, flush_cb);
634bf215546Sopenharmony_ci      }
635bf215546Sopenharmony_ci   }
636bf215546Sopenharmony_ci
637bf215546Sopenharmony_ci   cmd_buffer->state.flush_bits |=
638bf215546Sopenharmony_ci      RADV_CMD_FLAG_FLUSH_AND_INV_CB | RADV_CMD_FLAG_FLUSH_AND_INV_CB_META;
639bf215546Sopenharmony_ci
640bf215546Sopenharmony_ci   if (pred_offset) {
641bf215546Sopenharmony_ci      pred_offset += 8 * subresourceRange->baseMipLevel;
642bf215546Sopenharmony_ci
643bf215546Sopenharmony_ci      cmd_buffer->state.predicating = old_predicating;
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci      radv_emit_set_predication_state_from_image(cmd_buffer, image, pred_offset, false);
646bf215546Sopenharmony_ci
647bf215546Sopenharmony_ci      if (cmd_buffer->state.predication_type != -1) {
648bf215546Sopenharmony_ci         /* Restore previous conditional rendering user state. */
649bf215546Sopenharmony_ci         si_emit_set_predication_state(cmd_buffer, cmd_buffer->state.predication_type,
650bf215546Sopenharmony_ci                                       cmd_buffer->state.predication_op,
651bf215546Sopenharmony_ci                                       cmd_buffer->state.predication_va);
652bf215546Sopenharmony_ci      }
653bf215546Sopenharmony_ci   }
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_ci   radv_meta_restore(&saved_state, cmd_buffer);
656bf215546Sopenharmony_ci
657bf215546Sopenharmony_ci   /* Clear the image's fast-clear eliminate predicate because FMASK_DECOMPRESS and DCC_DECOMPRESS
658bf215546Sopenharmony_ci    * also perform a fast-clear eliminate.
659bf215546Sopenharmony_ci    */
660bf215546Sopenharmony_ci   radv_update_fce_metadata(cmd_buffer, image, subresourceRange, false);
661bf215546Sopenharmony_ci
662bf215546Sopenharmony_ci   /* Mark the image as being decompressed. */
663bf215546Sopenharmony_ci   if (op == DCC_DECOMPRESS)
664bf215546Sopenharmony_ci      radv_update_dcc_metadata(cmd_buffer, image, subresourceRange, false);
665bf215546Sopenharmony_ci}
666bf215546Sopenharmony_ci
667bf215546Sopenharmony_cistatic void
668bf215546Sopenharmony_ciradv_fast_clear_eliminate(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
669bf215546Sopenharmony_ci                          const VkImageSubresourceRange *subresourceRange)
670bf215546Sopenharmony_ci{
671bf215546Sopenharmony_ci   struct radv_barrier_data barrier = {0};
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci   barrier.layout_transitions.fast_clear_eliminate = 1;
674bf215546Sopenharmony_ci   radv_describe_layout_transition(cmd_buffer, &barrier);
675bf215546Sopenharmony_ci
676bf215546Sopenharmony_ci   radv_process_color_image(cmd_buffer, image, subresourceRange, FAST_CLEAR_ELIMINATE);
677bf215546Sopenharmony_ci}
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_cistatic void
680bf215546Sopenharmony_ciradv_fmask_decompress(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
681bf215546Sopenharmony_ci                      const VkImageSubresourceRange *subresourceRange)
682bf215546Sopenharmony_ci{
683bf215546Sopenharmony_ci   struct radv_barrier_data barrier = {0};
684bf215546Sopenharmony_ci
685bf215546Sopenharmony_ci   barrier.layout_transitions.fmask_decompress = 1;
686bf215546Sopenharmony_ci   radv_describe_layout_transition(cmd_buffer, &barrier);
687bf215546Sopenharmony_ci
688bf215546Sopenharmony_ci   radv_process_color_image(cmd_buffer, image, subresourceRange, FMASK_DECOMPRESS);
689bf215546Sopenharmony_ci}
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_civoid
692bf215546Sopenharmony_ciradv_fast_clear_flush_image_inplace(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
693bf215546Sopenharmony_ci                                    const VkImageSubresourceRange *subresourceRange)
694bf215546Sopenharmony_ci{
695bf215546Sopenharmony_ci   if (radv_image_has_fmask(image) && !image->tc_compatible_cmask) {
696bf215546Sopenharmony_ci      if (radv_image_has_dcc(image) && radv_image_has_cmask(image)) {
697bf215546Sopenharmony_ci         /* MSAA images with DCC and CMASK might have been fast-cleared and might require a FCE but
698bf215546Sopenharmony_ci          * FMASK_DECOMPRESS can't eliminate DCC fast clears.
699bf215546Sopenharmony_ci          */
700bf215546Sopenharmony_ci         radv_fast_clear_eliminate(cmd_buffer, image, subresourceRange);
701bf215546Sopenharmony_ci      }
702bf215546Sopenharmony_ci
703bf215546Sopenharmony_ci      radv_fmask_decompress(cmd_buffer, image, subresourceRange);
704bf215546Sopenharmony_ci   } else {
705bf215546Sopenharmony_ci      /* Skip fast clear eliminate for images that support comp-to-single fast clears. */
706bf215546Sopenharmony_ci      if (image->support_comp_to_single)
707bf215546Sopenharmony_ci         return;
708bf215546Sopenharmony_ci
709bf215546Sopenharmony_ci      radv_fast_clear_eliminate(cmd_buffer, image, subresourceRange);
710bf215546Sopenharmony_ci   }
711bf215546Sopenharmony_ci}
712bf215546Sopenharmony_ci
713bf215546Sopenharmony_cistatic void
714bf215546Sopenharmony_ciradv_decompress_dcc_compute(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
715bf215546Sopenharmony_ci                            const VkImageSubresourceRange *subresourceRange)
716bf215546Sopenharmony_ci{
717bf215546Sopenharmony_ci   struct radv_meta_saved_state saved_state;
718bf215546Sopenharmony_ci   struct radv_image_view load_iview = {0};
719bf215546Sopenharmony_ci   struct radv_image_view store_iview = {0};
720bf215546Sopenharmony_ci   struct radv_device *device = cmd_buffer->device;
721bf215546Sopenharmony_ci
722bf215546Sopenharmony_ci   cmd_buffer->state.flush_bits |=
723bf215546Sopenharmony_ci      radv_dst_access_flush(cmd_buffer, VK_ACCESS_2_SHADER_WRITE_BIT, image);
724bf215546Sopenharmony_ci
725bf215546Sopenharmony_ci   if (!cmd_buffer->device->meta_state.fast_clear_flush.cmask_eliminate_pipeline) {
726bf215546Sopenharmony_ci      VkResult ret = radv_device_init_meta_fast_clear_flush_state_internal(cmd_buffer->device);
727bf215546Sopenharmony_ci      if (ret != VK_SUCCESS) {
728bf215546Sopenharmony_ci         cmd_buffer->record_result = ret;
729bf215546Sopenharmony_ci         return;
730bf215546Sopenharmony_ci      }
731bf215546Sopenharmony_ci   }
732bf215546Sopenharmony_ci
733bf215546Sopenharmony_ci   radv_meta_save(&saved_state, cmd_buffer,
734bf215546Sopenharmony_ci                  RADV_META_SAVE_DESCRIPTORS | RADV_META_SAVE_COMPUTE_PIPELINE);
735bf215546Sopenharmony_ci
736bf215546Sopenharmony_ci   radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE,
737bf215546Sopenharmony_ci                        device->meta_state.fast_clear_flush.dcc_decompress_compute_pipeline);
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_ci   for (uint32_t l = 0; l < radv_get_levelCount(image, subresourceRange); l++) {
740bf215546Sopenharmony_ci      uint32_t width, height;
741bf215546Sopenharmony_ci
742bf215546Sopenharmony_ci      /* Do not decompress levels without DCC. */
743bf215546Sopenharmony_ci      if (!radv_dcc_enabled(image, subresourceRange->baseMipLevel + l))
744bf215546Sopenharmony_ci         continue;
745bf215546Sopenharmony_ci
746bf215546Sopenharmony_ci      width = radv_minify(image->info.width, subresourceRange->baseMipLevel + l);
747bf215546Sopenharmony_ci      height = radv_minify(image->info.height, subresourceRange->baseMipLevel + l);
748bf215546Sopenharmony_ci
749bf215546Sopenharmony_ci      for (uint32_t s = 0; s < radv_get_layerCount(image, subresourceRange); s++) {
750bf215546Sopenharmony_ci         radv_image_view_init(
751bf215546Sopenharmony_ci            &load_iview, cmd_buffer->device,
752bf215546Sopenharmony_ci            &(VkImageViewCreateInfo){
753bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
754bf215546Sopenharmony_ci               .image = radv_image_to_handle(image),
755bf215546Sopenharmony_ci               .viewType = VK_IMAGE_VIEW_TYPE_2D,
756bf215546Sopenharmony_ci               .format = image->vk.format,
757bf215546Sopenharmony_ci               .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
758bf215546Sopenharmony_ci                                    .baseMipLevel = subresourceRange->baseMipLevel + l,
759bf215546Sopenharmony_ci                                    .levelCount = 1,
760bf215546Sopenharmony_ci                                    .baseArrayLayer = subresourceRange->baseArrayLayer + s,
761bf215546Sopenharmony_ci                                    .layerCount = 1},
762bf215546Sopenharmony_ci            },
763bf215546Sopenharmony_ci            0, &(struct radv_image_view_extra_create_info){.enable_compression = true});
764bf215546Sopenharmony_ci         radv_image_view_init(
765bf215546Sopenharmony_ci            &store_iview, cmd_buffer->device,
766bf215546Sopenharmony_ci            &(VkImageViewCreateInfo){
767bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
768bf215546Sopenharmony_ci               .image = radv_image_to_handle(image),
769bf215546Sopenharmony_ci               .viewType = VK_IMAGE_VIEW_TYPE_2D,
770bf215546Sopenharmony_ci               .format = image->vk.format,
771bf215546Sopenharmony_ci               .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
772bf215546Sopenharmony_ci                                    .baseMipLevel = subresourceRange->baseMipLevel + l,
773bf215546Sopenharmony_ci                                    .levelCount = 1,
774bf215546Sopenharmony_ci                                    .baseArrayLayer = subresourceRange->baseArrayLayer + s,
775bf215546Sopenharmony_ci                                    .layerCount = 1},
776bf215546Sopenharmony_ci            },
777bf215546Sopenharmony_ci            0, &(struct radv_image_view_extra_create_info){.disable_compression = true});
778bf215546Sopenharmony_ci
779bf215546Sopenharmony_ci         radv_meta_push_descriptor_set(
780bf215546Sopenharmony_ci            cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE,
781bf215546Sopenharmony_ci            device->meta_state.fast_clear_flush.dcc_decompress_compute_p_layout, 0, /* set */
782bf215546Sopenharmony_ci            2, /* descriptorWriteCount */
783bf215546Sopenharmony_ci            (VkWriteDescriptorSet[]){{.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
784bf215546Sopenharmony_ci                                      .dstBinding = 0,
785bf215546Sopenharmony_ci                                      .dstArrayElement = 0,
786bf215546Sopenharmony_ci                                      .descriptorCount = 1,
787bf215546Sopenharmony_ci                                      .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
788bf215546Sopenharmony_ci                                      .pImageInfo =
789bf215546Sopenharmony_ci                                         (VkDescriptorImageInfo[]){
790bf215546Sopenharmony_ci                                            {
791bf215546Sopenharmony_ci                                               .sampler = VK_NULL_HANDLE,
792bf215546Sopenharmony_ci                                               .imageView = radv_image_view_to_handle(&load_iview),
793bf215546Sopenharmony_ci                                               .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
794bf215546Sopenharmony_ci                                            },
795bf215546Sopenharmony_ci                                         }},
796bf215546Sopenharmony_ci                                     {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
797bf215546Sopenharmony_ci                                      .dstBinding = 1,
798bf215546Sopenharmony_ci                                      .dstArrayElement = 0,
799bf215546Sopenharmony_ci                                      .descriptorCount = 1,
800bf215546Sopenharmony_ci                                      .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
801bf215546Sopenharmony_ci                                      .pImageInfo = (VkDescriptorImageInfo[]){
802bf215546Sopenharmony_ci                                         {
803bf215546Sopenharmony_ci                                            .sampler = VK_NULL_HANDLE,
804bf215546Sopenharmony_ci                                            .imageView = radv_image_view_to_handle(&store_iview),
805bf215546Sopenharmony_ci                                            .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
806bf215546Sopenharmony_ci                                         },
807bf215546Sopenharmony_ci                                      }}});
808bf215546Sopenharmony_ci
809bf215546Sopenharmony_ci         radv_unaligned_dispatch(cmd_buffer, width, height, 1);
810bf215546Sopenharmony_ci
811bf215546Sopenharmony_ci         radv_image_view_finish(&load_iview);
812bf215546Sopenharmony_ci         radv_image_view_finish(&store_iview);
813bf215546Sopenharmony_ci      }
814bf215546Sopenharmony_ci   }
815bf215546Sopenharmony_ci
816bf215546Sopenharmony_ci   /* Mark this image as actually being decompressed. */
817bf215546Sopenharmony_ci   radv_update_dcc_metadata(cmd_buffer, image, subresourceRange, false);
818bf215546Sopenharmony_ci
819bf215546Sopenharmony_ci   radv_meta_restore(&saved_state, cmd_buffer);
820bf215546Sopenharmony_ci
821bf215546Sopenharmony_ci   cmd_buffer->state.flush_bits |=
822bf215546Sopenharmony_ci      RADV_CMD_FLAG_CS_PARTIAL_FLUSH | RADV_CMD_FLAG_INV_VCACHE |
823bf215546Sopenharmony_ci      radv_src_access_flush(cmd_buffer, VK_ACCESS_2_SHADER_WRITE_BIT, image);
824bf215546Sopenharmony_ci
825bf215546Sopenharmony_ci   /* Initialize the DCC metadata as "fully expanded". */
826bf215546Sopenharmony_ci   cmd_buffer->state.flush_bits |= radv_init_dcc(cmd_buffer, image, subresourceRange, 0xffffffff);
827bf215546Sopenharmony_ci}
828bf215546Sopenharmony_ci
829bf215546Sopenharmony_civoid
830bf215546Sopenharmony_ciradv_decompress_dcc(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
831bf215546Sopenharmony_ci                    const VkImageSubresourceRange *subresourceRange)
832bf215546Sopenharmony_ci{
833bf215546Sopenharmony_ci   struct radv_barrier_data barrier = {0};
834bf215546Sopenharmony_ci
835bf215546Sopenharmony_ci   barrier.layout_transitions.dcc_decompress = 1;
836bf215546Sopenharmony_ci   radv_describe_layout_transition(cmd_buffer, &barrier);
837bf215546Sopenharmony_ci
838bf215546Sopenharmony_ci   if (cmd_buffer->qf == RADV_QUEUE_GENERAL)
839bf215546Sopenharmony_ci      radv_process_color_image(cmd_buffer, image, subresourceRange, DCC_DECOMPRESS);
840bf215546Sopenharmony_ci   else
841bf215546Sopenharmony_ci      radv_decompress_dcc_compute(cmd_buffer, image, subresourceRange);
842bf215546Sopenharmony_ci}
843