1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2015 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 "nir/nir_builder.h"
25bf215546Sopenharmony_ci#include "radv_debug.h"
26bf215546Sopenharmony_ci#include "radv_meta.h"
27bf215546Sopenharmony_ci#include "radv_private.h"
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "util/format_rgb9e5.h"
30bf215546Sopenharmony_ci#include "vk_format.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_cienum { DEPTH_CLEAR_SLOW, DEPTH_CLEAR_FAST };
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_cistatic void
35bf215546Sopenharmony_cibuild_color_shaders(struct radv_device *dev, struct nir_shader **out_vs, struct nir_shader **out_fs,
36bf215546Sopenharmony_ci                    uint32_t frag_output)
37bf215546Sopenharmony_ci{
38bf215546Sopenharmony_ci   nir_builder vs_b = radv_meta_init_shader(dev, MESA_SHADER_VERTEX, "meta_clear_color_vs");
39bf215546Sopenharmony_ci   nir_builder fs_b =
40bf215546Sopenharmony_ci      radv_meta_init_shader(dev, MESA_SHADER_FRAGMENT, "meta_clear_color_fs-%d", frag_output);
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci   const struct glsl_type *position_type = glsl_vec4_type();
43bf215546Sopenharmony_ci   const struct glsl_type *color_type = glsl_vec4_type();
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci   nir_variable *vs_out_pos =
46bf215546Sopenharmony_ci      nir_variable_create(vs_b.shader, nir_var_shader_out, position_type, "gl_Position");
47bf215546Sopenharmony_ci   vs_out_pos->data.location = VARYING_SLOT_POS;
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   nir_ssa_def *in_color_load =
50bf215546Sopenharmony_ci      nir_load_push_constant(&fs_b, 4, 32, nir_imm_int(&fs_b, 0), .range = 16);
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   nir_variable *fs_out_color =
53bf215546Sopenharmony_ci      nir_variable_create(fs_b.shader, nir_var_shader_out, color_type, "f_color");
54bf215546Sopenharmony_ci   fs_out_color->data.location = FRAG_RESULT_DATA0 + frag_output;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci   nir_store_var(&fs_b, fs_out_color, in_color_load, 0xf);
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci   nir_ssa_def *outvec = nir_gen_rect_vertices(&vs_b, NULL, NULL);
59bf215546Sopenharmony_ci   nir_store_var(&vs_b, vs_out_pos, outvec, 0xf);
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci   const struct glsl_type *layer_type = glsl_int_type();
62bf215546Sopenharmony_ci   nir_variable *vs_out_layer =
63bf215546Sopenharmony_ci      nir_variable_create(vs_b.shader, nir_var_shader_out, layer_type, "v_layer");
64bf215546Sopenharmony_ci   vs_out_layer->data.location = VARYING_SLOT_LAYER;
65bf215546Sopenharmony_ci   vs_out_layer->data.interpolation = INTERP_MODE_FLAT;
66bf215546Sopenharmony_ci   nir_ssa_def *inst_id = nir_load_instance_id(&vs_b);
67bf215546Sopenharmony_ci   nir_ssa_def *base_instance = nir_load_base_instance(&vs_b);
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci   nir_ssa_def *layer_id = nir_iadd(&vs_b, inst_id, base_instance);
70bf215546Sopenharmony_ci   nir_store_var(&vs_b, vs_out_layer, layer_id, 0x1);
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   *out_vs = vs_b.shader;
73bf215546Sopenharmony_ci   *out_fs = fs_b.shader;
74bf215546Sopenharmony_ci}
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_cistatic VkResult
77bf215546Sopenharmony_cicreate_pipeline(struct radv_device *device, uint32_t samples,
78bf215546Sopenharmony_ci                struct nir_shader *vs_nir, struct nir_shader *fs_nir,
79bf215546Sopenharmony_ci                const VkPipelineVertexInputStateCreateInfo *vi_state,
80bf215546Sopenharmony_ci                const VkPipelineDepthStencilStateCreateInfo *ds_state,
81bf215546Sopenharmony_ci                const VkPipelineColorBlendStateCreateInfo *cb_state,
82bf215546Sopenharmony_ci                const VkPipelineRenderingCreateInfo *dyn_state,
83bf215546Sopenharmony_ci                const VkPipelineLayout layout,
84bf215546Sopenharmony_ci                const struct radv_graphics_pipeline_create_info *extra,
85bf215546Sopenharmony_ci                const VkAllocationCallbacks *alloc, VkPipeline *pipeline)
86bf215546Sopenharmony_ci{
87bf215546Sopenharmony_ci   VkDevice device_h = radv_device_to_handle(device);
88bf215546Sopenharmony_ci   VkResult result;
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci   result = radv_graphics_pipeline_create(
91bf215546Sopenharmony_ci      device_h, radv_pipeline_cache_to_handle(&device->meta_state.cache),
92bf215546Sopenharmony_ci      &(VkGraphicsPipelineCreateInfo){
93bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
94bf215546Sopenharmony_ci         .pNext = dyn_state,
95bf215546Sopenharmony_ci         .stageCount = fs_nir ? 2 : 1,
96bf215546Sopenharmony_ci         .pStages =
97bf215546Sopenharmony_ci            (VkPipelineShaderStageCreateInfo[]){
98bf215546Sopenharmony_ci               {
99bf215546Sopenharmony_ci                  .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
100bf215546Sopenharmony_ci                  .stage = VK_SHADER_STAGE_VERTEX_BIT,
101bf215546Sopenharmony_ci                  .module = vk_shader_module_handle_from_nir(vs_nir),
102bf215546Sopenharmony_ci                  .pName = "main",
103bf215546Sopenharmony_ci               },
104bf215546Sopenharmony_ci               {
105bf215546Sopenharmony_ci                  .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
106bf215546Sopenharmony_ci                  .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
107bf215546Sopenharmony_ci                  .module = vk_shader_module_handle_from_nir(fs_nir),
108bf215546Sopenharmony_ci                  .pName = "main",
109bf215546Sopenharmony_ci               },
110bf215546Sopenharmony_ci            },
111bf215546Sopenharmony_ci         .pVertexInputState = vi_state,
112bf215546Sopenharmony_ci         .pInputAssemblyState =
113bf215546Sopenharmony_ci            &(VkPipelineInputAssemblyStateCreateInfo){
114bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
115bf215546Sopenharmony_ci               .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
116bf215546Sopenharmony_ci               .primitiveRestartEnable = false,
117bf215546Sopenharmony_ci            },
118bf215546Sopenharmony_ci         .pViewportState =
119bf215546Sopenharmony_ci            &(VkPipelineViewportStateCreateInfo){
120bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
121bf215546Sopenharmony_ci               .viewportCount = 1,
122bf215546Sopenharmony_ci               .scissorCount = 1,
123bf215546Sopenharmony_ci            },
124bf215546Sopenharmony_ci         .pRasterizationState =
125bf215546Sopenharmony_ci            &(VkPipelineRasterizationStateCreateInfo){
126bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
127bf215546Sopenharmony_ci               .rasterizerDiscardEnable = false,
128bf215546Sopenharmony_ci               .polygonMode = VK_POLYGON_MODE_FILL,
129bf215546Sopenharmony_ci               .cullMode = VK_CULL_MODE_NONE,
130bf215546Sopenharmony_ci               .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
131bf215546Sopenharmony_ci               .depthBiasEnable = false,
132bf215546Sopenharmony_ci               .depthBiasConstantFactor = 0.0f,
133bf215546Sopenharmony_ci               .depthBiasClamp = 0.0f,
134bf215546Sopenharmony_ci               .depthBiasSlopeFactor = 0.0f,
135bf215546Sopenharmony_ci               .lineWidth = 1.0f,
136bf215546Sopenharmony_ci            },
137bf215546Sopenharmony_ci         .pMultisampleState =
138bf215546Sopenharmony_ci            &(VkPipelineMultisampleStateCreateInfo){
139bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
140bf215546Sopenharmony_ci               .rasterizationSamples = samples,
141bf215546Sopenharmony_ci               .sampleShadingEnable = false,
142bf215546Sopenharmony_ci               .pSampleMask = NULL,
143bf215546Sopenharmony_ci               .alphaToCoverageEnable = false,
144bf215546Sopenharmony_ci               .alphaToOneEnable = false,
145bf215546Sopenharmony_ci            },
146bf215546Sopenharmony_ci         .pDepthStencilState = ds_state,
147bf215546Sopenharmony_ci         .pColorBlendState = cb_state,
148bf215546Sopenharmony_ci         .pDynamicState =
149bf215546Sopenharmony_ci            &(VkPipelineDynamicStateCreateInfo){
150bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
151bf215546Sopenharmony_ci               .dynamicStateCount = 3,
152bf215546Sopenharmony_ci               .pDynamicStates =
153bf215546Sopenharmony_ci                  (VkDynamicState[]){
154bf215546Sopenharmony_ci                     VK_DYNAMIC_STATE_VIEWPORT,
155bf215546Sopenharmony_ci                     VK_DYNAMIC_STATE_SCISSOR,
156bf215546Sopenharmony_ci                     VK_DYNAMIC_STATE_STENCIL_REFERENCE,
157bf215546Sopenharmony_ci                  },
158bf215546Sopenharmony_ci            },
159bf215546Sopenharmony_ci         .layout = layout,
160bf215546Sopenharmony_ci         .flags = 0,
161bf215546Sopenharmony_ci         .renderPass = VK_NULL_HANDLE,
162bf215546Sopenharmony_ci         .subpass = 0,
163bf215546Sopenharmony_ci      },
164bf215546Sopenharmony_ci      extra, alloc, pipeline);
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   ralloc_free(vs_nir);
167bf215546Sopenharmony_ci   ralloc_free(fs_nir);
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   return result;
170bf215546Sopenharmony_ci}
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_cistatic VkResult
173bf215546Sopenharmony_cicreate_color_pipeline(struct radv_device *device, uint32_t samples, uint32_t frag_output,
174bf215546Sopenharmony_ci                      VkFormat format, VkPipeline *pipeline)
175bf215546Sopenharmony_ci{
176bf215546Sopenharmony_ci   struct nir_shader *vs_nir;
177bf215546Sopenharmony_ci   struct nir_shader *fs_nir;
178bf215546Sopenharmony_ci   VkResult result;
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   mtx_lock(&device->meta_state.mtx);
181bf215546Sopenharmony_ci   if (*pipeline) {
182bf215546Sopenharmony_ci      mtx_unlock(&device->meta_state.mtx);
183bf215546Sopenharmony_ci      return VK_SUCCESS;
184bf215546Sopenharmony_ci   }
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci   build_color_shaders(device, &vs_nir, &fs_nir, frag_output);
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci   const VkPipelineVertexInputStateCreateInfo vi_state = {
189bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
190bf215546Sopenharmony_ci      .vertexBindingDescriptionCount = 0,
191bf215546Sopenharmony_ci      .vertexAttributeDescriptionCount = 0,
192bf215546Sopenharmony_ci   };
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   const VkPipelineDepthStencilStateCreateInfo ds_state = {
195bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
196bf215546Sopenharmony_ci      .depthTestEnable = false,
197bf215546Sopenharmony_ci      .depthWriteEnable = false,
198bf215546Sopenharmony_ci      .depthBoundsTestEnable = false,
199bf215546Sopenharmony_ci      .stencilTestEnable = false,
200bf215546Sopenharmony_ci      .minDepthBounds = 0.0f,
201bf215546Sopenharmony_ci      .maxDepthBounds = 1.0f,
202bf215546Sopenharmony_ci   };
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci   VkPipelineColorBlendAttachmentState blend_attachment_state[MAX_RTS] = {0};
205bf215546Sopenharmony_ci   blend_attachment_state[frag_output] = (VkPipelineColorBlendAttachmentState){
206bf215546Sopenharmony_ci      .blendEnable = false,
207bf215546Sopenharmony_ci      .colorWriteMask = VK_COLOR_COMPONENT_A_BIT | VK_COLOR_COMPONENT_R_BIT |
208bf215546Sopenharmony_ci                        VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT,
209bf215546Sopenharmony_ci   };
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   const VkPipelineColorBlendStateCreateInfo cb_state = {
212bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
213bf215546Sopenharmony_ci      .logicOpEnable = false,
214bf215546Sopenharmony_ci      .attachmentCount = MAX_RTS,
215bf215546Sopenharmony_ci      .pAttachments = blend_attachment_state,
216bf215546Sopenharmony_ci      .blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f }};
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   VkFormat att_formats[MAX_RTS] = { 0 };
219bf215546Sopenharmony_ci   att_formats[frag_output] = format;
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci   const VkPipelineRenderingCreateInfo rendering_create_info = {
222bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
223bf215546Sopenharmony_ci      .colorAttachmentCount = MAX_RTS,
224bf215546Sopenharmony_ci      .pColorAttachmentFormats = att_formats,
225bf215546Sopenharmony_ci   };
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci   struct radv_graphics_pipeline_create_info extra = {
228bf215546Sopenharmony_ci      .use_rectlist = true,
229bf215546Sopenharmony_ci   };
230bf215546Sopenharmony_ci   result =
231bf215546Sopenharmony_ci      create_pipeline(device, samples, vs_nir, fs_nir, &vi_state, &ds_state, &cb_state,
232bf215546Sopenharmony_ci                      &rendering_create_info, device->meta_state.clear_color_p_layout,
233bf215546Sopenharmony_ci                      &extra, &device->meta_state.alloc, pipeline);
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci   mtx_unlock(&device->meta_state.mtx);
236bf215546Sopenharmony_ci   return result;
237bf215546Sopenharmony_ci}
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_cistatic void
240bf215546Sopenharmony_cifinish_meta_clear_htile_mask_state(struct radv_device *device)
241bf215546Sopenharmony_ci{
242bf215546Sopenharmony_ci   struct radv_meta_state *state = &device->meta_state;
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci   radv_DestroyPipeline(radv_device_to_handle(device), state->clear_htile_mask_pipeline,
245bf215546Sopenharmony_ci                        &state->alloc);
246bf215546Sopenharmony_ci   radv_DestroyPipelineLayout(radv_device_to_handle(device), state->clear_htile_mask_p_layout,
247bf215546Sopenharmony_ci                              &state->alloc);
248bf215546Sopenharmony_ci   device->vk.dispatch_table.DestroyDescriptorSetLayout(
249bf215546Sopenharmony_ci      radv_device_to_handle(device), state->clear_htile_mask_ds_layout, &state->alloc);
250bf215546Sopenharmony_ci}
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_cistatic void
253bf215546Sopenharmony_cifinish_meta_clear_dcc_comp_to_single_state(struct radv_device *device)
254bf215546Sopenharmony_ci{
255bf215546Sopenharmony_ci   struct radv_meta_state *state = &device->meta_state;
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   for (uint32_t i = 0; i < 2; i++) {
258bf215546Sopenharmony_ci      radv_DestroyPipeline(radv_device_to_handle(device),
259bf215546Sopenharmony_ci                           state->clear_dcc_comp_to_single_pipeline[i], &state->alloc);
260bf215546Sopenharmony_ci   }
261bf215546Sopenharmony_ci   radv_DestroyPipelineLayout(radv_device_to_handle(device), state->clear_dcc_comp_to_single_p_layout,
262bf215546Sopenharmony_ci                              &state->alloc);
263bf215546Sopenharmony_ci   device->vk.dispatch_table.DestroyDescriptorSetLayout(
264bf215546Sopenharmony_ci      radv_device_to_handle(device), state->clear_dcc_comp_to_single_ds_layout, &state->alloc);
265bf215546Sopenharmony_ci}
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_civoid
268bf215546Sopenharmony_ciradv_device_finish_meta_clear_state(struct radv_device *device)
269bf215546Sopenharmony_ci{
270bf215546Sopenharmony_ci   struct radv_meta_state *state = &device->meta_state;
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci   for (uint32_t i = 0; i < ARRAY_SIZE(state->color_clear); ++i) {
273bf215546Sopenharmony_ci      for (uint32_t j = 0; j < ARRAY_SIZE(state->color_clear[0]); ++j) {
274bf215546Sopenharmony_ci         for (uint32_t k = 0; k < ARRAY_SIZE(state->color_clear[i][j].color_pipelines); ++k) {
275bf215546Sopenharmony_ci            radv_DestroyPipeline(radv_device_to_handle(device),
276bf215546Sopenharmony_ci                                 state->color_clear[i][j].color_pipelines[k], &state->alloc);
277bf215546Sopenharmony_ci         }
278bf215546Sopenharmony_ci      }
279bf215546Sopenharmony_ci   }
280bf215546Sopenharmony_ci   for (uint32_t i = 0; i < ARRAY_SIZE(state->ds_clear); ++i) {
281bf215546Sopenharmony_ci      for (uint32_t j = 0; j < NUM_DEPTH_CLEAR_PIPELINES; j++) {
282bf215546Sopenharmony_ci         radv_DestroyPipeline(radv_device_to_handle(device),
283bf215546Sopenharmony_ci                              state->ds_clear[i].depth_only_pipeline[j], &state->alloc);
284bf215546Sopenharmony_ci         radv_DestroyPipeline(radv_device_to_handle(device),
285bf215546Sopenharmony_ci                              state->ds_clear[i].stencil_only_pipeline[j], &state->alloc);
286bf215546Sopenharmony_ci         radv_DestroyPipeline(radv_device_to_handle(device),
287bf215546Sopenharmony_ci                              state->ds_clear[i].depthstencil_pipeline[j], &state->alloc);
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci         radv_DestroyPipeline(radv_device_to_handle(device),
290bf215546Sopenharmony_ci                              state->ds_clear[i].depth_only_unrestricted_pipeline[j],
291bf215546Sopenharmony_ci                              &state->alloc);
292bf215546Sopenharmony_ci         radv_DestroyPipeline(radv_device_to_handle(device),
293bf215546Sopenharmony_ci                              state->ds_clear[i].stencil_only_unrestricted_pipeline[j],
294bf215546Sopenharmony_ci                              &state->alloc);
295bf215546Sopenharmony_ci         radv_DestroyPipeline(radv_device_to_handle(device),
296bf215546Sopenharmony_ci                              state->ds_clear[i].depthstencil_unrestricted_pipeline[j],
297bf215546Sopenharmony_ci                              &state->alloc);
298bf215546Sopenharmony_ci      }
299bf215546Sopenharmony_ci   }
300bf215546Sopenharmony_ci   radv_DestroyPipelineLayout(radv_device_to_handle(device), state->clear_color_p_layout,
301bf215546Sopenharmony_ci                              &state->alloc);
302bf215546Sopenharmony_ci   radv_DestroyPipelineLayout(radv_device_to_handle(device), state->clear_depth_p_layout,
303bf215546Sopenharmony_ci                              &state->alloc);
304bf215546Sopenharmony_ci   radv_DestroyPipelineLayout(radv_device_to_handle(device),
305bf215546Sopenharmony_ci                              state->clear_depth_unrestricted_p_layout, &state->alloc);
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci   finish_meta_clear_htile_mask_state(device);
308bf215546Sopenharmony_ci   finish_meta_clear_dcc_comp_to_single_state(device);
309bf215546Sopenharmony_ci}
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_cistatic void
312bf215546Sopenharmony_ciemit_color_clear(struct radv_cmd_buffer *cmd_buffer, const VkClearAttachment *clear_att,
313bf215546Sopenharmony_ci                 const VkClearRect *clear_rect, uint32_t view_mask)
314bf215546Sopenharmony_ci{
315bf215546Sopenharmony_ci   struct radv_device *device = cmd_buffer->device;
316bf215546Sopenharmony_ci   const struct radv_subpass *subpass = cmd_buffer->state.subpass;
317bf215546Sopenharmony_ci   const uint32_t subpass_att = clear_att->colorAttachment;
318bf215546Sopenharmony_ci   const uint32_t pass_att = subpass->color_attachments[subpass_att].attachment;
319bf215546Sopenharmony_ci   const struct radv_image_view *iview =
320bf215546Sopenharmony_ci      cmd_buffer->state.attachments ? cmd_buffer->state.attachments[pass_att].iview : NULL;
321bf215546Sopenharmony_ci   uint32_t samples, samples_log2;
322bf215546Sopenharmony_ci   VkFormat format;
323bf215546Sopenharmony_ci   unsigned fs_key;
324bf215546Sopenharmony_ci   VkClearColorValue clear_value = clear_att->clearValue.color;
325bf215546Sopenharmony_ci   VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
326bf215546Sopenharmony_ci   VkPipeline pipeline;
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci   /* When a framebuffer is bound to the current command buffer, get the
329bf215546Sopenharmony_ci    * number of samples from it. Otherwise, get the number of samples from
330bf215546Sopenharmony_ci    * the render pass because it's likely a secondary command buffer.
331bf215546Sopenharmony_ci    */
332bf215546Sopenharmony_ci   if (iview) {
333bf215546Sopenharmony_ci      samples = iview->image->info.samples;
334bf215546Sopenharmony_ci      format = iview->vk.format;
335bf215546Sopenharmony_ci   } else {
336bf215546Sopenharmony_ci      samples = cmd_buffer->state.pass->attachments[pass_att].samples;
337bf215546Sopenharmony_ci      format = cmd_buffer->state.pass->attachments[pass_att].format;
338bf215546Sopenharmony_ci   }
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ci   samples_log2 = ffs(samples) - 1;
341bf215546Sopenharmony_ci   fs_key = radv_format_meta_fs_key(device, format);
342bf215546Sopenharmony_ci   assert(fs_key != -1);
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci   if (device->meta_state.color_clear[samples_log2][clear_att->colorAttachment]
345bf215546Sopenharmony_ci          .color_pipelines[fs_key] == VK_NULL_HANDLE) {
346bf215546Sopenharmony_ci      VkResult ret = create_color_pipeline(
347bf215546Sopenharmony_ci         device, samples, clear_att->colorAttachment, radv_fs_key_format_exemplars[fs_key],
348bf215546Sopenharmony_ci         &device->meta_state.color_clear[samples_log2][clear_att->colorAttachment]
349bf215546Sopenharmony_ci             .color_pipelines[fs_key]);
350bf215546Sopenharmony_ci      if (ret != VK_SUCCESS) {
351bf215546Sopenharmony_ci         cmd_buffer->record_result = ret;
352bf215546Sopenharmony_ci         return;
353bf215546Sopenharmony_ci      }
354bf215546Sopenharmony_ci   }
355bf215546Sopenharmony_ci
356bf215546Sopenharmony_ci   pipeline = device->meta_state.color_clear[samples_log2][clear_att->colorAttachment]
357bf215546Sopenharmony_ci                 .color_pipelines[fs_key];
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci   assert(samples_log2 < ARRAY_SIZE(device->meta_state.color_clear));
360bf215546Sopenharmony_ci   assert(pipeline);
361bf215546Sopenharmony_ci   assert(clear_att->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
362bf215546Sopenharmony_ci   assert(clear_att->colorAttachment < subpass->color_count);
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci   radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
365bf215546Sopenharmony_ci                         device->meta_state.clear_color_p_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 0,
366bf215546Sopenharmony_ci                         16, &clear_value);
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci   radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci   radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
371bf215546Sopenharmony_ci                       &(VkViewport){.x = clear_rect->rect.offset.x,
372bf215546Sopenharmony_ci                                     .y = clear_rect->rect.offset.y,
373bf215546Sopenharmony_ci                                     .width = clear_rect->rect.extent.width,
374bf215546Sopenharmony_ci                                     .height = clear_rect->rect.extent.height,
375bf215546Sopenharmony_ci                                     .minDepth = 0.0f,
376bf215546Sopenharmony_ci                                     .maxDepth = 1.0f});
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &clear_rect->rect);
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci   if (view_mask) {
381bf215546Sopenharmony_ci      u_foreach_bit(i, view_mask) radv_CmdDraw(cmd_buffer_h, 3, 1, 0, i);
382bf215546Sopenharmony_ci   } else {
383bf215546Sopenharmony_ci      radv_CmdDraw(cmd_buffer_h, 3, clear_rect->layerCount, 0, clear_rect->baseArrayLayer);
384bf215546Sopenharmony_ci   }
385bf215546Sopenharmony_ci}
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_cistatic void
388bf215546Sopenharmony_cibuild_depthstencil_shader(struct radv_device *dev, struct nir_shader **out_vs,
389bf215546Sopenharmony_ci                          struct nir_shader **out_fs, bool unrestricted)
390bf215546Sopenharmony_ci{
391bf215546Sopenharmony_ci   nir_builder vs_b = radv_meta_init_shader(
392bf215546Sopenharmony_ci      dev, MESA_SHADER_VERTEX,
393bf215546Sopenharmony_ci      unrestricted ? "meta_clear_depthstencil_unrestricted_vs" : "meta_clear_depthstencil_vs");
394bf215546Sopenharmony_ci   nir_builder fs_b = radv_meta_init_shader(
395bf215546Sopenharmony_ci      dev, MESA_SHADER_FRAGMENT,
396bf215546Sopenharmony_ci      unrestricted ? "meta_clear_depthstencil_unrestricted_fs" : "meta_clear_depthstencil_fs");
397bf215546Sopenharmony_ci
398bf215546Sopenharmony_ci   const struct glsl_type *position_out_type = glsl_vec4_type();
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci   nir_variable *vs_out_pos =
401bf215546Sopenharmony_ci      nir_variable_create(vs_b.shader, nir_var_shader_out, position_out_type, "gl_Position");
402bf215546Sopenharmony_ci   vs_out_pos->data.location = VARYING_SLOT_POS;
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_ci   nir_ssa_def *z;
405bf215546Sopenharmony_ci   if (unrestricted) {
406bf215546Sopenharmony_ci      nir_ssa_def *in_color_load =
407bf215546Sopenharmony_ci         nir_load_push_constant(&fs_b, 1, 32, nir_imm_int(&fs_b, 0), .range = 4);
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci      nir_variable *fs_out_depth =
410bf215546Sopenharmony_ci         nir_variable_create(fs_b.shader, nir_var_shader_out, glsl_int_type(), "f_depth");
411bf215546Sopenharmony_ci      fs_out_depth->data.location = FRAG_RESULT_DEPTH;
412bf215546Sopenharmony_ci      nir_store_var(&fs_b, fs_out_depth, in_color_load, 0x1);
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci      z = nir_imm_float(&vs_b, 0.0);
415bf215546Sopenharmony_ci   } else {
416bf215546Sopenharmony_ci      z = nir_load_push_constant(&vs_b, 1, 32, nir_imm_int(&vs_b, 0), .range = 4);
417bf215546Sopenharmony_ci   }
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_ci   nir_ssa_def *outvec = nir_gen_rect_vertices(&vs_b, z, NULL);
420bf215546Sopenharmony_ci   nir_store_var(&vs_b, vs_out_pos, outvec, 0xf);
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci   const struct glsl_type *layer_type = glsl_int_type();
423bf215546Sopenharmony_ci   nir_variable *vs_out_layer =
424bf215546Sopenharmony_ci      nir_variable_create(vs_b.shader, nir_var_shader_out, layer_type, "v_layer");
425bf215546Sopenharmony_ci   vs_out_layer->data.location = VARYING_SLOT_LAYER;
426bf215546Sopenharmony_ci   vs_out_layer->data.interpolation = INTERP_MODE_FLAT;
427bf215546Sopenharmony_ci   nir_ssa_def *inst_id = nir_load_instance_id(&vs_b);
428bf215546Sopenharmony_ci   nir_ssa_def *base_instance = nir_load_base_instance(&vs_b);
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci   nir_ssa_def *layer_id = nir_iadd(&vs_b, inst_id, base_instance);
431bf215546Sopenharmony_ci   nir_store_var(&vs_b, vs_out_layer, layer_id, 0x1);
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci   *out_vs = vs_b.shader;
434bf215546Sopenharmony_ci   *out_fs = fs_b.shader;
435bf215546Sopenharmony_ci}
436bf215546Sopenharmony_ci
437bf215546Sopenharmony_cistatic VkResult
438bf215546Sopenharmony_cicreate_depthstencil_pipeline(struct radv_device *device, VkImageAspectFlags aspects,
439bf215546Sopenharmony_ci                             uint32_t samples, int index, bool unrestricted, VkPipeline *pipeline)
440bf215546Sopenharmony_ci{
441bf215546Sopenharmony_ci   struct nir_shader *vs_nir, *fs_nir;
442bf215546Sopenharmony_ci   VkResult result;
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci   mtx_lock(&device->meta_state.mtx);
445bf215546Sopenharmony_ci   if (*pipeline) {
446bf215546Sopenharmony_ci      mtx_unlock(&device->meta_state.mtx);
447bf215546Sopenharmony_ci      return VK_SUCCESS;
448bf215546Sopenharmony_ci   }
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_ci   build_depthstencil_shader(device, &vs_nir, &fs_nir, unrestricted);
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci   const VkPipelineVertexInputStateCreateInfo vi_state = {
453bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
454bf215546Sopenharmony_ci      .vertexBindingDescriptionCount = 0,
455bf215546Sopenharmony_ci      .vertexAttributeDescriptionCount = 0,
456bf215546Sopenharmony_ci   };
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_ci   const VkPipelineDepthStencilStateCreateInfo ds_state = {
459bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
460bf215546Sopenharmony_ci      .depthTestEnable = !!(aspects & VK_IMAGE_ASPECT_DEPTH_BIT),
461bf215546Sopenharmony_ci      .depthCompareOp = VK_COMPARE_OP_ALWAYS,
462bf215546Sopenharmony_ci      .depthWriteEnable = !!(aspects & VK_IMAGE_ASPECT_DEPTH_BIT),
463bf215546Sopenharmony_ci      .depthBoundsTestEnable = false,
464bf215546Sopenharmony_ci      .stencilTestEnable = !!(aspects & VK_IMAGE_ASPECT_STENCIL_BIT),
465bf215546Sopenharmony_ci      .front =
466bf215546Sopenharmony_ci         {
467bf215546Sopenharmony_ci            .passOp = VK_STENCIL_OP_REPLACE,
468bf215546Sopenharmony_ci            .compareOp = VK_COMPARE_OP_ALWAYS,
469bf215546Sopenharmony_ci            .writeMask = UINT32_MAX,
470bf215546Sopenharmony_ci            .reference = 0, /* dynamic */
471bf215546Sopenharmony_ci         },
472bf215546Sopenharmony_ci      .back = {0 /* dont care */},
473bf215546Sopenharmony_ci      .minDepthBounds = 0.0f,
474bf215546Sopenharmony_ci      .maxDepthBounds = 1.0f,
475bf215546Sopenharmony_ci   };
476bf215546Sopenharmony_ci
477bf215546Sopenharmony_ci   const VkPipelineColorBlendStateCreateInfo cb_state = {
478bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
479bf215546Sopenharmony_ci      .logicOpEnable = false,
480bf215546Sopenharmony_ci      .attachmentCount = 0,
481bf215546Sopenharmony_ci      .pAttachments = NULL,
482bf215546Sopenharmony_ci      .blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f },
483bf215546Sopenharmony_ci   };
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci   const VkPipelineRenderingCreateInfo rendering_create_info = {
486bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
487bf215546Sopenharmony_ci      .depthAttachmentFormat =
488bf215546Sopenharmony_ci         (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) ? VK_FORMAT_D32_SFLOAT : VK_FORMAT_UNDEFINED,
489bf215546Sopenharmony_ci      .stencilAttachmentFormat =
490bf215546Sopenharmony_ci         (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) ? VK_FORMAT_S8_UINT : VK_FORMAT_UNDEFINED,
491bf215546Sopenharmony_ci   };
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_ci   struct radv_graphics_pipeline_create_info extra = {
494bf215546Sopenharmony_ci      .use_rectlist = true,
495bf215546Sopenharmony_ci   };
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci   if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
498bf215546Sopenharmony_ci      extra.db_depth_clear = index == DEPTH_CLEAR_SLOW ? false : true;
499bf215546Sopenharmony_ci   }
500bf215546Sopenharmony_ci   if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
501bf215546Sopenharmony_ci      extra.db_stencil_clear = index == DEPTH_CLEAR_SLOW ? false : true;
502bf215546Sopenharmony_ci   }
503bf215546Sopenharmony_ci   result =
504bf215546Sopenharmony_ci      create_pipeline(device, samples, vs_nir, fs_nir, &vi_state, &ds_state, &cb_state,
505bf215546Sopenharmony_ci                      &rendering_create_info, device->meta_state.clear_depth_p_layout, &extra,
506bf215546Sopenharmony_ci                      &device->meta_state.alloc, pipeline);
507bf215546Sopenharmony_ci
508bf215546Sopenharmony_ci   mtx_unlock(&device->meta_state.mtx);
509bf215546Sopenharmony_ci   return result;
510bf215546Sopenharmony_ci}
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_cistatic bool
513bf215546Sopenharmony_cidepth_view_can_fast_clear(struct radv_cmd_buffer *cmd_buffer, const struct radv_image_view *iview,
514bf215546Sopenharmony_ci                          VkImageAspectFlags aspects, VkImageLayout layout, bool in_render_loop,
515bf215546Sopenharmony_ci                          const VkClearRect *clear_rect, VkClearDepthStencilValue clear_value)
516bf215546Sopenharmony_ci{
517bf215546Sopenharmony_ci   if (!iview)
518bf215546Sopenharmony_ci      return false;
519bf215546Sopenharmony_ci
520bf215546Sopenharmony_ci   uint32_t queue_mask = radv_image_queue_family_mask(iview->image, cmd_buffer->qf,
521bf215546Sopenharmony_ci                                                      cmd_buffer->qf);
522bf215546Sopenharmony_ci   if (clear_rect->rect.offset.x || clear_rect->rect.offset.y ||
523bf215546Sopenharmony_ci       clear_rect->rect.extent.width != iview->extent.width ||
524bf215546Sopenharmony_ci       clear_rect->rect.extent.height != iview->extent.height)
525bf215546Sopenharmony_ci      return false;
526bf215546Sopenharmony_ci   if (radv_image_is_tc_compat_htile(iview->image) &&
527bf215546Sopenharmony_ci       (((aspects & VK_IMAGE_ASPECT_DEPTH_BIT) && clear_value.depth != 0.0 &&
528bf215546Sopenharmony_ci         clear_value.depth != 1.0) ||
529bf215546Sopenharmony_ci        ((aspects & VK_IMAGE_ASPECT_STENCIL_BIT) && clear_value.stencil != 0)))
530bf215546Sopenharmony_ci      return false;
531bf215546Sopenharmony_ci   if (radv_htile_enabled(iview->image, iview->vk.base_mip_level) && iview->vk.base_mip_level == 0 &&
532bf215546Sopenharmony_ci       iview->vk.base_array_layer == 0 && iview->vk.layer_count == iview->image->info.array_size &&
533bf215546Sopenharmony_ci       radv_layout_is_htile_compressed(cmd_buffer->device, iview->image, layout, in_render_loop,
534bf215546Sopenharmony_ci                                       queue_mask) &&
535bf215546Sopenharmony_ci       radv_image_extent_compare(iview->image, &iview->extent))
536bf215546Sopenharmony_ci      return true;
537bf215546Sopenharmony_ci   return false;
538bf215546Sopenharmony_ci}
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_cistatic VkPipeline
541bf215546Sopenharmony_cipick_depthstencil_pipeline(struct radv_cmd_buffer *cmd_buffer, struct radv_meta_state *meta_state,
542bf215546Sopenharmony_ci                           const struct radv_image_view *iview, int samples_log2,
543bf215546Sopenharmony_ci                           VkImageAspectFlags aspects, VkImageLayout layout, bool in_render_loop,
544bf215546Sopenharmony_ci                           const VkClearRect *clear_rect, VkClearDepthStencilValue clear_value)
545bf215546Sopenharmony_ci{
546bf215546Sopenharmony_ci   bool fast = depth_view_can_fast_clear(cmd_buffer, iview, aspects, layout, in_render_loop,
547bf215546Sopenharmony_ci                                         clear_rect, clear_value);
548bf215546Sopenharmony_ci   bool unrestricted = cmd_buffer->device->vk.enabled_extensions.EXT_depth_range_unrestricted;
549bf215546Sopenharmony_ci   int index = fast ? DEPTH_CLEAR_FAST : DEPTH_CLEAR_SLOW;
550bf215546Sopenharmony_ci   VkPipeline *pipeline;
551bf215546Sopenharmony_ci
552bf215546Sopenharmony_ci   switch (aspects) {
553bf215546Sopenharmony_ci   case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
554bf215546Sopenharmony_ci      pipeline = unrestricted
555bf215546Sopenharmony_ci                    ? &meta_state->ds_clear[samples_log2].depthstencil_unrestricted_pipeline[index]
556bf215546Sopenharmony_ci                    : &meta_state->ds_clear[samples_log2].depthstencil_pipeline[index];
557bf215546Sopenharmony_ci      break;
558bf215546Sopenharmony_ci   case VK_IMAGE_ASPECT_DEPTH_BIT:
559bf215546Sopenharmony_ci      pipeline = unrestricted
560bf215546Sopenharmony_ci                    ? &meta_state->ds_clear[samples_log2].depth_only_unrestricted_pipeline[index]
561bf215546Sopenharmony_ci                    : &meta_state->ds_clear[samples_log2].depth_only_pipeline[index];
562bf215546Sopenharmony_ci      break;
563bf215546Sopenharmony_ci   case VK_IMAGE_ASPECT_STENCIL_BIT:
564bf215546Sopenharmony_ci      pipeline = unrestricted
565bf215546Sopenharmony_ci                    ? &meta_state->ds_clear[samples_log2].stencil_only_unrestricted_pipeline[index]
566bf215546Sopenharmony_ci                    : &meta_state->ds_clear[samples_log2].stencil_only_pipeline[index];
567bf215546Sopenharmony_ci      break;
568bf215546Sopenharmony_ci   default:
569bf215546Sopenharmony_ci      unreachable("expected depth or stencil aspect");
570bf215546Sopenharmony_ci   }
571bf215546Sopenharmony_ci
572bf215546Sopenharmony_ci   if (*pipeline == VK_NULL_HANDLE) {
573bf215546Sopenharmony_ci      VkResult ret = create_depthstencil_pipeline(
574bf215546Sopenharmony_ci         cmd_buffer->device, aspects, 1u << samples_log2, index, unrestricted, pipeline);
575bf215546Sopenharmony_ci      if (ret != VK_SUCCESS) {
576bf215546Sopenharmony_ci         cmd_buffer->record_result = ret;
577bf215546Sopenharmony_ci         return VK_NULL_HANDLE;
578bf215546Sopenharmony_ci      }
579bf215546Sopenharmony_ci   }
580bf215546Sopenharmony_ci   return *pipeline;
581bf215546Sopenharmony_ci}
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_cistatic void
584bf215546Sopenharmony_ciemit_depthstencil_clear(struct radv_cmd_buffer *cmd_buffer, const VkClearAttachment *clear_att,
585bf215546Sopenharmony_ci                        const VkClearRect *clear_rect, struct radv_subpass_attachment *ds_att,
586bf215546Sopenharmony_ci                        uint32_t view_mask, bool ds_resolve_clear)
587bf215546Sopenharmony_ci{
588bf215546Sopenharmony_ci   struct radv_device *device = cmd_buffer->device;
589bf215546Sopenharmony_ci   struct radv_meta_state *meta_state = &device->meta_state;
590bf215546Sopenharmony_ci   const struct radv_subpass *subpass = cmd_buffer->state.subpass;
591bf215546Sopenharmony_ci   const uint32_t pass_att = ds_att->attachment;
592bf215546Sopenharmony_ci   VkClearDepthStencilValue clear_value = clear_att->clearValue.depthStencil;
593bf215546Sopenharmony_ci   VkImageAspectFlags aspects = clear_att->aspectMask;
594bf215546Sopenharmony_ci   const struct radv_image_view *iview =
595bf215546Sopenharmony_ci      cmd_buffer->state.attachments ? cmd_buffer->state.attachments[pass_att].iview : NULL;
596bf215546Sopenharmony_ci   uint32_t samples, samples_log2;
597bf215546Sopenharmony_ci   VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
598bf215546Sopenharmony_ci
599bf215546Sopenharmony_ci   /* When a framebuffer is bound to the current command buffer, get the
600bf215546Sopenharmony_ci    * number of samples from it. Otherwise, get the number of samples from
601bf215546Sopenharmony_ci    * the render pass because it's likely a secondary command buffer.
602bf215546Sopenharmony_ci    */
603bf215546Sopenharmony_ci   if (iview) {
604bf215546Sopenharmony_ci      samples = iview->image->info.samples;
605bf215546Sopenharmony_ci   } else {
606bf215546Sopenharmony_ci      samples = cmd_buffer->state.pass->attachments[pass_att].samples;
607bf215546Sopenharmony_ci   }
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_ci   samples_log2 = ffs(samples) - 1;
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_ci   assert(pass_att != VK_ATTACHMENT_UNUSED);
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_ci   if (!(aspects & VK_IMAGE_ASPECT_DEPTH_BIT))
614bf215546Sopenharmony_ci      clear_value.depth = 1.0f;
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_ci   if (cmd_buffer->device->vk.enabled_extensions.EXT_depth_range_unrestricted) {
617bf215546Sopenharmony_ci      radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
618bf215546Sopenharmony_ci                            device->meta_state.clear_depth_unrestricted_p_layout,
619bf215546Sopenharmony_ci                            VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4, &clear_value.depth);
620bf215546Sopenharmony_ci   } else {
621bf215546Sopenharmony_ci      radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
622bf215546Sopenharmony_ci                            device->meta_state.clear_depth_p_layout, VK_SHADER_STAGE_VERTEX_BIT, 0,
623bf215546Sopenharmony_ci                            4, &clear_value.depth);
624bf215546Sopenharmony_ci   }
625bf215546Sopenharmony_ci
626bf215546Sopenharmony_ci   uint32_t prev_reference = cmd_buffer->state.dynamic.stencil_reference.front;
627bf215546Sopenharmony_ci   if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
628bf215546Sopenharmony_ci      radv_CmdSetStencilReference(cmd_buffer_h, VK_STENCIL_FACE_FRONT_BIT, clear_value.stencil);
629bf215546Sopenharmony_ci   }
630bf215546Sopenharmony_ci
631bf215546Sopenharmony_ci   VkPipeline pipeline =
632bf215546Sopenharmony_ci      pick_depthstencil_pipeline(cmd_buffer, meta_state, iview, samples_log2, aspects,
633bf215546Sopenharmony_ci                                 ds_att->layout, ds_att->in_render_loop, clear_rect, clear_value);
634bf215546Sopenharmony_ci   if (!pipeline)
635bf215546Sopenharmony_ci      return;
636bf215546Sopenharmony_ci
637bf215546Sopenharmony_ci   struct radv_subpass clear_subpass = {
638bf215546Sopenharmony_ci      .color_count = 0,
639bf215546Sopenharmony_ci      .color_attachments = NULL,
640bf215546Sopenharmony_ci      .depth_stencil_attachment = ds_att,
641bf215546Sopenharmony_ci   };
642bf215546Sopenharmony_ci
643bf215546Sopenharmony_ci   if (ds_resolve_clear)
644bf215546Sopenharmony_ci      radv_cmd_buffer_set_subpass(cmd_buffer, &clear_subpass);
645bf215546Sopenharmony_ci
646bf215546Sopenharmony_ci   radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
647bf215546Sopenharmony_ci
648bf215546Sopenharmony_ci   if (depth_view_can_fast_clear(cmd_buffer, iview, aspects, ds_att->layout, ds_att->in_render_loop,
649bf215546Sopenharmony_ci                                 clear_rect, clear_value))
650bf215546Sopenharmony_ci      radv_update_ds_clear_metadata(cmd_buffer, iview, clear_value, aspects);
651bf215546Sopenharmony_ci
652bf215546Sopenharmony_ci   radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
653bf215546Sopenharmony_ci                       &(VkViewport){.x = clear_rect->rect.offset.x,
654bf215546Sopenharmony_ci                                     .y = clear_rect->rect.offset.y,
655bf215546Sopenharmony_ci                                     .width = clear_rect->rect.extent.width,
656bf215546Sopenharmony_ci                                     .height = clear_rect->rect.extent.height,
657bf215546Sopenharmony_ci                                     .minDepth = 0.0f,
658bf215546Sopenharmony_ci                                     .maxDepth = 1.0f});
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_ci   radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &clear_rect->rect);
661bf215546Sopenharmony_ci
662bf215546Sopenharmony_ci   if (view_mask) {
663bf215546Sopenharmony_ci      u_foreach_bit(i, view_mask) radv_CmdDraw(cmd_buffer_h, 3, 1, 0, i);
664bf215546Sopenharmony_ci   } else {
665bf215546Sopenharmony_ci      radv_CmdDraw(cmd_buffer_h, 3, clear_rect->layerCount, 0, clear_rect->baseArrayLayer);
666bf215546Sopenharmony_ci   }
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_ci   if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
669bf215546Sopenharmony_ci      radv_CmdSetStencilReference(cmd_buffer_h, VK_STENCIL_FACE_FRONT_BIT, prev_reference);
670bf215546Sopenharmony_ci   }
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ci   if (ds_resolve_clear)
673bf215546Sopenharmony_ci      radv_cmd_buffer_restore_subpass(cmd_buffer, subpass);
674bf215546Sopenharmony_ci}
675bf215546Sopenharmony_ci
676bf215546Sopenharmony_cistatic uint32_t
677bf215546Sopenharmony_ciclear_htile_mask(struct radv_cmd_buffer *cmd_buffer, const struct radv_image *image,
678bf215546Sopenharmony_ci                 struct radeon_winsys_bo *bo, uint64_t offset, uint64_t size, uint32_t htile_value,
679bf215546Sopenharmony_ci                 uint32_t htile_mask)
680bf215546Sopenharmony_ci{
681bf215546Sopenharmony_ci   struct radv_device *device = cmd_buffer->device;
682bf215546Sopenharmony_ci   struct radv_meta_state *state = &device->meta_state;
683bf215546Sopenharmony_ci   uint64_t block_count = round_up_u64(size, 1024);
684bf215546Sopenharmony_ci   struct radv_meta_saved_state saved_state;
685bf215546Sopenharmony_ci   struct radv_buffer dst_buffer;
686bf215546Sopenharmony_ci
687bf215546Sopenharmony_ci   radv_meta_save(
688bf215546Sopenharmony_ci      &saved_state, cmd_buffer,
689bf215546Sopenharmony_ci      RADV_META_SAVE_COMPUTE_PIPELINE | RADV_META_SAVE_CONSTANTS | RADV_META_SAVE_DESCRIPTORS);
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_ci   radv_buffer_init(&dst_buffer, device, bo, size, offset);
692bf215546Sopenharmony_ci
693bf215546Sopenharmony_ci   radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE,
694bf215546Sopenharmony_ci                        state->clear_htile_mask_pipeline);
695bf215546Sopenharmony_ci
696bf215546Sopenharmony_ci   radv_meta_push_descriptor_set(
697bf215546Sopenharmony_ci      cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, state->clear_htile_mask_p_layout, 0, /* set */
698bf215546Sopenharmony_ci      1, /* descriptorWriteCount */
699bf215546Sopenharmony_ci      (VkWriteDescriptorSet[]){
700bf215546Sopenharmony_ci         {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
701bf215546Sopenharmony_ci          .dstBinding = 0,
702bf215546Sopenharmony_ci          .dstArrayElement = 0,
703bf215546Sopenharmony_ci          .descriptorCount = 1,
704bf215546Sopenharmony_ci          .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
705bf215546Sopenharmony_ci          .pBufferInfo = &(VkDescriptorBufferInfo){.buffer = radv_buffer_to_handle(&dst_buffer),
706bf215546Sopenharmony_ci                                                   .offset = 0,
707bf215546Sopenharmony_ci                                                   .range = size}}});
708bf215546Sopenharmony_ci
709bf215546Sopenharmony_ci   const unsigned constants[2] = {
710bf215546Sopenharmony_ci      htile_value & htile_mask,
711bf215546Sopenharmony_ci      ~htile_mask,
712bf215546Sopenharmony_ci   };
713bf215546Sopenharmony_ci
714bf215546Sopenharmony_ci   radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), state->clear_htile_mask_p_layout,
715bf215546Sopenharmony_ci                         VK_SHADER_STAGE_COMPUTE_BIT, 0, 8, constants);
716bf215546Sopenharmony_ci
717bf215546Sopenharmony_ci   radv_CmdDispatch(radv_cmd_buffer_to_handle(cmd_buffer), block_count, 1, 1);
718bf215546Sopenharmony_ci
719bf215546Sopenharmony_ci   radv_buffer_finish(&dst_buffer);
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_ci   radv_meta_restore(&saved_state, cmd_buffer);
722bf215546Sopenharmony_ci
723bf215546Sopenharmony_ci   return RADV_CMD_FLAG_CS_PARTIAL_FLUSH |
724bf215546Sopenharmony_ci          radv_src_access_flush(cmd_buffer, VK_ACCESS_2_SHADER_WRITE_BIT, image);
725bf215546Sopenharmony_ci}
726bf215546Sopenharmony_ci
727bf215546Sopenharmony_cistatic uint32_t
728bf215546Sopenharmony_ciradv_get_htile_fast_clear_value(const struct radv_device *device, const struct radv_image *image,
729bf215546Sopenharmony_ci                                VkClearDepthStencilValue value)
730bf215546Sopenharmony_ci{
731bf215546Sopenharmony_ci   uint32_t max_zval = 0x3fff; /* maximum 14-bit value. */
732bf215546Sopenharmony_ci   uint32_t zmask = 0, smem = 0;
733bf215546Sopenharmony_ci   uint32_t htile_value;
734bf215546Sopenharmony_ci   uint32_t zmin, zmax;
735bf215546Sopenharmony_ci
736bf215546Sopenharmony_ci   /* Convert the depth value to 14-bit zmin/zmax values. */
737bf215546Sopenharmony_ci   zmin = lroundf(value.depth * max_zval);
738bf215546Sopenharmony_ci   zmax = zmin;
739bf215546Sopenharmony_ci
740bf215546Sopenharmony_ci   if (radv_image_tile_stencil_disabled(device, image)) {
741bf215546Sopenharmony_ci      /* Z only (no stencil):
742bf215546Sopenharmony_ci       *
743bf215546Sopenharmony_ci       * |31     18|17      4|3     0|
744bf215546Sopenharmony_ci       * +---------+---------+-------+
745bf215546Sopenharmony_ci       * |  Max Z  |  Min Z  | ZMask |
746bf215546Sopenharmony_ci       */
747bf215546Sopenharmony_ci      htile_value = (((zmax  & 0x3fff) << 18) |
748bf215546Sopenharmony_ci                     ((zmin  & 0x3fff) <<  4) |
749bf215546Sopenharmony_ci                     ((zmask &    0xf) <<  0));
750bf215546Sopenharmony_ci   } else {
751bf215546Sopenharmony_ci
752bf215546Sopenharmony_ci      /* Z and stencil:
753bf215546Sopenharmony_ci       *
754bf215546Sopenharmony_ci       * |31       12|11 10|9    8|7   6|5   4|3     0|
755bf215546Sopenharmony_ci       * +-----------+-----+------+-----+-----+-------+
756bf215546Sopenharmony_ci       * |  Z Range  |     | SMem | SR1 | SR0 | ZMask |
757bf215546Sopenharmony_ci       *
758bf215546Sopenharmony_ci       * Z, stencil, 4 bit VRS encoding:
759bf215546Sopenharmony_ci       * |31       12| 11      10 |9    8|7         6 |5   4|3     0|
760bf215546Sopenharmony_ci       * +-----------+------------+------+------------+-----+-------+
761bf215546Sopenharmony_ci       * |  Z Range  | VRS Y-rate | SMem | VRS X-rate | SR0 | ZMask |
762bf215546Sopenharmony_ci       */
763bf215546Sopenharmony_ci      uint32_t delta = 0;
764bf215546Sopenharmony_ci      uint32_t zrange = ((zmax << 6) | delta);
765bf215546Sopenharmony_ci      uint32_t sresults = 0xf; /* SR0/SR1 both as 0x3. */
766bf215546Sopenharmony_ci
767bf215546Sopenharmony_ci      if (radv_image_has_vrs_htile(device, image))
768bf215546Sopenharmony_ci         sresults = 0x3;
769bf215546Sopenharmony_ci
770bf215546Sopenharmony_ci      htile_value = (((zrange   & 0xfffff) << 12) |
771bf215546Sopenharmony_ci                     ((smem     & 0x3)     <<  8) |
772bf215546Sopenharmony_ci                     ((sresults & 0xf)     <<  4) |
773bf215546Sopenharmony_ci                     ((zmask    & 0xf)     <<  0));
774bf215546Sopenharmony_ci   }
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_ci   return htile_value;
777bf215546Sopenharmony_ci}
778bf215546Sopenharmony_ci
779bf215546Sopenharmony_cistatic uint32_t
780bf215546Sopenharmony_ciradv_get_htile_mask(const struct radv_device *device, const struct radv_image *image,
781bf215546Sopenharmony_ci                    VkImageAspectFlags aspects)
782bf215546Sopenharmony_ci{
783bf215546Sopenharmony_ci   uint32_t mask = 0;
784bf215546Sopenharmony_ci
785bf215546Sopenharmony_ci   if (radv_image_tile_stencil_disabled(device, image)) {
786bf215546Sopenharmony_ci      /* All the HTILE buffer is used when there is no stencil. */
787bf215546Sopenharmony_ci      mask = UINT32_MAX;
788bf215546Sopenharmony_ci   } else {
789bf215546Sopenharmony_ci      if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
790bf215546Sopenharmony_ci         mask |= 0xfffffc0f;
791bf215546Sopenharmony_ci      if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
792bf215546Sopenharmony_ci         mask |= 0x000003f0;
793bf215546Sopenharmony_ci   }
794bf215546Sopenharmony_ci
795bf215546Sopenharmony_ci   return mask;
796bf215546Sopenharmony_ci}
797bf215546Sopenharmony_ci
798bf215546Sopenharmony_cistatic bool
799bf215546Sopenharmony_ciradv_is_fast_clear_depth_allowed(VkClearDepthStencilValue value)
800bf215546Sopenharmony_ci{
801bf215546Sopenharmony_ci   return value.depth == 1.0f || value.depth == 0.0f;
802bf215546Sopenharmony_ci}
803bf215546Sopenharmony_ci
804bf215546Sopenharmony_cistatic bool
805bf215546Sopenharmony_ciradv_is_fast_clear_stencil_allowed(VkClearDepthStencilValue value)
806bf215546Sopenharmony_ci{
807bf215546Sopenharmony_ci   return value.stencil == 0;
808bf215546Sopenharmony_ci}
809bf215546Sopenharmony_ci
810bf215546Sopenharmony_cistatic bool
811bf215546Sopenharmony_ciradv_can_fast_clear_depth(struct radv_cmd_buffer *cmd_buffer, const struct radv_image_view *iview,
812bf215546Sopenharmony_ci                          VkImageLayout image_layout, bool in_render_loop,
813bf215546Sopenharmony_ci                          VkImageAspectFlags aspects, const VkClearRect *clear_rect,
814bf215546Sopenharmony_ci                          const VkClearDepthStencilValue clear_value, uint32_t view_mask)
815bf215546Sopenharmony_ci{
816bf215546Sopenharmony_ci   if (!iview || !iview->support_fast_clear)
817bf215546Sopenharmony_ci      return false;
818bf215546Sopenharmony_ci
819bf215546Sopenharmony_ci   if (!radv_layout_is_htile_compressed(
820bf215546Sopenharmony_ci          cmd_buffer->device, iview->image, image_layout, in_render_loop,
821bf215546Sopenharmony_ci          radv_image_queue_family_mask(iview->image, cmd_buffer->qf,
822bf215546Sopenharmony_ci                                       cmd_buffer->qf)))
823bf215546Sopenharmony_ci      return false;
824bf215546Sopenharmony_ci
825bf215546Sopenharmony_ci   if (clear_rect->rect.offset.x || clear_rect->rect.offset.y ||
826bf215546Sopenharmony_ci       clear_rect->rect.extent.width != iview->image->info.width ||
827bf215546Sopenharmony_ci       clear_rect->rect.extent.height != iview->image->info.height)
828bf215546Sopenharmony_ci      return false;
829bf215546Sopenharmony_ci
830bf215546Sopenharmony_ci   if (view_mask && (iview->image->info.array_size >= 32 ||
831bf215546Sopenharmony_ci                     (1u << iview->image->info.array_size) - 1u != view_mask))
832bf215546Sopenharmony_ci      return false;
833bf215546Sopenharmony_ci   if (!view_mask && clear_rect->baseArrayLayer != 0)
834bf215546Sopenharmony_ci      return false;
835bf215546Sopenharmony_ci   if (!view_mask && clear_rect->layerCount != iview->image->info.array_size)
836bf215546Sopenharmony_ci      return false;
837bf215546Sopenharmony_ci
838bf215546Sopenharmony_ci   if (cmd_buffer->device->vk.enabled_extensions.EXT_depth_range_unrestricted &&
839bf215546Sopenharmony_ci       (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) &&
840bf215546Sopenharmony_ci       (clear_value.depth < 0.0 || clear_value.depth > 1.0))
841bf215546Sopenharmony_ci      return false;
842bf215546Sopenharmony_ci
843bf215546Sopenharmony_ci   if (radv_image_is_tc_compat_htile(iview->image) &&
844bf215546Sopenharmony_ci       (((aspects & VK_IMAGE_ASPECT_DEPTH_BIT) && !radv_is_fast_clear_depth_allowed(clear_value)) ||
845bf215546Sopenharmony_ci        ((aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
846bf215546Sopenharmony_ci         !radv_is_fast_clear_stencil_allowed(clear_value))))
847bf215546Sopenharmony_ci      return false;
848bf215546Sopenharmony_ci
849bf215546Sopenharmony_ci   if (iview->image->info.levels > 1) {
850bf215546Sopenharmony_ci      uint32_t last_level = iview->vk.base_mip_level + iview->vk.level_count - 1;
851bf215546Sopenharmony_ci      if (last_level >= iview->image->planes[0].surface.num_meta_levels) {
852bf215546Sopenharmony_ci         /* Do not fast clears if one level can't be fast cleared. */
853bf215546Sopenharmony_ci         return false;
854bf215546Sopenharmony_ci      }
855bf215546Sopenharmony_ci   }
856bf215546Sopenharmony_ci
857bf215546Sopenharmony_ci   return true;
858bf215546Sopenharmony_ci}
859bf215546Sopenharmony_ci
860bf215546Sopenharmony_cistatic void
861bf215546Sopenharmony_ciradv_fast_clear_depth(struct radv_cmd_buffer *cmd_buffer, const struct radv_image_view *iview,
862bf215546Sopenharmony_ci                      const VkClearAttachment *clear_att, enum radv_cmd_flush_bits *pre_flush,
863bf215546Sopenharmony_ci                      enum radv_cmd_flush_bits *post_flush)
864bf215546Sopenharmony_ci{
865bf215546Sopenharmony_ci   VkClearDepthStencilValue clear_value = clear_att->clearValue.depthStencil;
866bf215546Sopenharmony_ci   VkImageAspectFlags aspects = clear_att->aspectMask;
867bf215546Sopenharmony_ci   uint32_t clear_word, flush_bits;
868bf215546Sopenharmony_ci
869bf215546Sopenharmony_ci   clear_word = radv_get_htile_fast_clear_value(cmd_buffer->device, iview->image, clear_value);
870bf215546Sopenharmony_ci
871bf215546Sopenharmony_ci   if (pre_flush) {
872bf215546Sopenharmony_ci      enum radv_cmd_flush_bits bits =
873bf215546Sopenharmony_ci         radv_src_access_flush(cmd_buffer, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
874bf215546Sopenharmony_ci                               iview->image) |
875bf215546Sopenharmony_ci         radv_dst_access_flush(cmd_buffer, VK_ACCESS_2_SHADER_WRITE_BIT |
876bf215546Sopenharmony_ci                                           VK_ACCESS_2_SHADER_READ_BIT, iview->image);
877bf215546Sopenharmony_ci      cmd_buffer->state.flush_bits |= bits & ~*pre_flush;
878bf215546Sopenharmony_ci      *pre_flush |= cmd_buffer->state.flush_bits;
879bf215546Sopenharmony_ci   }
880bf215546Sopenharmony_ci
881bf215546Sopenharmony_ci   VkImageSubresourceRange range = {
882bf215546Sopenharmony_ci      .aspectMask = aspects,
883bf215546Sopenharmony_ci      .baseMipLevel = iview->vk.base_mip_level,
884bf215546Sopenharmony_ci      .levelCount = iview->vk.level_count,
885bf215546Sopenharmony_ci      .baseArrayLayer = iview->vk.base_array_layer,
886bf215546Sopenharmony_ci      .layerCount = iview->vk.layer_count,
887bf215546Sopenharmony_ci   };
888bf215546Sopenharmony_ci
889bf215546Sopenharmony_ci   flush_bits = radv_clear_htile(cmd_buffer, iview->image, &range, clear_word);
890bf215546Sopenharmony_ci
891bf215546Sopenharmony_ci   if (iview->image->planes[0].surface.has_stencil &&
892bf215546Sopenharmony_ci       !(aspects == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
893bf215546Sopenharmony_ci      /* Synchronize after performing a depth-only or a stencil-only
894bf215546Sopenharmony_ci       * fast clear because the driver uses an optimized path which
895bf215546Sopenharmony_ci       * performs a read-modify-write operation, and the two separate
896bf215546Sopenharmony_ci       * aspects might use the same HTILE memory.
897bf215546Sopenharmony_ci       */
898bf215546Sopenharmony_ci      cmd_buffer->state.flush_bits |= flush_bits;
899bf215546Sopenharmony_ci   }
900bf215546Sopenharmony_ci
901bf215546Sopenharmony_ci   radv_update_ds_clear_metadata(cmd_buffer, iview, clear_value, aspects);
902bf215546Sopenharmony_ci   if (post_flush) {
903bf215546Sopenharmony_ci      *post_flush |= flush_bits;
904bf215546Sopenharmony_ci   }
905bf215546Sopenharmony_ci}
906bf215546Sopenharmony_ci
907bf215546Sopenharmony_cistatic nir_shader *
908bf215546Sopenharmony_cibuild_clear_htile_mask_shader(struct radv_device *dev)
909bf215546Sopenharmony_ci{
910bf215546Sopenharmony_ci   nir_builder b = radv_meta_init_shader(dev, MESA_SHADER_COMPUTE, "meta_clear_htile_mask");
911bf215546Sopenharmony_ci   b.shader->info.workgroup_size[0] = 64;
912bf215546Sopenharmony_ci
913bf215546Sopenharmony_ci   nir_ssa_def *global_id = get_global_ids(&b, 1);
914bf215546Sopenharmony_ci
915bf215546Sopenharmony_ci   nir_ssa_def *offset = nir_imul_imm(&b, global_id, 16);
916bf215546Sopenharmony_ci   offset = nir_channel(&b, offset, 0);
917bf215546Sopenharmony_ci
918bf215546Sopenharmony_ci   nir_ssa_def *buf = radv_meta_load_descriptor(&b, 0, 0);
919bf215546Sopenharmony_ci
920bf215546Sopenharmony_ci   nir_ssa_def *constants = nir_load_push_constant(&b, 2, 32, nir_imm_int(&b, 0), .range = 8);
921bf215546Sopenharmony_ci
922bf215546Sopenharmony_ci   nir_ssa_def *load = nir_load_ssbo(&b, 4, 32, buf, offset, .align_mul = 16);
923bf215546Sopenharmony_ci
924bf215546Sopenharmony_ci   /* data = (data & ~htile_mask) | (htile_value & htile_mask) */
925bf215546Sopenharmony_ci   nir_ssa_def *data = nir_iand(&b, load, nir_channel(&b, constants, 1));
926bf215546Sopenharmony_ci   data = nir_ior(&b, data, nir_channel(&b, constants, 0));
927bf215546Sopenharmony_ci
928bf215546Sopenharmony_ci   nir_store_ssbo(&b, data, buf, offset, .access = ACCESS_NON_READABLE, .align_mul = 16);
929bf215546Sopenharmony_ci
930bf215546Sopenharmony_ci   return b.shader;
931bf215546Sopenharmony_ci}
932bf215546Sopenharmony_ci
933bf215546Sopenharmony_cistatic VkResult
934bf215546Sopenharmony_ciinit_meta_clear_htile_mask_state(struct radv_device *device)
935bf215546Sopenharmony_ci{
936bf215546Sopenharmony_ci   struct radv_meta_state *state = &device->meta_state;
937bf215546Sopenharmony_ci   VkResult result;
938bf215546Sopenharmony_ci   nir_shader *cs = build_clear_htile_mask_shader(device);
939bf215546Sopenharmony_ci
940bf215546Sopenharmony_ci   VkDescriptorSetLayoutCreateInfo ds_layout_info = {
941bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
942bf215546Sopenharmony_ci      .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
943bf215546Sopenharmony_ci      .bindingCount = 1,
944bf215546Sopenharmony_ci      .pBindings = (VkDescriptorSetLayoutBinding[]){
945bf215546Sopenharmony_ci         {.binding = 0,
946bf215546Sopenharmony_ci          .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
947bf215546Sopenharmony_ci          .descriptorCount = 1,
948bf215546Sopenharmony_ci          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
949bf215546Sopenharmony_ci          .pImmutableSamplers = NULL},
950bf215546Sopenharmony_ci      }};
951bf215546Sopenharmony_ci
952bf215546Sopenharmony_ci   result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device), &ds_layout_info,
953bf215546Sopenharmony_ci                                           &state->alloc, &state->clear_htile_mask_ds_layout);
954bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
955bf215546Sopenharmony_ci      goto fail;
956bf215546Sopenharmony_ci
957bf215546Sopenharmony_ci   VkPipelineLayoutCreateInfo p_layout_info = {
958bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
959bf215546Sopenharmony_ci      .setLayoutCount = 1,
960bf215546Sopenharmony_ci      .pSetLayouts = &state->clear_htile_mask_ds_layout,
961bf215546Sopenharmony_ci      .pushConstantRangeCount = 1,
962bf215546Sopenharmony_ci      .pPushConstantRanges =
963bf215546Sopenharmony_ci         &(VkPushConstantRange){
964bf215546Sopenharmony_ci            VK_SHADER_STAGE_COMPUTE_BIT,
965bf215546Sopenharmony_ci            0,
966bf215546Sopenharmony_ci            8,
967bf215546Sopenharmony_ci         },
968bf215546Sopenharmony_ci   };
969bf215546Sopenharmony_ci
970bf215546Sopenharmony_ci   result = radv_CreatePipelineLayout(radv_device_to_handle(device), &p_layout_info, &state->alloc,
971bf215546Sopenharmony_ci                                      &state->clear_htile_mask_p_layout);
972bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
973bf215546Sopenharmony_ci      goto fail;
974bf215546Sopenharmony_ci
975bf215546Sopenharmony_ci   VkPipelineShaderStageCreateInfo shader_stage = {
976bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
977bf215546Sopenharmony_ci      .stage = VK_SHADER_STAGE_COMPUTE_BIT,
978bf215546Sopenharmony_ci      .module = vk_shader_module_handle_from_nir(cs),
979bf215546Sopenharmony_ci      .pName = "main",
980bf215546Sopenharmony_ci      .pSpecializationInfo = NULL,
981bf215546Sopenharmony_ci   };
982bf215546Sopenharmony_ci
983bf215546Sopenharmony_ci   VkComputePipelineCreateInfo pipeline_info = {
984bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
985bf215546Sopenharmony_ci      .stage = shader_stage,
986bf215546Sopenharmony_ci      .flags = 0,
987bf215546Sopenharmony_ci      .layout = state->clear_htile_mask_p_layout,
988bf215546Sopenharmony_ci   };
989bf215546Sopenharmony_ci
990bf215546Sopenharmony_ci   result = radv_CreateComputePipelines(radv_device_to_handle(device),
991bf215546Sopenharmony_ci                                        radv_pipeline_cache_to_handle(&state->cache), 1,
992bf215546Sopenharmony_ci                                        &pipeline_info, NULL, &state->clear_htile_mask_pipeline);
993bf215546Sopenharmony_ci
994bf215546Sopenharmony_cifail:
995bf215546Sopenharmony_ci   ralloc_free(cs);
996bf215546Sopenharmony_ci   return result;
997bf215546Sopenharmony_ci}
998bf215546Sopenharmony_ci
999bf215546Sopenharmony_ci/* Clear DCC using comp-to-single by storing the clear value at the beginning of every 256B block.
1000bf215546Sopenharmony_ci * For MSAA images, clearing the first sample should be enough as long as CMASK is also cleared.
1001bf215546Sopenharmony_ci */
1002bf215546Sopenharmony_cistatic nir_shader *
1003bf215546Sopenharmony_cibuild_clear_dcc_comp_to_single_shader(struct radv_device *dev, bool is_msaa)
1004bf215546Sopenharmony_ci{
1005bf215546Sopenharmony_ci   enum glsl_sampler_dim dim = is_msaa ? GLSL_SAMPLER_DIM_MS : GLSL_SAMPLER_DIM_2D;
1006bf215546Sopenharmony_ci   const struct glsl_type *img_type = glsl_image_type(dim, true, GLSL_TYPE_FLOAT);
1007bf215546Sopenharmony_ci
1008bf215546Sopenharmony_ci   nir_builder b =
1009bf215546Sopenharmony_ci      radv_meta_init_shader(dev, MESA_SHADER_COMPUTE, "meta_clear_dcc_comp_to_single-%s",
1010bf215546Sopenharmony_ci                            is_msaa ? "multisampled" : "singlesampled");
1011bf215546Sopenharmony_ci   b.shader->info.workgroup_size[0] = 8;
1012bf215546Sopenharmony_ci   b.shader->info.workgroup_size[1] = 8;
1013bf215546Sopenharmony_ci
1014bf215546Sopenharmony_ci   nir_ssa_def *global_id = get_global_ids(&b, 3);
1015bf215546Sopenharmony_ci
1016bf215546Sopenharmony_ci   /* Load the dimensions in pixels of a block that gets compressed to one DCC byte. */
1017bf215546Sopenharmony_ci   nir_ssa_def *dcc_block_size = nir_load_push_constant(&b, 2, 32, nir_imm_int(&b, 0), .range = 8);
1018bf215546Sopenharmony_ci
1019bf215546Sopenharmony_ci   /* Compute the coordinates. */
1020bf215546Sopenharmony_ci   nir_ssa_def *coord = nir_channels(&b, global_id, 0x3);
1021bf215546Sopenharmony_ci   coord = nir_imul(&b, coord, dcc_block_size);
1022bf215546Sopenharmony_ci   coord = nir_vec4(&b, nir_channel(&b, coord, 0),
1023bf215546Sopenharmony_ci                        nir_channel(&b, coord, 1),
1024bf215546Sopenharmony_ci                        nir_channel(&b, global_id, 2),
1025bf215546Sopenharmony_ci                        nir_ssa_undef(&b, 1, 32));
1026bf215546Sopenharmony_ci
1027bf215546Sopenharmony_ci   nir_variable *output_img = nir_variable_create(b.shader, nir_var_image, img_type, "out_img");
1028bf215546Sopenharmony_ci   output_img->data.descriptor_set = 0;
1029bf215546Sopenharmony_ci   output_img->data.binding = 0;
1030bf215546Sopenharmony_ci
1031bf215546Sopenharmony_ci   /* Load the clear color values. */
1032bf215546Sopenharmony_ci   nir_ssa_def *clear_values = nir_load_push_constant(&b, 2, 32, nir_imm_int(&b, 8), .range = 8);
1033bf215546Sopenharmony_ci
1034bf215546Sopenharmony_ci   nir_ssa_def *data = nir_vec4(&b, nir_channel(&b, clear_values, 0),
1035bf215546Sopenharmony_ci                                    nir_channel(&b, clear_values, 1),
1036bf215546Sopenharmony_ci                                    nir_channel(&b, clear_values, 1),
1037bf215546Sopenharmony_ci                                    nir_channel(&b, clear_values, 1));
1038bf215546Sopenharmony_ci
1039bf215546Sopenharmony_ci   /* Store the clear color values. */
1040bf215546Sopenharmony_ci   nir_ssa_def *sample_id = is_msaa ? nir_imm_int(&b, 0) : nir_ssa_undef(&b, 1, 32);
1041bf215546Sopenharmony_ci   nir_image_deref_store(&b, &nir_build_deref_var(&b, output_img)->dest.ssa, coord,
1042bf215546Sopenharmony_ci                         sample_id, data, nir_imm_int(&b, 0),
1043bf215546Sopenharmony_ci                         .image_dim = dim, .image_array = true);
1044bf215546Sopenharmony_ci
1045bf215546Sopenharmony_ci   return b.shader;
1046bf215546Sopenharmony_ci}
1047bf215546Sopenharmony_ci
1048bf215546Sopenharmony_cistatic VkResult
1049bf215546Sopenharmony_cicreate_dcc_comp_to_single_pipeline(struct radv_device *device, bool is_msaa, VkPipeline *pipeline)
1050bf215546Sopenharmony_ci{
1051bf215546Sopenharmony_ci   struct radv_meta_state *state = &device->meta_state;
1052bf215546Sopenharmony_ci   VkResult result;
1053bf215546Sopenharmony_ci   nir_shader *cs = build_clear_dcc_comp_to_single_shader(device, is_msaa);
1054bf215546Sopenharmony_ci
1055bf215546Sopenharmony_ci   VkPipelineShaderStageCreateInfo shader_stage = {
1056bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1057bf215546Sopenharmony_ci      .stage = VK_SHADER_STAGE_COMPUTE_BIT,
1058bf215546Sopenharmony_ci      .module = vk_shader_module_handle_from_nir(cs),
1059bf215546Sopenharmony_ci      .pName = "main",
1060bf215546Sopenharmony_ci      .pSpecializationInfo = NULL,
1061bf215546Sopenharmony_ci   };
1062bf215546Sopenharmony_ci
1063bf215546Sopenharmony_ci   VkComputePipelineCreateInfo pipeline_info = {
1064bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1065bf215546Sopenharmony_ci      .stage = shader_stage,
1066bf215546Sopenharmony_ci      .flags = 0,
1067bf215546Sopenharmony_ci      .layout = state->clear_dcc_comp_to_single_p_layout,
1068bf215546Sopenharmony_ci   };
1069bf215546Sopenharmony_ci
1070bf215546Sopenharmony_ci   result = radv_CreateComputePipelines(radv_device_to_handle(device),
1071bf215546Sopenharmony_ci                                        radv_pipeline_cache_to_handle(&state->cache), 1,
1072bf215546Sopenharmony_ci                                        &pipeline_info, NULL, pipeline);
1073bf215546Sopenharmony_ci
1074bf215546Sopenharmony_ci   ralloc_free(cs);
1075bf215546Sopenharmony_ci   return result;
1076bf215546Sopenharmony_ci}
1077bf215546Sopenharmony_ci
1078bf215546Sopenharmony_cistatic VkResult
1079bf215546Sopenharmony_ciinit_meta_clear_dcc_comp_to_single_state(struct radv_device *device)
1080bf215546Sopenharmony_ci{
1081bf215546Sopenharmony_ci   struct radv_meta_state *state = &device->meta_state;
1082bf215546Sopenharmony_ci   VkResult result;
1083bf215546Sopenharmony_ci
1084bf215546Sopenharmony_ci   VkDescriptorSetLayoutCreateInfo ds_layout_info = {
1085bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
1086bf215546Sopenharmony_ci      .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
1087bf215546Sopenharmony_ci      .bindingCount = 1,
1088bf215546Sopenharmony_ci      .pBindings = (VkDescriptorSetLayoutBinding[]){
1089bf215546Sopenharmony_ci         {.binding = 0,
1090bf215546Sopenharmony_ci          .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
1091bf215546Sopenharmony_ci          .descriptorCount = 1,
1092bf215546Sopenharmony_ci          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
1093bf215546Sopenharmony_ci          .pImmutableSamplers = NULL},
1094bf215546Sopenharmony_ci      }};
1095bf215546Sopenharmony_ci
1096bf215546Sopenharmony_ci   result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device), &ds_layout_info,
1097bf215546Sopenharmony_ci                                           &state->alloc, &state->clear_dcc_comp_to_single_ds_layout);
1098bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1099bf215546Sopenharmony_ci      goto fail;
1100bf215546Sopenharmony_ci
1101bf215546Sopenharmony_ci   VkPipelineLayoutCreateInfo p_layout_info = {
1102bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1103bf215546Sopenharmony_ci      .setLayoutCount = 1,
1104bf215546Sopenharmony_ci      .pSetLayouts = &state->clear_dcc_comp_to_single_ds_layout,
1105bf215546Sopenharmony_ci      .pushConstantRangeCount = 1,
1106bf215546Sopenharmony_ci      .pPushConstantRanges =
1107bf215546Sopenharmony_ci         &(VkPushConstantRange){
1108bf215546Sopenharmony_ci            VK_SHADER_STAGE_COMPUTE_BIT,
1109bf215546Sopenharmony_ci            0,
1110bf215546Sopenharmony_ci            16,
1111bf215546Sopenharmony_ci         },
1112bf215546Sopenharmony_ci   };
1113bf215546Sopenharmony_ci
1114bf215546Sopenharmony_ci   result = radv_CreatePipelineLayout(radv_device_to_handle(device), &p_layout_info, &state->alloc,
1115bf215546Sopenharmony_ci                                      &state->clear_dcc_comp_to_single_p_layout);
1116bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1117bf215546Sopenharmony_ci      goto fail;
1118bf215546Sopenharmony_ci
1119bf215546Sopenharmony_ci   for (uint32_t i = 0; i < 2; i++) {
1120bf215546Sopenharmony_ci      result = create_dcc_comp_to_single_pipeline(device, !!i,
1121bf215546Sopenharmony_ci                                                  &state->clear_dcc_comp_to_single_pipeline[i]);
1122bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1123bf215546Sopenharmony_ci         goto fail;
1124bf215546Sopenharmony_ci   }
1125bf215546Sopenharmony_ci
1126bf215546Sopenharmony_cifail:
1127bf215546Sopenharmony_ci   return result;
1128bf215546Sopenharmony_ci}
1129bf215546Sopenharmony_ci
1130bf215546Sopenharmony_ciVkResult
1131bf215546Sopenharmony_ciradv_device_init_meta_clear_state(struct radv_device *device, bool on_demand)
1132bf215546Sopenharmony_ci{
1133bf215546Sopenharmony_ci   VkResult res;
1134bf215546Sopenharmony_ci   struct radv_meta_state *state = &device->meta_state;
1135bf215546Sopenharmony_ci
1136bf215546Sopenharmony_ci   VkPipelineLayoutCreateInfo pl_color_create_info = {
1137bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1138bf215546Sopenharmony_ci      .setLayoutCount = 0,
1139bf215546Sopenharmony_ci      .pushConstantRangeCount = 1,
1140bf215546Sopenharmony_ci      .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16},
1141bf215546Sopenharmony_ci   };
1142bf215546Sopenharmony_ci
1143bf215546Sopenharmony_ci   res = radv_CreatePipelineLayout(radv_device_to_handle(device), &pl_color_create_info,
1144bf215546Sopenharmony_ci                                   &device->meta_state.alloc,
1145bf215546Sopenharmony_ci                                   &device->meta_state.clear_color_p_layout);
1146bf215546Sopenharmony_ci   if (res != VK_SUCCESS)
1147bf215546Sopenharmony_ci      return res;
1148bf215546Sopenharmony_ci
1149bf215546Sopenharmony_ci   VkPipelineLayoutCreateInfo pl_depth_create_info = {
1150bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1151bf215546Sopenharmony_ci      .setLayoutCount = 0,
1152bf215546Sopenharmony_ci      .pushConstantRangeCount = 1,
1153bf215546Sopenharmony_ci      .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_VERTEX_BIT, 0, 4},
1154bf215546Sopenharmony_ci   };
1155bf215546Sopenharmony_ci
1156bf215546Sopenharmony_ci   res = radv_CreatePipelineLayout(radv_device_to_handle(device), &pl_depth_create_info,
1157bf215546Sopenharmony_ci                                   &device->meta_state.alloc,
1158bf215546Sopenharmony_ci                                   &device->meta_state.clear_depth_p_layout);
1159bf215546Sopenharmony_ci   if (res != VK_SUCCESS)
1160bf215546Sopenharmony_ci      return res;
1161bf215546Sopenharmony_ci
1162bf215546Sopenharmony_ci   VkPipelineLayoutCreateInfo pl_depth_unrestricted_create_info = {
1163bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1164bf215546Sopenharmony_ci      .setLayoutCount = 0,
1165bf215546Sopenharmony_ci      .pushConstantRangeCount = 1,
1166bf215546Sopenharmony_ci      .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4},
1167bf215546Sopenharmony_ci   };
1168bf215546Sopenharmony_ci
1169bf215546Sopenharmony_ci   res = radv_CreatePipelineLayout(radv_device_to_handle(device),
1170bf215546Sopenharmony_ci                                   &pl_depth_unrestricted_create_info, &device->meta_state.alloc,
1171bf215546Sopenharmony_ci                                   &device->meta_state.clear_depth_unrestricted_p_layout);
1172bf215546Sopenharmony_ci   if (res != VK_SUCCESS)
1173bf215546Sopenharmony_ci      return res;
1174bf215546Sopenharmony_ci
1175bf215546Sopenharmony_ci   res = init_meta_clear_htile_mask_state(device);
1176bf215546Sopenharmony_ci   if (res != VK_SUCCESS)
1177bf215546Sopenharmony_ci      return res;
1178bf215546Sopenharmony_ci
1179bf215546Sopenharmony_ci   res = init_meta_clear_dcc_comp_to_single_state(device);
1180bf215546Sopenharmony_ci   if (res != VK_SUCCESS)
1181bf215546Sopenharmony_ci      return res;
1182bf215546Sopenharmony_ci
1183bf215546Sopenharmony_ci   if (on_demand)
1184bf215546Sopenharmony_ci      return VK_SUCCESS;
1185bf215546Sopenharmony_ci
1186bf215546Sopenharmony_ci   for (uint32_t i = 0; i < ARRAY_SIZE(state->color_clear); ++i) {
1187bf215546Sopenharmony_ci      uint32_t samples = 1 << i;
1188bf215546Sopenharmony_ci
1189bf215546Sopenharmony_ci      /* Only precompile meta pipelines for attachment 0 as other are uncommon. */
1190bf215546Sopenharmony_ci      for (uint32_t j = 0; j < NUM_META_FS_KEYS; ++j) {
1191bf215546Sopenharmony_ci         VkFormat format = radv_fs_key_format_exemplars[j];
1192bf215546Sopenharmony_ci         unsigned fs_key = radv_format_meta_fs_key(device, format);
1193bf215546Sopenharmony_ci         assert(!state->color_clear[i][0].color_pipelines[fs_key]);
1194bf215546Sopenharmony_ci
1195bf215546Sopenharmony_ci         res = create_color_pipeline(device, samples, 0, format,
1196bf215546Sopenharmony_ci                                     &state->color_clear[i][0].color_pipelines[fs_key]);
1197bf215546Sopenharmony_ci         if (res != VK_SUCCESS)
1198bf215546Sopenharmony_ci            return res;
1199bf215546Sopenharmony_ci      }
1200bf215546Sopenharmony_ci   }
1201bf215546Sopenharmony_ci   for (uint32_t i = 0; i < ARRAY_SIZE(state->ds_clear); ++i) {
1202bf215546Sopenharmony_ci      uint32_t samples = 1 << i;
1203bf215546Sopenharmony_ci
1204bf215546Sopenharmony_ci      for (uint32_t j = 0; j < NUM_DEPTH_CLEAR_PIPELINES; j++) {
1205bf215546Sopenharmony_ci         res = create_depthstencil_pipeline(device, VK_IMAGE_ASPECT_DEPTH_BIT, samples, j, false,
1206bf215546Sopenharmony_ci                                            &state->ds_clear[i].depth_only_pipeline[j]);
1207bf215546Sopenharmony_ci         if (res != VK_SUCCESS)
1208bf215546Sopenharmony_ci            return res;
1209bf215546Sopenharmony_ci
1210bf215546Sopenharmony_ci         res = create_depthstencil_pipeline(device, VK_IMAGE_ASPECT_STENCIL_BIT, samples, j, false,
1211bf215546Sopenharmony_ci                                            &state->ds_clear[i].stencil_only_pipeline[j]);
1212bf215546Sopenharmony_ci         if (res != VK_SUCCESS)
1213bf215546Sopenharmony_ci            return res;
1214bf215546Sopenharmony_ci
1215bf215546Sopenharmony_ci         res = create_depthstencil_pipeline(
1216bf215546Sopenharmony_ci            device, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, samples, j, false,
1217bf215546Sopenharmony_ci            &state->ds_clear[i].depthstencil_pipeline[j]);
1218bf215546Sopenharmony_ci         if (res != VK_SUCCESS)
1219bf215546Sopenharmony_ci            return res;
1220bf215546Sopenharmony_ci
1221bf215546Sopenharmony_ci         res = create_depthstencil_pipeline(device, VK_IMAGE_ASPECT_DEPTH_BIT, samples, j, true,
1222bf215546Sopenharmony_ci                                            &state->ds_clear[i].depth_only_unrestricted_pipeline[j]);
1223bf215546Sopenharmony_ci         if (res != VK_SUCCESS)
1224bf215546Sopenharmony_ci            return res;
1225bf215546Sopenharmony_ci
1226bf215546Sopenharmony_ci         res =
1227bf215546Sopenharmony_ci            create_depthstencil_pipeline(device, VK_IMAGE_ASPECT_STENCIL_BIT, samples, j, true,
1228bf215546Sopenharmony_ci                                         &state->ds_clear[i].stencil_only_unrestricted_pipeline[j]);
1229bf215546Sopenharmony_ci         if (res != VK_SUCCESS)
1230bf215546Sopenharmony_ci            return res;
1231bf215546Sopenharmony_ci
1232bf215546Sopenharmony_ci         res = create_depthstencil_pipeline(
1233bf215546Sopenharmony_ci            device, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, samples, j, true,
1234bf215546Sopenharmony_ci            &state->ds_clear[i].depthstencil_unrestricted_pipeline[j]);
1235bf215546Sopenharmony_ci         if (res != VK_SUCCESS)
1236bf215546Sopenharmony_ci            return res;
1237bf215546Sopenharmony_ci      }
1238bf215546Sopenharmony_ci   }
1239bf215546Sopenharmony_ci   return VK_SUCCESS;
1240bf215546Sopenharmony_ci}
1241bf215546Sopenharmony_ci
1242bf215546Sopenharmony_cistatic uint32_t
1243bf215546Sopenharmony_ciradv_get_cmask_fast_clear_value(const struct radv_image *image)
1244bf215546Sopenharmony_ci{
1245bf215546Sopenharmony_ci   uint32_t value = 0; /* Default value when no DCC. */
1246bf215546Sopenharmony_ci
1247bf215546Sopenharmony_ci   /* The fast-clear value is different for images that have both DCC and
1248bf215546Sopenharmony_ci    * CMASK metadata.
1249bf215546Sopenharmony_ci    */
1250bf215546Sopenharmony_ci   if (radv_image_has_dcc(image)) {
1251bf215546Sopenharmony_ci      /* DCC fast clear with MSAA should clear CMASK to 0xC. */
1252bf215546Sopenharmony_ci      return image->info.samples > 1 ? 0xcccccccc : 0xffffffff;
1253bf215546Sopenharmony_ci   }
1254bf215546Sopenharmony_ci
1255bf215546Sopenharmony_ci   return value;
1256bf215546Sopenharmony_ci}
1257bf215546Sopenharmony_ci
1258bf215546Sopenharmony_ciuint32_t
1259bf215546Sopenharmony_ciradv_clear_cmask(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
1260bf215546Sopenharmony_ci                 const VkImageSubresourceRange *range, uint32_t value)
1261bf215546Sopenharmony_ci{
1262bf215546Sopenharmony_ci   uint64_t offset = image->bindings[0].offset + image->planes[0].surface.cmask_offset;
1263bf215546Sopenharmony_ci   uint64_t size;
1264bf215546Sopenharmony_ci
1265bf215546Sopenharmony_ci   if (cmd_buffer->device->physical_device->rad_info.gfx_level == GFX9) {
1266bf215546Sopenharmony_ci      /* TODO: clear layers. */
1267bf215546Sopenharmony_ci      size = image->planes[0].surface.cmask_size;
1268bf215546Sopenharmony_ci   } else {
1269bf215546Sopenharmony_ci      unsigned slice_size = image->planes[0].surface.cmask_slice_size;
1270bf215546Sopenharmony_ci
1271bf215546Sopenharmony_ci      offset += slice_size * range->baseArrayLayer;
1272bf215546Sopenharmony_ci      size = slice_size * radv_get_layerCount(image, range);
1273bf215546Sopenharmony_ci   }
1274bf215546Sopenharmony_ci
1275bf215546Sopenharmony_ci   return radv_fill_buffer(cmd_buffer, image, image->bindings[0].bo,
1276bf215546Sopenharmony_ci         radv_buffer_get_va(image->bindings[0].bo) + offset, size, value);
1277bf215546Sopenharmony_ci}
1278bf215546Sopenharmony_ci
1279bf215546Sopenharmony_ciuint32_t
1280bf215546Sopenharmony_ciradv_clear_fmask(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
1281bf215546Sopenharmony_ci                 const VkImageSubresourceRange *range, uint32_t value)
1282bf215546Sopenharmony_ci{
1283bf215546Sopenharmony_ci   uint64_t offset = image->bindings[0].offset + image->planes[0].surface.fmask_offset;
1284bf215546Sopenharmony_ci   unsigned slice_size = image->planes[0].surface.fmask_slice_size;
1285bf215546Sopenharmony_ci   uint64_t size;
1286bf215546Sopenharmony_ci
1287bf215546Sopenharmony_ci   /* MSAA images do not support mipmap levels. */
1288bf215546Sopenharmony_ci   assert(range->baseMipLevel == 0 && radv_get_levelCount(image, range) == 1);
1289bf215546Sopenharmony_ci
1290bf215546Sopenharmony_ci   offset += slice_size * range->baseArrayLayer;
1291bf215546Sopenharmony_ci   size = slice_size * radv_get_layerCount(image, range);
1292bf215546Sopenharmony_ci
1293bf215546Sopenharmony_ci   return radv_fill_buffer(cmd_buffer, image, image->bindings[0].bo,
1294bf215546Sopenharmony_ci         radv_buffer_get_va(image->bindings[0].bo) + offset, size, value);
1295bf215546Sopenharmony_ci}
1296bf215546Sopenharmony_ci
1297bf215546Sopenharmony_ciuint32_t
1298bf215546Sopenharmony_ciradv_clear_dcc(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
1299bf215546Sopenharmony_ci               const VkImageSubresourceRange *range, uint32_t value)
1300bf215546Sopenharmony_ci{
1301bf215546Sopenharmony_ci   uint32_t level_count = radv_get_levelCount(image, range);
1302bf215546Sopenharmony_ci   uint32_t layer_count = radv_get_layerCount(image, range);
1303bf215546Sopenharmony_ci   uint32_t flush_bits = 0;
1304bf215546Sopenharmony_ci
1305bf215546Sopenharmony_ci   /* Mark the image as being compressed. */
1306bf215546Sopenharmony_ci   radv_update_dcc_metadata(cmd_buffer, image, range, true);
1307bf215546Sopenharmony_ci
1308bf215546Sopenharmony_ci   for (uint32_t l = 0; l < level_count; l++) {
1309bf215546Sopenharmony_ci      uint64_t offset = image->bindings[0].offset + image->planes[0].surface.meta_offset;
1310bf215546Sopenharmony_ci      uint32_t level = range->baseMipLevel + l;
1311bf215546Sopenharmony_ci      uint64_t size;
1312bf215546Sopenharmony_ci
1313bf215546Sopenharmony_ci      if (cmd_buffer->device->physical_device->rad_info.gfx_level >= GFX10) {
1314bf215546Sopenharmony_ci         /* DCC for mipmaps+layers is currently disabled. */
1315bf215546Sopenharmony_ci         offset += image->planes[0].surface.meta_slice_size * range->baseArrayLayer +
1316bf215546Sopenharmony_ci                   image->planes[0].surface.u.gfx9.meta_levels[level].offset;
1317bf215546Sopenharmony_ci         size = image->planes[0].surface.u.gfx9.meta_levels[level].size * layer_count;
1318bf215546Sopenharmony_ci      } else if (cmd_buffer->device->physical_device->rad_info.gfx_level == GFX9) {
1319bf215546Sopenharmony_ci         /* Mipmap levels and layers aren't implemented. */
1320bf215546Sopenharmony_ci         assert(level == 0);
1321bf215546Sopenharmony_ci         size = image->planes[0].surface.meta_size;
1322bf215546Sopenharmony_ci      } else {
1323bf215546Sopenharmony_ci         const struct legacy_surf_dcc_level *dcc_level =
1324bf215546Sopenharmony_ci            &image->planes[0].surface.u.legacy.color.dcc_level[level];
1325bf215546Sopenharmony_ci
1326bf215546Sopenharmony_ci         /* If dcc_fast_clear_size is 0 (which might happens for
1327bf215546Sopenharmony_ci          * mipmaps) the fill buffer operation below is a no-op.
1328bf215546Sopenharmony_ci          * This can only happen during initialization as the
1329bf215546Sopenharmony_ci          * fast clear path fallbacks to slow clears if one
1330bf215546Sopenharmony_ci          * level can't be fast cleared.
1331bf215546Sopenharmony_ci          */
1332bf215546Sopenharmony_ci         offset +=
1333bf215546Sopenharmony_ci            dcc_level->dcc_offset + dcc_level->dcc_slice_fast_clear_size * range->baseArrayLayer;
1334bf215546Sopenharmony_ci         size = dcc_level->dcc_slice_fast_clear_size * radv_get_layerCount(image, range);
1335bf215546Sopenharmony_ci      }
1336bf215546Sopenharmony_ci
1337bf215546Sopenharmony_ci      /* Do not clear this level if it can't be compressed. */
1338bf215546Sopenharmony_ci      if (!size)
1339bf215546Sopenharmony_ci         continue;
1340bf215546Sopenharmony_ci
1341bf215546Sopenharmony_ci      flush_bits |= radv_fill_buffer(cmd_buffer, image, image->bindings[0].bo,
1342bf215546Sopenharmony_ci                                     radv_buffer_get_va(image->bindings[0].bo) + offset,
1343bf215546Sopenharmony_ci                                     size, value);
1344bf215546Sopenharmony_ci   }
1345bf215546Sopenharmony_ci
1346bf215546Sopenharmony_ci   return flush_bits;
1347bf215546Sopenharmony_ci}
1348bf215546Sopenharmony_ci
1349bf215546Sopenharmony_cistatic uint32_t
1350bf215546Sopenharmony_ciradv_clear_dcc_comp_to_single(struct radv_cmd_buffer *cmd_buffer,
1351bf215546Sopenharmony_ci                              struct radv_image *image,
1352bf215546Sopenharmony_ci                              const VkImageSubresourceRange *range,
1353bf215546Sopenharmony_ci                              uint32_t color_values[2])
1354bf215546Sopenharmony_ci{
1355bf215546Sopenharmony_ci   struct radv_device *device = cmd_buffer->device;
1356bf215546Sopenharmony_ci   unsigned bytes_per_pixel = vk_format_get_blocksize(image->vk.format);
1357bf215546Sopenharmony_ci   unsigned layer_count = radv_get_layerCount(image, range);
1358bf215546Sopenharmony_ci   struct radv_meta_saved_state saved_state;
1359bf215546Sopenharmony_ci   bool is_msaa = image->info.samples > 1;
1360bf215546Sopenharmony_ci   struct radv_image_view iview;
1361bf215546Sopenharmony_ci   VkFormat format;
1362bf215546Sopenharmony_ci
1363bf215546Sopenharmony_ci   switch (bytes_per_pixel) {
1364bf215546Sopenharmony_ci   case 1:
1365bf215546Sopenharmony_ci      format = VK_FORMAT_R8_UINT;
1366bf215546Sopenharmony_ci      break;
1367bf215546Sopenharmony_ci   case 2:
1368bf215546Sopenharmony_ci      format = VK_FORMAT_R16_UINT;
1369bf215546Sopenharmony_ci      break;
1370bf215546Sopenharmony_ci   case 4:
1371bf215546Sopenharmony_ci      format = VK_FORMAT_R32_UINT;
1372bf215546Sopenharmony_ci      break;
1373bf215546Sopenharmony_ci   case 8:
1374bf215546Sopenharmony_ci      format = VK_FORMAT_R32G32_UINT;
1375bf215546Sopenharmony_ci      break;
1376bf215546Sopenharmony_ci   case 16:
1377bf215546Sopenharmony_ci      format = VK_FORMAT_R32G32B32A32_UINT;
1378bf215546Sopenharmony_ci      break;
1379bf215546Sopenharmony_ci   default:
1380bf215546Sopenharmony_ci      unreachable("Unsupported number of bytes per pixel");
1381bf215546Sopenharmony_ci   }
1382bf215546Sopenharmony_ci
1383bf215546Sopenharmony_ci   radv_meta_save(
1384bf215546Sopenharmony_ci      &saved_state, cmd_buffer,
1385bf215546Sopenharmony_ci      RADV_META_SAVE_DESCRIPTORS | RADV_META_SAVE_COMPUTE_PIPELINE | RADV_META_SAVE_CONSTANTS);
1386bf215546Sopenharmony_ci
1387bf215546Sopenharmony_ci   VkPipeline pipeline = device->meta_state.clear_dcc_comp_to_single_pipeline[is_msaa];
1388bf215546Sopenharmony_ci
1389bf215546Sopenharmony_ci   radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE,
1390bf215546Sopenharmony_ci                        pipeline);
1391bf215546Sopenharmony_ci
1392bf215546Sopenharmony_ci   for (uint32_t l = 0; l < radv_get_levelCount(image, range); l++) {
1393bf215546Sopenharmony_ci      uint32_t width, height;
1394bf215546Sopenharmony_ci
1395bf215546Sopenharmony_ci      /* Do not write the clear color value for levels without DCC. */
1396bf215546Sopenharmony_ci      if (!radv_dcc_enabled(image, range->baseMipLevel + l))
1397bf215546Sopenharmony_ci         continue;
1398bf215546Sopenharmony_ci
1399bf215546Sopenharmony_ci      width = radv_minify(image->info.width, range->baseMipLevel + l);
1400bf215546Sopenharmony_ci      height = radv_minify(image->info.height, range->baseMipLevel + l);
1401bf215546Sopenharmony_ci
1402bf215546Sopenharmony_ci      radv_image_view_init(
1403bf215546Sopenharmony_ci         &iview, cmd_buffer->device,
1404bf215546Sopenharmony_ci         &(VkImageViewCreateInfo){
1405bf215546Sopenharmony_ci            .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
1406bf215546Sopenharmony_ci            .image = radv_image_to_handle(image),
1407bf215546Sopenharmony_ci            .viewType = VK_IMAGE_VIEW_TYPE_2D,
1408bf215546Sopenharmony_ci            .format = format,
1409bf215546Sopenharmony_ci            .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1410bf215546Sopenharmony_ci                                 .baseMipLevel = range->baseMipLevel + l,
1411bf215546Sopenharmony_ci                                 .levelCount = 1,
1412bf215546Sopenharmony_ci                                 .baseArrayLayer = range->baseArrayLayer,
1413bf215546Sopenharmony_ci                                 .layerCount = layer_count},
1414bf215546Sopenharmony_ci         },
1415bf215546Sopenharmony_ci         0, &(struct radv_image_view_extra_create_info){.disable_compression = true});
1416bf215546Sopenharmony_ci
1417bf215546Sopenharmony_ci      radv_meta_push_descriptor_set(
1418bf215546Sopenharmony_ci         cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE,
1419bf215546Sopenharmony_ci         device->meta_state.clear_dcc_comp_to_single_p_layout, 0,
1420bf215546Sopenharmony_ci         1,
1421bf215546Sopenharmony_ci         (VkWriteDescriptorSet[]){{.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1422bf215546Sopenharmony_ci                                   .dstBinding = 0,
1423bf215546Sopenharmony_ci                                   .dstArrayElement = 0,
1424bf215546Sopenharmony_ci                                   .descriptorCount = 1,
1425bf215546Sopenharmony_ci                                   .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
1426bf215546Sopenharmony_ci                                   .pImageInfo =
1427bf215546Sopenharmony_ci                                      (VkDescriptorImageInfo[]){
1428bf215546Sopenharmony_ci                                         {
1429bf215546Sopenharmony_ci                                            .sampler = VK_NULL_HANDLE,
1430bf215546Sopenharmony_ci                                            .imageView = radv_image_view_to_handle(&iview),
1431bf215546Sopenharmony_ci                                            .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
1432bf215546Sopenharmony_ci                                         },
1433bf215546Sopenharmony_ci                                      }}});
1434bf215546Sopenharmony_ci
1435bf215546Sopenharmony_ci      unsigned dcc_width =
1436bf215546Sopenharmony_ci         DIV_ROUND_UP(width, image->planes[0].surface.u.gfx9.color.dcc_block_width);
1437bf215546Sopenharmony_ci      unsigned dcc_height =
1438bf215546Sopenharmony_ci         DIV_ROUND_UP(height, image->planes[0].surface.u.gfx9.color.dcc_block_height);
1439bf215546Sopenharmony_ci
1440bf215546Sopenharmony_ci      const unsigned constants[4] = {
1441bf215546Sopenharmony_ci         image->planes[0].surface.u.gfx9.color.dcc_block_width,
1442bf215546Sopenharmony_ci         image->planes[0].surface.u.gfx9.color.dcc_block_height,
1443bf215546Sopenharmony_ci         color_values[0],
1444bf215546Sopenharmony_ci         color_values[1],
1445bf215546Sopenharmony_ci      };
1446bf215546Sopenharmony_ci
1447bf215546Sopenharmony_ci      radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
1448bf215546Sopenharmony_ci                            device->meta_state.clear_dcc_comp_to_single_p_layout,
1449bf215546Sopenharmony_ci                            VK_SHADER_STAGE_COMPUTE_BIT, 0, 16, constants);
1450bf215546Sopenharmony_ci
1451bf215546Sopenharmony_ci      radv_unaligned_dispatch(cmd_buffer, dcc_width, dcc_height, layer_count);
1452bf215546Sopenharmony_ci
1453bf215546Sopenharmony_ci      radv_image_view_finish(&iview);
1454bf215546Sopenharmony_ci   }
1455bf215546Sopenharmony_ci
1456bf215546Sopenharmony_ci   radv_meta_restore(&saved_state, cmd_buffer);
1457bf215546Sopenharmony_ci
1458bf215546Sopenharmony_ci   return RADV_CMD_FLAG_CS_PARTIAL_FLUSH |
1459bf215546Sopenharmony_ci          radv_src_access_flush(cmd_buffer, VK_ACCESS_2_SHADER_WRITE_BIT, image);
1460bf215546Sopenharmony_ci}
1461bf215546Sopenharmony_ci
1462bf215546Sopenharmony_ciuint32_t
1463bf215546Sopenharmony_ciradv_clear_htile(struct radv_cmd_buffer *cmd_buffer, const struct radv_image *image,
1464bf215546Sopenharmony_ci                 const VkImageSubresourceRange *range, uint32_t value)
1465bf215546Sopenharmony_ci{
1466bf215546Sopenharmony_ci   uint32_t level_count = radv_get_levelCount(image, range);
1467bf215546Sopenharmony_ci   uint32_t flush_bits = 0;
1468bf215546Sopenharmony_ci   uint32_t htile_mask;
1469bf215546Sopenharmony_ci
1470bf215546Sopenharmony_ci   htile_mask = radv_get_htile_mask(cmd_buffer->device, image, range->aspectMask);
1471bf215546Sopenharmony_ci
1472bf215546Sopenharmony_ci   if (level_count != image->info.levels) {
1473bf215546Sopenharmony_ci      assert(cmd_buffer->device->physical_device->rad_info.gfx_level >= GFX10);
1474bf215546Sopenharmony_ci
1475bf215546Sopenharmony_ci      /* Clear individuals levels separately. */
1476bf215546Sopenharmony_ci      for (uint32_t l = 0; l < level_count; l++) {
1477bf215546Sopenharmony_ci         uint32_t level = range->baseMipLevel + l;
1478bf215546Sopenharmony_ci         uint64_t offset = image->bindings[0].offset + image->planes[0].surface.meta_offset +
1479bf215546Sopenharmony_ci                           image->planes[0].surface.u.gfx9.meta_levels[level].offset;
1480bf215546Sopenharmony_ci         uint32_t size = image->planes[0].surface.u.gfx9.meta_levels[level].size;
1481bf215546Sopenharmony_ci
1482bf215546Sopenharmony_ci         /* Do not clear this level if it can be compressed. */
1483bf215546Sopenharmony_ci         if (!size)
1484bf215546Sopenharmony_ci            continue;
1485bf215546Sopenharmony_ci
1486bf215546Sopenharmony_ci         if (htile_mask == UINT_MAX) {
1487bf215546Sopenharmony_ci            /* Clear the whole HTILE buffer. */
1488bf215546Sopenharmony_ci            flush_bits |= radv_fill_buffer(cmd_buffer, image, image->bindings[0].bo,
1489bf215546Sopenharmony_ci                                           radv_buffer_get_va(image->bindings[0].bo) + offset,
1490bf215546Sopenharmony_ci                                           size, value);
1491bf215546Sopenharmony_ci         } else {
1492bf215546Sopenharmony_ci            /* Only clear depth or stencil bytes in the HTILE buffer. */
1493bf215546Sopenharmony_ci            flush_bits |=
1494bf215546Sopenharmony_ci               clear_htile_mask(cmd_buffer, image, image->bindings[0].bo, offset, size, value, htile_mask);
1495bf215546Sopenharmony_ci         }
1496bf215546Sopenharmony_ci      }
1497bf215546Sopenharmony_ci   } else {
1498bf215546Sopenharmony_ci      unsigned layer_count = radv_get_layerCount(image, range);
1499bf215546Sopenharmony_ci      uint64_t size = image->planes[0].surface.meta_slice_size * layer_count;
1500bf215546Sopenharmony_ci      uint64_t offset = image->bindings[0].offset + image->planes[0].surface.meta_offset +
1501bf215546Sopenharmony_ci                        image->planes[0].surface.meta_slice_size * range->baseArrayLayer;
1502bf215546Sopenharmony_ci
1503bf215546Sopenharmony_ci      if (htile_mask == UINT_MAX) {
1504bf215546Sopenharmony_ci         /* Clear the whole HTILE buffer. */
1505bf215546Sopenharmony_ci         flush_bits = radv_fill_buffer(cmd_buffer, image, image->bindings[0].bo,
1506bf215546Sopenharmony_ci                                       radv_buffer_get_va(image->bindings[0].bo) + offset,
1507bf215546Sopenharmony_ci                                       size, value);
1508bf215546Sopenharmony_ci      } else {
1509bf215546Sopenharmony_ci         /* Only clear depth or stencil bytes in the HTILE buffer. */
1510bf215546Sopenharmony_ci         flush_bits =
1511bf215546Sopenharmony_ci            clear_htile_mask(cmd_buffer, image, image->bindings[0].bo, offset, size, value, htile_mask);
1512bf215546Sopenharmony_ci      }
1513bf215546Sopenharmony_ci   }
1514bf215546Sopenharmony_ci
1515bf215546Sopenharmony_ci   return flush_bits;
1516bf215546Sopenharmony_ci}
1517bf215546Sopenharmony_ci
1518bf215546Sopenharmony_cienum {
1519bf215546Sopenharmony_ci   RADV_DCC_CLEAR_0000 = 0x00000000U,
1520bf215546Sopenharmony_ci   RADV_DCC_GFX8_CLEAR_0001 = 0x40404040U,
1521bf215546Sopenharmony_ci   RADV_DCC_GFX8_CLEAR_1110 = 0x80808080U,
1522bf215546Sopenharmony_ci   RADV_DCC_GFX8_CLEAR_1111 = 0xC0C0C0C0U,
1523bf215546Sopenharmony_ci   RADV_DCC_GFX8_CLEAR_REG = 0x20202020U,
1524bf215546Sopenharmony_ci   RADV_DCC_GFX9_CLEAR_SINGLE = 0x10101010U,
1525bf215546Sopenharmony_ci   RADV_DCC_GFX11_CLEAR_SINGLE = 0x01010101U,
1526bf215546Sopenharmony_ci   RADV_DCC_GFX11_CLEAR_0000 = 0x00000000U,
1527bf215546Sopenharmony_ci   RADV_DCC_GFX11_CLEAR_1111_UNORM = 0x02020202U,
1528bf215546Sopenharmony_ci   RADV_DCC_GFX11_CLEAR_1111_FP16 = 0x04040404U,
1529bf215546Sopenharmony_ci   RADV_DCC_GFX11_CLEAR_1111_FP32 = 0x06060606U,
1530bf215546Sopenharmony_ci   RADV_DCC_GFX11_CLEAR_0001_UNORM = 0x08080808U,
1531bf215546Sopenharmony_ci   RADV_DCC_GFX11_CLEAR_1110_UNORM = 0x0A0A0A0AU,
1532bf215546Sopenharmony_ci};
1533bf215546Sopenharmony_ci
1534bf215546Sopenharmony_cistatic uint32_t
1535bf215546Sopenharmony_ciradv_dcc_single_clear_value(const struct radv_device *device)
1536bf215546Sopenharmony_ci{
1537bf215546Sopenharmony_ci   return device->physical_device->rad_info.gfx_level >= GFX11 ? RADV_DCC_GFX11_CLEAR_SINGLE
1538bf215546Sopenharmony_ci                                                               : RADV_DCC_GFX9_CLEAR_SINGLE;
1539bf215546Sopenharmony_ci}
1540bf215546Sopenharmony_ci
1541bf215546Sopenharmony_cistatic void
1542bf215546Sopenharmony_cigfx8_get_fast_clear_parameters(struct radv_device *device, const struct radv_image_view *iview,
1543bf215546Sopenharmony_ci                               const VkClearColorValue *clear_value, uint32_t *reset_value,
1544bf215546Sopenharmony_ci                               bool *can_avoid_fast_clear_elim)
1545bf215546Sopenharmony_ci{
1546bf215546Sopenharmony_ci   bool values[4] = {0};
1547bf215546Sopenharmony_ci   int extra_channel;
1548bf215546Sopenharmony_ci   bool main_value = false;
1549bf215546Sopenharmony_ci   bool extra_value = false;
1550bf215546Sopenharmony_ci   bool has_color = false;
1551bf215546Sopenharmony_ci   bool has_alpha = false;
1552bf215546Sopenharmony_ci
1553bf215546Sopenharmony_ci   /* comp-to-single allows to perform DCC fast clears without requiring a FCE. */
1554bf215546Sopenharmony_ci   if (iview->image->support_comp_to_single) {
1555bf215546Sopenharmony_ci      *reset_value = RADV_DCC_GFX9_CLEAR_SINGLE;
1556bf215546Sopenharmony_ci      *can_avoid_fast_clear_elim = true;
1557bf215546Sopenharmony_ci   } else {
1558bf215546Sopenharmony_ci      *reset_value = RADV_DCC_GFX8_CLEAR_REG;
1559bf215546Sopenharmony_ci      *can_avoid_fast_clear_elim = false;
1560bf215546Sopenharmony_ci   }
1561bf215546Sopenharmony_ci
1562bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(iview->vk.format);
1563bf215546Sopenharmony_ci   if (iview->vk.format == VK_FORMAT_B10G11R11_UFLOAT_PACK32 ||
1564bf215546Sopenharmony_ci       iview->vk.format == VK_FORMAT_R5G6B5_UNORM_PACK16 || iview->vk.format == VK_FORMAT_B5G6R5_UNORM_PACK16)
1565bf215546Sopenharmony_ci      extra_channel = -1;
1566bf215546Sopenharmony_ci   else if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN) {
1567bf215546Sopenharmony_ci      if (vi_alpha_is_on_msb(device, iview->vk.format))
1568bf215546Sopenharmony_ci         extra_channel = desc->nr_channels - 1;
1569bf215546Sopenharmony_ci      else
1570bf215546Sopenharmony_ci         extra_channel = 0;
1571bf215546Sopenharmony_ci   } else
1572bf215546Sopenharmony_ci      return;
1573bf215546Sopenharmony_ci
1574bf215546Sopenharmony_ci   for (int i = 0; i < 4; i++) {
1575bf215546Sopenharmony_ci      int index = desc->swizzle[i] - PIPE_SWIZZLE_X;
1576bf215546Sopenharmony_ci      if (desc->swizzle[i] < PIPE_SWIZZLE_X || desc->swizzle[i] > PIPE_SWIZZLE_W)
1577bf215546Sopenharmony_ci         continue;
1578bf215546Sopenharmony_ci
1579bf215546Sopenharmony_ci      if (desc->channel[i].pure_integer && desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
1580bf215546Sopenharmony_ci         /* Use the maximum value for clamping the clear color. */
1581bf215546Sopenharmony_ci         int max = u_bit_consecutive(0, desc->channel[i].size - 1);
1582bf215546Sopenharmony_ci
1583bf215546Sopenharmony_ci         values[i] = clear_value->int32[i] != 0;
1584bf215546Sopenharmony_ci         if (clear_value->int32[i] != 0 && MIN2(clear_value->int32[i], max) != max)
1585bf215546Sopenharmony_ci            return;
1586bf215546Sopenharmony_ci      } else if (desc->channel[i].pure_integer &&
1587bf215546Sopenharmony_ci                 desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) {
1588bf215546Sopenharmony_ci         /* Use the maximum value for clamping the clear color. */
1589bf215546Sopenharmony_ci         unsigned max = u_bit_consecutive(0, desc->channel[i].size);
1590bf215546Sopenharmony_ci
1591bf215546Sopenharmony_ci         values[i] = clear_value->uint32[i] != 0U;
1592bf215546Sopenharmony_ci         if (clear_value->uint32[i] != 0U && MIN2(clear_value->uint32[i], max) != max)
1593bf215546Sopenharmony_ci            return;
1594bf215546Sopenharmony_ci      } else {
1595bf215546Sopenharmony_ci         values[i] = clear_value->float32[i] != 0.0F;
1596bf215546Sopenharmony_ci         if (clear_value->float32[i] != 0.0F && clear_value->float32[i] != 1.0F)
1597bf215546Sopenharmony_ci            return;
1598bf215546Sopenharmony_ci      }
1599bf215546Sopenharmony_ci
1600bf215546Sopenharmony_ci      if (index == extra_channel) {
1601bf215546Sopenharmony_ci         extra_value = values[i];
1602bf215546Sopenharmony_ci         has_alpha = true;
1603bf215546Sopenharmony_ci      } else {
1604bf215546Sopenharmony_ci         main_value = values[i];
1605bf215546Sopenharmony_ci         has_color = true;
1606bf215546Sopenharmony_ci      }
1607bf215546Sopenharmony_ci   }
1608bf215546Sopenharmony_ci
1609bf215546Sopenharmony_ci   /* If alpha isn't present, make it the same as color, and vice versa. */
1610bf215546Sopenharmony_ci   if (!has_alpha)
1611bf215546Sopenharmony_ci      extra_value = main_value;
1612bf215546Sopenharmony_ci   else if (!has_color)
1613bf215546Sopenharmony_ci      main_value = extra_value;
1614bf215546Sopenharmony_ci
1615bf215546Sopenharmony_ci   for (int i = 0; i < 4; ++i)
1616bf215546Sopenharmony_ci      if (values[i] != main_value && desc->swizzle[i] - PIPE_SWIZZLE_X != extra_channel &&
1617bf215546Sopenharmony_ci          desc->swizzle[i] >= PIPE_SWIZZLE_X && desc->swizzle[i] <= PIPE_SWIZZLE_W)
1618bf215546Sopenharmony_ci         return;
1619bf215546Sopenharmony_ci
1620bf215546Sopenharmony_ci   /* Only DCC clear code 0000 is allowed for signed<->unsigned formats. */
1621bf215546Sopenharmony_ci   if ((main_value || extra_value) && iview->image->dcc_sign_reinterpret)
1622bf215546Sopenharmony_ci      return;
1623bf215546Sopenharmony_ci
1624bf215546Sopenharmony_ci   *can_avoid_fast_clear_elim = true;
1625bf215546Sopenharmony_ci
1626bf215546Sopenharmony_ci   if (main_value) {
1627bf215546Sopenharmony_ci      if (extra_value)
1628bf215546Sopenharmony_ci         *reset_value = RADV_DCC_GFX8_CLEAR_1111;
1629bf215546Sopenharmony_ci      else
1630bf215546Sopenharmony_ci         *reset_value = RADV_DCC_GFX8_CLEAR_1110;
1631bf215546Sopenharmony_ci   } else {
1632bf215546Sopenharmony_ci      if (extra_value)
1633bf215546Sopenharmony_ci         *reset_value = RADV_DCC_GFX8_CLEAR_0001;
1634bf215546Sopenharmony_ci      else
1635bf215546Sopenharmony_ci         *reset_value = RADV_DCC_CLEAR_0000;
1636bf215546Sopenharmony_ci   }
1637bf215546Sopenharmony_ci}
1638bf215546Sopenharmony_ci
1639bf215546Sopenharmony_cistatic bool
1640bf215546Sopenharmony_cigfx11_get_fast_clear_parameters(struct radv_device *device, const struct radv_image_view *iview,
1641bf215546Sopenharmony_ci                                const VkClearColorValue *clear_value, uint32_t *reset_value)
1642bf215546Sopenharmony_ci{
1643bf215546Sopenharmony_ci   int extra_channel;
1644bf215546Sopenharmony_ci
1645bf215546Sopenharmony_ci   bool all_bits_are_0 = true;
1646bf215546Sopenharmony_ci   bool all_bits_are_1 = true;
1647bf215546Sopenharmony_ci   bool all_words_are_fp16_1 = true;
1648bf215546Sopenharmony_ci   bool all_words_are_fp32_1 = true;
1649bf215546Sopenharmony_ci   bool unorm_0001 = true;
1650bf215546Sopenharmony_ci   bool unorm_1110 = true;
1651bf215546Sopenharmony_ci
1652bf215546Sopenharmony_ci   const struct util_format_description *desc = vk_format_description(iview->vk.format);
1653bf215546Sopenharmony_ci   if (iview->vk.format == VK_FORMAT_B10G11R11_UFLOAT_PACK32 ||
1654bf215546Sopenharmony_ci       iview->vk.format == VK_FORMAT_R5G6B5_UNORM_PACK16 ||
1655bf215546Sopenharmony_ci       iview->vk.format == VK_FORMAT_B5G6R5_UNORM_PACK16)
1656bf215546Sopenharmony_ci      extra_channel = -1;
1657bf215546Sopenharmony_ci   else if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN) {
1658bf215546Sopenharmony_ci      if (vi_alpha_is_on_msb(device, iview->vk.format))
1659bf215546Sopenharmony_ci         extra_channel = desc->nr_channels - 1;
1660bf215546Sopenharmony_ci      else
1661bf215546Sopenharmony_ci         extra_channel = 0;
1662bf215546Sopenharmony_ci   } else
1663bf215546Sopenharmony_ci      return false;
1664bf215546Sopenharmony_ci
1665bf215546Sopenharmony_ci   for (int i = 0; i < 4; i++) {
1666bf215546Sopenharmony_ci      int index = desc->swizzle[i] - PIPE_SWIZZLE_X;
1667bf215546Sopenharmony_ci      if (desc->swizzle[i] < PIPE_SWIZZLE_X || desc->swizzle[i] > PIPE_SWIZZLE_W)
1668bf215546Sopenharmony_ci         continue;
1669bf215546Sopenharmony_ci
1670bf215546Sopenharmony_ci      uint32_t extra_xor = index == extra_channel ? ~0u : 0;
1671bf215546Sopenharmony_ci      if (clear_value->uint32[i] & ((1u << desc->channel[i].size) - 1))
1672bf215546Sopenharmony_ci         all_bits_are_0 = false;
1673bf215546Sopenharmony_ci      if (~clear_value->uint32[i] & ((1u << desc->channel[i].size) - 1))
1674bf215546Sopenharmony_ci         all_bits_are_1 = false;
1675bf215546Sopenharmony_ci      if (desc->channel[i].type != UTIL_FORMAT_TYPE_FLOAT || desc->channel[i].size != 16 ||
1676bf215546Sopenharmony_ci          clear_value->float32[i] != 1.0)
1677bf215546Sopenharmony_ci         all_words_are_fp16_1 = false;
1678bf215546Sopenharmony_ci      if (desc->channel[i].type != UTIL_FORMAT_TYPE_FLOAT || desc->channel[i].size != 32 ||
1679bf215546Sopenharmony_ci          clear_value->float32[i] != 1.0)
1680bf215546Sopenharmony_ci         all_words_are_fp32_1 = false;
1681bf215546Sopenharmony_ci      if ((clear_value->uint32[i] ^ extra_xor) & ((1u << desc->channel[i].size) - 1))
1682bf215546Sopenharmony_ci         unorm_0001 = false;
1683bf215546Sopenharmony_ci      if ((~clear_value->uint32[i] ^ extra_xor) & ((1u << desc->channel[i].size) - 1))
1684bf215546Sopenharmony_ci         unorm_1110 = false;
1685bf215546Sopenharmony_ci   }
1686bf215546Sopenharmony_ci
1687bf215546Sopenharmony_ci   if (all_bits_are_0)
1688bf215546Sopenharmony_ci      *reset_value = RADV_DCC_CLEAR_0000;
1689bf215546Sopenharmony_ci   else if (all_bits_are_1)
1690bf215546Sopenharmony_ci      *reset_value = RADV_DCC_GFX11_CLEAR_1111_UNORM;
1691bf215546Sopenharmony_ci   else if (all_words_are_fp16_1)
1692bf215546Sopenharmony_ci      *reset_value = RADV_DCC_GFX11_CLEAR_1111_FP16;
1693bf215546Sopenharmony_ci   else if (all_words_are_fp32_1)
1694bf215546Sopenharmony_ci      *reset_value = RADV_DCC_GFX11_CLEAR_1111_FP32;
1695bf215546Sopenharmony_ci   else if (unorm_0001)
1696bf215546Sopenharmony_ci      *reset_value = RADV_DCC_GFX11_CLEAR_0001_UNORM;
1697bf215546Sopenharmony_ci   else if (unorm_1110)
1698bf215546Sopenharmony_ci      *reset_value = RADV_DCC_GFX11_CLEAR_1110_UNORM;
1699bf215546Sopenharmony_ci   else if (iview->image->support_comp_to_single)
1700bf215546Sopenharmony_ci      *reset_value = RADV_DCC_GFX11_CLEAR_SINGLE;
1701bf215546Sopenharmony_ci   else
1702bf215546Sopenharmony_ci      return false;
1703bf215546Sopenharmony_ci
1704bf215546Sopenharmony_ci   return true;
1705bf215546Sopenharmony_ci}
1706bf215546Sopenharmony_ci
1707bf215546Sopenharmony_cistatic bool
1708bf215546Sopenharmony_ciradv_can_fast_clear_color(struct radv_cmd_buffer *cmd_buffer, const struct radv_image_view *iview,
1709bf215546Sopenharmony_ci                          VkImageLayout image_layout, bool in_render_loop,
1710bf215546Sopenharmony_ci                          const VkClearRect *clear_rect, VkClearColorValue clear_value,
1711bf215546Sopenharmony_ci                          uint32_t view_mask)
1712bf215546Sopenharmony_ci{
1713bf215546Sopenharmony_ci   uint32_t clear_color[2];
1714bf215546Sopenharmony_ci
1715bf215546Sopenharmony_ci   if (!iview || !iview->support_fast_clear)
1716bf215546Sopenharmony_ci      return false;
1717bf215546Sopenharmony_ci
1718bf215546Sopenharmony_ci   if (!radv_layout_can_fast_clear(
1719bf215546Sopenharmony_ci          cmd_buffer->device, iview->image, iview->vk.base_mip_level, image_layout, in_render_loop,
1720bf215546Sopenharmony_ci          radv_image_queue_family_mask(iview->image, cmd_buffer->qf,
1721bf215546Sopenharmony_ci                                       cmd_buffer->qf)))
1722bf215546Sopenharmony_ci      return false;
1723bf215546Sopenharmony_ci
1724bf215546Sopenharmony_ci   if (clear_rect->rect.offset.x || clear_rect->rect.offset.y ||
1725bf215546Sopenharmony_ci       clear_rect->rect.extent.width != iview->image->info.width ||
1726bf215546Sopenharmony_ci       clear_rect->rect.extent.height != iview->image->info.height)
1727bf215546Sopenharmony_ci      return false;
1728bf215546Sopenharmony_ci
1729bf215546Sopenharmony_ci   if (view_mask && (iview->image->info.array_size >= 32 ||
1730bf215546Sopenharmony_ci                     (1u << iview->image->info.array_size) - 1u != view_mask))
1731bf215546Sopenharmony_ci      return false;
1732bf215546Sopenharmony_ci   if (!view_mask && clear_rect->baseArrayLayer != 0)
1733bf215546Sopenharmony_ci      return false;
1734bf215546Sopenharmony_ci   if (!view_mask && clear_rect->layerCount != iview->image->info.array_size)
1735bf215546Sopenharmony_ci      return false;
1736bf215546Sopenharmony_ci
1737bf215546Sopenharmony_ci   /* DCC */
1738bf215546Sopenharmony_ci   if (!radv_format_pack_clear_color(iview->vk.format, clear_color, &clear_value))
1739bf215546Sopenharmony_ci      return false;
1740bf215546Sopenharmony_ci
1741bf215546Sopenharmony_ci   /* Images that support comp-to-single clears don't have clear values. */
1742bf215546Sopenharmony_ci   if (!iview->image->support_comp_to_single &&
1743bf215546Sopenharmony_ci       !radv_image_has_clear_value(iview->image) && (clear_color[0] != 0 || clear_color[1] != 0))
1744bf215546Sopenharmony_ci      return false;
1745bf215546Sopenharmony_ci
1746bf215546Sopenharmony_ci   if (radv_dcc_enabled(iview->image, iview->vk.base_mip_level)) {
1747bf215546Sopenharmony_ci      bool can_avoid_fast_clear_elim;
1748bf215546Sopenharmony_ci      uint32_t reset_value;
1749bf215546Sopenharmony_ci
1750bf215546Sopenharmony_ci      if (cmd_buffer->device->physical_device->rad_info.gfx_level >= GFX11) {
1751bf215546Sopenharmony_ci         if (!gfx11_get_fast_clear_parameters(cmd_buffer->device, iview, &clear_value,
1752bf215546Sopenharmony_ci                                              &reset_value))
1753bf215546Sopenharmony_ci            return false;
1754bf215546Sopenharmony_ci      } else {
1755bf215546Sopenharmony_ci         gfx8_get_fast_clear_parameters(cmd_buffer->device, iview, &clear_value, &reset_value,
1756bf215546Sopenharmony_ci                                        &can_avoid_fast_clear_elim);
1757bf215546Sopenharmony_ci      }
1758bf215546Sopenharmony_ci
1759bf215546Sopenharmony_ci      if (iview->image->info.levels > 1) {
1760bf215546Sopenharmony_ci         if (cmd_buffer->device->physical_device->rad_info.gfx_level >= GFX9) {
1761bf215546Sopenharmony_ci            uint32_t last_level = iview->vk.base_mip_level + iview->vk.level_count - 1;
1762bf215546Sopenharmony_ci            if (last_level >= iview->image->planes[0].surface.num_meta_levels) {
1763bf215546Sopenharmony_ci               /* Do not fast clears if one level can't be fast cleard. */
1764bf215546Sopenharmony_ci               return false;
1765bf215546Sopenharmony_ci            }
1766bf215546Sopenharmony_ci         } else {
1767bf215546Sopenharmony_ci            for (uint32_t l = 0; l < iview->vk.level_count; l++) {
1768bf215546Sopenharmony_ci               uint32_t level = iview->vk.base_mip_level + l;
1769bf215546Sopenharmony_ci               struct legacy_surf_dcc_level *dcc_level =
1770bf215546Sopenharmony_ci                  &iview->image->planes[0].surface.u.legacy.color.dcc_level[level];
1771bf215546Sopenharmony_ci
1772bf215546Sopenharmony_ci               /* Do not fast clears if one level can't be
1773bf215546Sopenharmony_ci                * fast cleared.
1774bf215546Sopenharmony_ci                */
1775bf215546Sopenharmony_ci               if (!dcc_level->dcc_fast_clear_size)
1776bf215546Sopenharmony_ci                  return false;
1777bf215546Sopenharmony_ci            }
1778bf215546Sopenharmony_ci         }
1779bf215546Sopenharmony_ci      }
1780bf215546Sopenharmony_ci   }
1781bf215546Sopenharmony_ci
1782bf215546Sopenharmony_ci   return true;
1783bf215546Sopenharmony_ci}
1784bf215546Sopenharmony_ci
1785bf215546Sopenharmony_cistatic void
1786bf215546Sopenharmony_ciradv_fast_clear_color(struct radv_cmd_buffer *cmd_buffer, const struct radv_image_view *iview,
1787bf215546Sopenharmony_ci                      const VkClearAttachment *clear_att, uint32_t subpass_att,
1788bf215546Sopenharmony_ci                      enum radv_cmd_flush_bits *pre_flush, enum radv_cmd_flush_bits *post_flush)
1789bf215546Sopenharmony_ci{
1790bf215546Sopenharmony_ci   VkClearColorValue clear_value = clear_att->clearValue.color;
1791bf215546Sopenharmony_ci   uint32_t clear_color[2], flush_bits = 0;
1792bf215546Sopenharmony_ci   uint32_t cmask_clear_value;
1793bf215546Sopenharmony_ci   VkImageSubresourceRange range = {
1794bf215546Sopenharmony_ci      .aspectMask = iview->vk.aspects,
1795bf215546Sopenharmony_ci      .baseMipLevel = iview->vk.base_mip_level,
1796bf215546Sopenharmony_ci      .levelCount = iview->vk.level_count,
1797bf215546Sopenharmony_ci      .baseArrayLayer = iview->vk.base_array_layer,
1798bf215546Sopenharmony_ci      .layerCount = iview->vk.layer_count,
1799bf215546Sopenharmony_ci   };
1800bf215546Sopenharmony_ci
1801bf215546Sopenharmony_ci   if (pre_flush) {
1802bf215546Sopenharmony_ci      enum radv_cmd_flush_bits bits =
1803bf215546Sopenharmony_ci         radv_src_access_flush(cmd_buffer, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, iview->image) |
1804bf215546Sopenharmony_ci         radv_dst_access_flush(cmd_buffer, VK_ACCESS_2_SHADER_WRITE_BIT, iview->image);
1805bf215546Sopenharmony_ci      cmd_buffer->state.flush_bits |= bits & ~*pre_flush;
1806bf215546Sopenharmony_ci      *pre_flush |= cmd_buffer->state.flush_bits;
1807bf215546Sopenharmony_ci   }
1808bf215546Sopenharmony_ci
1809bf215546Sopenharmony_ci   /* DCC */
1810bf215546Sopenharmony_ci   radv_format_pack_clear_color(iview->vk.format, clear_color, &clear_value);
1811bf215546Sopenharmony_ci
1812bf215546Sopenharmony_ci   cmask_clear_value = radv_get_cmask_fast_clear_value(iview->image);
1813bf215546Sopenharmony_ci
1814bf215546Sopenharmony_ci   /* clear cmask buffer */
1815bf215546Sopenharmony_ci   bool need_decompress_pass = false;
1816bf215546Sopenharmony_ci   if (radv_dcc_enabled(iview->image, iview->vk.base_mip_level)) {
1817bf215546Sopenharmony_ci      uint32_t reset_value;
1818bf215546Sopenharmony_ci      bool can_avoid_fast_clear_elim = true;
1819bf215546Sopenharmony_ci
1820bf215546Sopenharmony_ci      if (cmd_buffer->device->physical_device->rad_info.gfx_level >= GFX11) {
1821bf215546Sopenharmony_ci         ASSERTED bool result =
1822bf215546Sopenharmony_ci            gfx11_get_fast_clear_parameters(cmd_buffer->device, iview, &clear_value, &reset_value);
1823bf215546Sopenharmony_ci         assert(result);
1824bf215546Sopenharmony_ci      } else {
1825bf215546Sopenharmony_ci         gfx8_get_fast_clear_parameters(cmd_buffer->device, iview, &clear_value, &reset_value,
1826bf215546Sopenharmony_ci                                        &can_avoid_fast_clear_elim);
1827bf215546Sopenharmony_ci      }
1828bf215546Sopenharmony_ci
1829bf215546Sopenharmony_ci      if (radv_image_has_cmask(iview->image)) {
1830bf215546Sopenharmony_ci         flush_bits = radv_clear_cmask(cmd_buffer, iview->image, &range, cmask_clear_value);
1831bf215546Sopenharmony_ci      }
1832bf215546Sopenharmony_ci
1833bf215546Sopenharmony_ci      if (!can_avoid_fast_clear_elim)
1834bf215546Sopenharmony_ci         need_decompress_pass = true;
1835bf215546Sopenharmony_ci
1836bf215546Sopenharmony_ci      flush_bits |= radv_clear_dcc(cmd_buffer, iview->image, &range, reset_value);
1837bf215546Sopenharmony_ci
1838bf215546Sopenharmony_ci      if (reset_value == radv_dcc_single_clear_value(cmd_buffer->device)) {
1839bf215546Sopenharmony_ci         /* Write the clear color to the first byte of each 256B block when the image supports DCC
1840bf215546Sopenharmony_ci          * fast clears with comp-to-single.
1841bf215546Sopenharmony_ci          */
1842bf215546Sopenharmony_ci         flush_bits |= radv_clear_dcc_comp_to_single(cmd_buffer, iview->image, &range, clear_color);
1843bf215546Sopenharmony_ci      }
1844bf215546Sopenharmony_ci   } else {
1845bf215546Sopenharmony_ci      flush_bits = radv_clear_cmask(cmd_buffer, iview->image, &range, cmask_clear_value);
1846bf215546Sopenharmony_ci
1847bf215546Sopenharmony_ci      /* Fast clearing with CMASK should always be eliminated. */
1848bf215546Sopenharmony_ci      need_decompress_pass = true;
1849bf215546Sopenharmony_ci   }
1850bf215546Sopenharmony_ci
1851bf215546Sopenharmony_ci   if (post_flush) {
1852bf215546Sopenharmony_ci      *post_flush |= flush_bits;
1853bf215546Sopenharmony_ci   }
1854bf215546Sopenharmony_ci
1855bf215546Sopenharmony_ci   /* Update the FCE predicate to perform a fast-clear eliminate. */
1856bf215546Sopenharmony_ci   radv_update_fce_metadata(cmd_buffer, iview->image, &range, need_decompress_pass);
1857bf215546Sopenharmony_ci
1858bf215546Sopenharmony_ci   radv_update_color_clear_metadata(cmd_buffer, iview, subpass_att, clear_color);
1859bf215546Sopenharmony_ci}
1860bf215546Sopenharmony_ci
1861bf215546Sopenharmony_ci/**
1862bf215546Sopenharmony_ci * The parameters mean that same as those in vkCmdClearAttachments.
1863bf215546Sopenharmony_ci */
1864bf215546Sopenharmony_cistatic void
1865bf215546Sopenharmony_ciemit_clear(struct radv_cmd_buffer *cmd_buffer, const VkClearAttachment *clear_att,
1866bf215546Sopenharmony_ci           const VkClearRect *clear_rect, enum radv_cmd_flush_bits *pre_flush,
1867bf215546Sopenharmony_ci           enum radv_cmd_flush_bits *post_flush, uint32_t view_mask, bool ds_resolve_clear)
1868bf215546Sopenharmony_ci{
1869bf215546Sopenharmony_ci   const struct vk_framebuffer *fb = cmd_buffer->state.framebuffer;
1870bf215546Sopenharmony_ci   const struct radv_subpass *subpass = cmd_buffer->state.subpass;
1871bf215546Sopenharmony_ci   VkImageAspectFlags aspects = clear_att->aspectMask;
1872bf215546Sopenharmony_ci
1873bf215546Sopenharmony_ci   if (aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
1874bf215546Sopenharmony_ci      const uint32_t subpass_att = clear_att->colorAttachment;
1875bf215546Sopenharmony_ci      assert(subpass_att < subpass->color_count);
1876bf215546Sopenharmony_ci      const uint32_t pass_att = subpass->color_attachments[subpass_att].attachment;
1877bf215546Sopenharmony_ci      if (pass_att == VK_ATTACHMENT_UNUSED)
1878bf215546Sopenharmony_ci         return;
1879bf215546Sopenharmony_ci
1880bf215546Sopenharmony_ci      VkImageLayout image_layout = subpass->color_attachments[subpass_att].layout;
1881bf215546Sopenharmony_ci      bool in_render_loop = subpass->color_attachments[subpass_att].in_render_loop;
1882bf215546Sopenharmony_ci      const struct radv_image_view *iview =
1883bf215546Sopenharmony_ci         fb ? cmd_buffer->state.attachments[pass_att].iview : NULL;
1884bf215546Sopenharmony_ci      VkClearColorValue clear_value = clear_att->clearValue.color;
1885bf215546Sopenharmony_ci
1886bf215546Sopenharmony_ci      if (radv_can_fast_clear_color(cmd_buffer, iview, image_layout, in_render_loop, clear_rect,
1887bf215546Sopenharmony_ci                                    clear_value, view_mask)) {
1888bf215546Sopenharmony_ci         radv_fast_clear_color(cmd_buffer, iview, clear_att, subpass_att, pre_flush, post_flush);
1889bf215546Sopenharmony_ci      } else {
1890bf215546Sopenharmony_ci         emit_color_clear(cmd_buffer, clear_att, clear_rect, view_mask);
1891bf215546Sopenharmony_ci      }
1892bf215546Sopenharmony_ci   } else {
1893bf215546Sopenharmony_ci      struct radv_subpass_attachment *ds_att = subpass->depth_stencil_attachment;
1894bf215546Sopenharmony_ci
1895bf215546Sopenharmony_ci      if (ds_resolve_clear)
1896bf215546Sopenharmony_ci         ds_att = subpass->ds_resolve_attachment;
1897bf215546Sopenharmony_ci
1898bf215546Sopenharmony_ci      if (!ds_att || ds_att->attachment == VK_ATTACHMENT_UNUSED)
1899bf215546Sopenharmony_ci         return;
1900bf215546Sopenharmony_ci
1901bf215546Sopenharmony_ci      VkImageLayout image_layout = ds_att->layout;
1902bf215546Sopenharmony_ci      bool in_render_loop = ds_att->in_render_loop;
1903bf215546Sopenharmony_ci      const struct radv_image_view *iview =
1904bf215546Sopenharmony_ci         fb ? cmd_buffer->state.attachments[ds_att->attachment].iview : NULL;
1905bf215546Sopenharmony_ci      VkClearDepthStencilValue clear_value = clear_att->clearValue.depthStencil;
1906bf215546Sopenharmony_ci
1907bf215546Sopenharmony_ci      assert(aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
1908bf215546Sopenharmony_ci
1909bf215546Sopenharmony_ci      if (radv_can_fast_clear_depth(cmd_buffer, iview, image_layout, in_render_loop, aspects,
1910bf215546Sopenharmony_ci                                    clear_rect, clear_value, view_mask)) {
1911bf215546Sopenharmony_ci         radv_fast_clear_depth(cmd_buffer, iview, clear_att, pre_flush, post_flush);
1912bf215546Sopenharmony_ci      } else {
1913bf215546Sopenharmony_ci         emit_depthstencil_clear(cmd_buffer, clear_att, clear_rect, ds_att, view_mask,
1914bf215546Sopenharmony_ci                                 ds_resolve_clear);
1915bf215546Sopenharmony_ci      }
1916bf215546Sopenharmony_ci   }
1917bf215546Sopenharmony_ci}
1918bf215546Sopenharmony_ci
1919bf215546Sopenharmony_cistatic inline bool
1920bf215546Sopenharmony_ciradv_attachment_needs_clear(struct radv_cmd_state *cmd_state, uint32_t a)
1921bf215546Sopenharmony_ci{
1922bf215546Sopenharmony_ci   uint32_t view_mask = cmd_state->subpass->view_mask;
1923bf215546Sopenharmony_ci   return (a != VK_ATTACHMENT_UNUSED && cmd_state->attachments[a].pending_clear_aspects &&
1924bf215546Sopenharmony_ci           (!view_mask || (view_mask & ~cmd_state->attachments[a].cleared_views)));
1925bf215546Sopenharmony_ci}
1926bf215546Sopenharmony_ci
1927bf215546Sopenharmony_cistatic bool
1928bf215546Sopenharmony_ciradv_subpass_needs_clear(struct radv_cmd_buffer *cmd_buffer)
1929bf215546Sopenharmony_ci{
1930bf215546Sopenharmony_ci   struct radv_cmd_state *cmd_state = &cmd_buffer->state;
1931bf215546Sopenharmony_ci   uint32_t a;
1932bf215546Sopenharmony_ci
1933bf215546Sopenharmony_ci   if (!cmd_state->subpass)
1934bf215546Sopenharmony_ci      return false;
1935bf215546Sopenharmony_ci
1936bf215546Sopenharmony_ci   for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
1937bf215546Sopenharmony_ci      a = cmd_state->subpass->color_attachments[i].attachment;
1938bf215546Sopenharmony_ci      if (radv_attachment_needs_clear(cmd_state, a))
1939bf215546Sopenharmony_ci         return true;
1940bf215546Sopenharmony_ci   }
1941bf215546Sopenharmony_ci
1942bf215546Sopenharmony_ci   if (cmd_state->subpass->depth_stencil_attachment) {
1943bf215546Sopenharmony_ci      a = cmd_state->subpass->depth_stencil_attachment->attachment;
1944bf215546Sopenharmony_ci      if (radv_attachment_needs_clear(cmd_state, a))
1945bf215546Sopenharmony_ci         return true;
1946bf215546Sopenharmony_ci   }
1947bf215546Sopenharmony_ci
1948bf215546Sopenharmony_ci   if (!cmd_state->subpass->ds_resolve_attachment)
1949bf215546Sopenharmony_ci      return false;
1950bf215546Sopenharmony_ci
1951bf215546Sopenharmony_ci   a = cmd_state->subpass->ds_resolve_attachment->attachment;
1952bf215546Sopenharmony_ci   return radv_attachment_needs_clear(cmd_state, a);
1953bf215546Sopenharmony_ci}
1954bf215546Sopenharmony_ci
1955bf215546Sopenharmony_cistatic void
1956bf215546Sopenharmony_ciradv_subpass_clear_attachment(struct radv_cmd_buffer *cmd_buffer,
1957bf215546Sopenharmony_ci                              struct radv_attachment_state *attachment,
1958bf215546Sopenharmony_ci                              const VkClearAttachment *clear_att,
1959bf215546Sopenharmony_ci                              enum radv_cmd_flush_bits *pre_flush,
1960bf215546Sopenharmony_ci                              enum radv_cmd_flush_bits *post_flush, bool ds_resolve_clear)
1961bf215546Sopenharmony_ci{
1962bf215546Sopenharmony_ci   struct radv_cmd_state *cmd_state = &cmd_buffer->state;
1963bf215546Sopenharmony_ci   uint32_t view_mask = cmd_state->subpass->view_mask;
1964bf215546Sopenharmony_ci
1965bf215546Sopenharmony_ci   VkClearRect clear_rect = {
1966bf215546Sopenharmony_ci      .rect = cmd_state->render_area,
1967bf215546Sopenharmony_ci      .baseArrayLayer = 0,
1968bf215546Sopenharmony_ci      .layerCount = cmd_state->framebuffer->layers,
1969bf215546Sopenharmony_ci   };
1970bf215546Sopenharmony_ci
1971bf215546Sopenharmony_ci   radv_describe_begin_render_pass_clear(cmd_buffer, clear_att->aspectMask);
1972bf215546Sopenharmony_ci
1973bf215546Sopenharmony_ci   emit_clear(cmd_buffer, clear_att, &clear_rect, pre_flush, post_flush,
1974bf215546Sopenharmony_ci              view_mask & ~attachment->cleared_views, ds_resolve_clear);
1975bf215546Sopenharmony_ci   if (view_mask)
1976bf215546Sopenharmony_ci      attachment->cleared_views |= view_mask;
1977bf215546Sopenharmony_ci   else
1978bf215546Sopenharmony_ci      attachment->pending_clear_aspects = 0;
1979bf215546Sopenharmony_ci
1980bf215546Sopenharmony_ci   radv_describe_end_render_pass_clear(cmd_buffer);
1981bf215546Sopenharmony_ci}
1982bf215546Sopenharmony_ci
1983bf215546Sopenharmony_ci/**
1984bf215546Sopenharmony_ci * Emit any pending attachment clears for the current subpass.
1985bf215546Sopenharmony_ci *
1986bf215546Sopenharmony_ci * @see radv_attachment_state::pending_clear_aspects
1987bf215546Sopenharmony_ci */
1988bf215546Sopenharmony_civoid
1989bf215546Sopenharmony_ciradv_cmd_buffer_clear_subpass(struct radv_cmd_buffer *cmd_buffer)
1990bf215546Sopenharmony_ci{
1991bf215546Sopenharmony_ci   struct radv_cmd_state *cmd_state = &cmd_buffer->state;
1992bf215546Sopenharmony_ci   struct radv_meta_saved_state saved_state;
1993bf215546Sopenharmony_ci   enum radv_cmd_flush_bits pre_flush = 0;
1994bf215546Sopenharmony_ci   enum radv_cmd_flush_bits post_flush = 0;
1995bf215546Sopenharmony_ci
1996bf215546Sopenharmony_ci   if (!radv_subpass_needs_clear(cmd_buffer))
1997bf215546Sopenharmony_ci      return;
1998bf215546Sopenharmony_ci
1999bf215546Sopenharmony_ci   /* Subpass clear should not be affected by conditional rendering. */
2000bf215546Sopenharmony_ci   radv_meta_save(
2001bf215546Sopenharmony_ci      &saved_state, cmd_buffer,
2002bf215546Sopenharmony_ci      RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_CONSTANTS | RADV_META_SUSPEND_PREDICATING);
2003bf215546Sopenharmony_ci
2004bf215546Sopenharmony_ci   for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
2005bf215546Sopenharmony_ci      uint32_t a = cmd_state->subpass->color_attachments[i].attachment;
2006bf215546Sopenharmony_ci
2007bf215546Sopenharmony_ci      if (!radv_attachment_needs_clear(cmd_state, a))
2008bf215546Sopenharmony_ci         continue;
2009bf215546Sopenharmony_ci
2010bf215546Sopenharmony_ci      assert(cmd_state->attachments[a].pending_clear_aspects == VK_IMAGE_ASPECT_COLOR_BIT);
2011bf215546Sopenharmony_ci
2012bf215546Sopenharmony_ci      VkClearAttachment clear_att = {
2013bf215546Sopenharmony_ci         .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2014bf215546Sopenharmony_ci         .colorAttachment = i, /* Use attachment index relative to subpass */
2015bf215546Sopenharmony_ci         .clearValue = cmd_state->attachments[a].clear_value,
2016bf215546Sopenharmony_ci      };
2017bf215546Sopenharmony_ci
2018bf215546Sopenharmony_ci      radv_subpass_clear_attachment(cmd_buffer, &cmd_state->attachments[a], &clear_att, &pre_flush,
2019bf215546Sopenharmony_ci                                    &post_flush, false);
2020bf215546Sopenharmony_ci   }
2021bf215546Sopenharmony_ci
2022bf215546Sopenharmony_ci   if (cmd_state->subpass->depth_stencil_attachment) {
2023bf215546Sopenharmony_ci      uint32_t ds = cmd_state->subpass->depth_stencil_attachment->attachment;
2024bf215546Sopenharmony_ci      if (radv_attachment_needs_clear(cmd_state, ds)) {
2025bf215546Sopenharmony_ci         VkClearAttachment clear_att = {
2026bf215546Sopenharmony_ci            .aspectMask = cmd_state->attachments[ds].pending_clear_aspects,
2027bf215546Sopenharmony_ci            .clearValue = cmd_state->attachments[ds].clear_value,
2028bf215546Sopenharmony_ci         };
2029bf215546Sopenharmony_ci
2030bf215546Sopenharmony_ci         radv_subpass_clear_attachment(cmd_buffer, &cmd_state->attachments[ds], &clear_att,
2031bf215546Sopenharmony_ci                                       &pre_flush, &post_flush, false);
2032bf215546Sopenharmony_ci      }
2033bf215546Sopenharmony_ci   }
2034bf215546Sopenharmony_ci
2035bf215546Sopenharmony_ci   if (cmd_state->subpass->ds_resolve_attachment) {
2036bf215546Sopenharmony_ci      uint32_t ds_resolve = cmd_state->subpass->ds_resolve_attachment->attachment;
2037bf215546Sopenharmony_ci      if (radv_attachment_needs_clear(cmd_state, ds_resolve)) {
2038bf215546Sopenharmony_ci         VkClearAttachment clear_att = {
2039bf215546Sopenharmony_ci            .aspectMask = cmd_state->attachments[ds_resolve].pending_clear_aspects,
2040bf215546Sopenharmony_ci            .clearValue = cmd_state->attachments[ds_resolve].clear_value,
2041bf215546Sopenharmony_ci         };
2042bf215546Sopenharmony_ci
2043bf215546Sopenharmony_ci         radv_subpass_clear_attachment(cmd_buffer, &cmd_state->attachments[ds_resolve], &clear_att,
2044bf215546Sopenharmony_ci                                       &pre_flush, &post_flush, true);
2045bf215546Sopenharmony_ci      }
2046bf215546Sopenharmony_ci   }
2047bf215546Sopenharmony_ci
2048bf215546Sopenharmony_ci   radv_meta_restore(&saved_state, cmd_buffer);
2049bf215546Sopenharmony_ci   cmd_buffer->state.flush_bits |= post_flush;
2050bf215546Sopenharmony_ci}
2051bf215546Sopenharmony_ci
2052bf215546Sopenharmony_cistatic void
2053bf215546Sopenharmony_ciradv_clear_image_layer(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
2054bf215546Sopenharmony_ci                       VkImageLayout image_layout, const VkImageSubresourceRange *range,
2055bf215546Sopenharmony_ci                       VkFormat format, int level, unsigned layer_count,
2056bf215546Sopenharmony_ci                       const VkClearValue *clear_val)
2057bf215546Sopenharmony_ci{
2058bf215546Sopenharmony_ci   struct radv_image_view iview;
2059bf215546Sopenharmony_ci   uint32_t width = radv_minify(image->info.width, range->baseMipLevel + level);
2060bf215546Sopenharmony_ci   uint32_t height = radv_minify(image->info.height, range->baseMipLevel + level);
2061bf215546Sopenharmony_ci
2062bf215546Sopenharmony_ci   radv_image_view_init(&iview, cmd_buffer->device,
2063bf215546Sopenharmony_ci                        &(VkImageViewCreateInfo){
2064bf215546Sopenharmony_ci                           .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
2065bf215546Sopenharmony_ci                           .image = radv_image_to_handle(image),
2066bf215546Sopenharmony_ci                           .viewType = radv_meta_get_view_type(image),
2067bf215546Sopenharmony_ci                           .format = format,
2068bf215546Sopenharmony_ci                           .subresourceRange = {.aspectMask = range->aspectMask,
2069bf215546Sopenharmony_ci                                                .baseMipLevel = range->baseMipLevel + level,
2070bf215546Sopenharmony_ci                                                .levelCount = 1,
2071bf215546Sopenharmony_ci                                                .baseArrayLayer = range->baseArrayLayer,
2072bf215546Sopenharmony_ci                                                .layerCount = layer_count},
2073bf215546Sopenharmony_ci                        },
2074bf215546Sopenharmony_ci                        0, NULL);
2075bf215546Sopenharmony_ci
2076bf215546Sopenharmony_ci   VkClearAttachment clear_att = {
2077bf215546Sopenharmony_ci      .aspectMask = range->aspectMask,
2078bf215546Sopenharmony_ci      .colorAttachment = 0,
2079bf215546Sopenharmony_ci      .clearValue = *clear_val,
2080bf215546Sopenharmony_ci   };
2081bf215546Sopenharmony_ci
2082bf215546Sopenharmony_ci   VkClearRect clear_rect = {
2083bf215546Sopenharmony_ci      .rect =
2084bf215546Sopenharmony_ci         {
2085bf215546Sopenharmony_ci            .offset = {0, 0},
2086bf215546Sopenharmony_ci            .extent = {width, height},
2087bf215546Sopenharmony_ci         },
2088bf215546Sopenharmony_ci      .baseArrayLayer = 0,
2089bf215546Sopenharmony_ci      .layerCount = layer_count,
2090bf215546Sopenharmony_ci   };
2091bf215546Sopenharmony_ci
2092bf215546Sopenharmony_ci   VkRenderingAttachmentInfo color_att = {0}, depth_att = {0}, stencil_att = {0};
2093bf215546Sopenharmony_ci
2094bf215546Sopenharmony_ci   if (range->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
2095bf215546Sopenharmony_ci      color_att.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
2096bf215546Sopenharmony_ci      color_att.imageView = radv_image_view_to_handle(&iview);
2097bf215546Sopenharmony_ci      color_att.imageLayout = image_layout;
2098bf215546Sopenharmony_ci      color_att.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
2099bf215546Sopenharmony_ci      color_att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
2100bf215546Sopenharmony_ci   } else {
2101bf215546Sopenharmony_ci      if (range->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) {
2102bf215546Sopenharmony_ci         depth_att.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
2103bf215546Sopenharmony_ci         depth_att.imageView = radv_image_view_to_handle(&iview);
2104bf215546Sopenharmony_ci         depth_att.imageLayout = image_layout;
2105bf215546Sopenharmony_ci         depth_att.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
2106bf215546Sopenharmony_ci         depth_att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
2107bf215546Sopenharmony_ci      }
2108bf215546Sopenharmony_ci
2109bf215546Sopenharmony_ci      if (range->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
2110bf215546Sopenharmony_ci         stencil_att.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
2111bf215546Sopenharmony_ci         stencil_att.imageView = radv_image_view_to_handle(&iview);
2112bf215546Sopenharmony_ci         stencil_att.imageLayout = image_layout;
2113bf215546Sopenharmony_ci         stencil_att.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
2114bf215546Sopenharmony_ci         stencil_att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
2115bf215546Sopenharmony_ci      }
2116bf215546Sopenharmony_ci   }
2117bf215546Sopenharmony_ci
2118bf215546Sopenharmony_ci   VkRenderingInfo rendering_info = {
2119bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
2120bf215546Sopenharmony_ci      .renderArea = {
2121bf215546Sopenharmony_ci         .offset = { 0, 0 },
2122bf215546Sopenharmony_ci         .extent = { width, height },
2123bf215546Sopenharmony_ci      },
2124bf215546Sopenharmony_ci      .layerCount = layer_count,
2125bf215546Sopenharmony_ci   };
2126bf215546Sopenharmony_ci
2127bf215546Sopenharmony_ci   if (range->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
2128bf215546Sopenharmony_ci      rendering_info.colorAttachmentCount = 1;
2129bf215546Sopenharmony_ci      rendering_info.pColorAttachments = &color_att;
2130bf215546Sopenharmony_ci   } else {
2131bf215546Sopenharmony_ci      if (range->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
2132bf215546Sopenharmony_ci         rendering_info.pDepthAttachment = &depth_att;
2133bf215546Sopenharmony_ci      if (range->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
2134bf215546Sopenharmony_ci         rendering_info.pStencilAttachment = &stencil_att;
2135bf215546Sopenharmony_ci   }
2136bf215546Sopenharmony_ci
2137bf215546Sopenharmony_ci   radv_CmdBeginRendering(radv_cmd_buffer_to_handle(cmd_buffer), &rendering_info);
2138bf215546Sopenharmony_ci
2139bf215546Sopenharmony_ci   emit_clear(cmd_buffer, &clear_att, &clear_rect, NULL, NULL, 0, false);
2140bf215546Sopenharmony_ci
2141bf215546Sopenharmony_ci   radv_CmdEndRendering(radv_cmd_buffer_to_handle(cmd_buffer));
2142bf215546Sopenharmony_ci
2143bf215546Sopenharmony_ci   radv_image_view_finish(&iview);
2144bf215546Sopenharmony_ci}
2145bf215546Sopenharmony_ci
2146bf215546Sopenharmony_ci/**
2147bf215546Sopenharmony_ci * Return TRUE if a fast color or depth clear has been performed.
2148bf215546Sopenharmony_ci */
2149bf215546Sopenharmony_cistatic bool
2150bf215546Sopenharmony_ciradv_fast_clear_range(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image, VkFormat format,
2151bf215546Sopenharmony_ci                      VkImageLayout image_layout, bool in_render_loop,
2152bf215546Sopenharmony_ci                      const VkImageSubresourceRange *range, const VkClearValue *clear_val)
2153bf215546Sopenharmony_ci{
2154bf215546Sopenharmony_ci   struct radv_image_view iview;
2155bf215546Sopenharmony_ci   bool fast_cleared = false;
2156bf215546Sopenharmony_ci
2157bf215546Sopenharmony_ci   radv_image_view_init(&iview, cmd_buffer->device,
2158bf215546Sopenharmony_ci                        &(VkImageViewCreateInfo){
2159bf215546Sopenharmony_ci                           .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
2160bf215546Sopenharmony_ci                           .image = radv_image_to_handle(image),
2161bf215546Sopenharmony_ci                           .viewType = radv_meta_get_view_type(image),
2162bf215546Sopenharmony_ci                           .format = image->vk.format,
2163bf215546Sopenharmony_ci                           .subresourceRange =
2164bf215546Sopenharmony_ci                              {
2165bf215546Sopenharmony_ci                                 .aspectMask = range->aspectMask,
2166bf215546Sopenharmony_ci                                 .baseMipLevel = range->baseMipLevel,
2167bf215546Sopenharmony_ci                                 .levelCount = range->levelCount,
2168bf215546Sopenharmony_ci                                 .baseArrayLayer = range->baseArrayLayer,
2169bf215546Sopenharmony_ci                                 .layerCount = range->layerCount,
2170bf215546Sopenharmony_ci                              },
2171bf215546Sopenharmony_ci                        },
2172bf215546Sopenharmony_ci                        0, NULL);
2173bf215546Sopenharmony_ci
2174bf215546Sopenharmony_ci   VkClearRect clear_rect = {
2175bf215546Sopenharmony_ci      .rect =
2176bf215546Sopenharmony_ci         {
2177bf215546Sopenharmony_ci            .offset = {0, 0},
2178bf215546Sopenharmony_ci            .extent =
2179bf215546Sopenharmony_ci               {
2180bf215546Sopenharmony_ci                  radv_minify(image->info.width, range->baseMipLevel),
2181bf215546Sopenharmony_ci                  radv_minify(image->info.height, range->baseMipLevel),
2182bf215546Sopenharmony_ci               },
2183bf215546Sopenharmony_ci         },
2184bf215546Sopenharmony_ci      .baseArrayLayer = range->baseArrayLayer,
2185bf215546Sopenharmony_ci      .layerCount = range->layerCount,
2186bf215546Sopenharmony_ci   };
2187bf215546Sopenharmony_ci
2188bf215546Sopenharmony_ci   VkClearAttachment clear_att = {
2189bf215546Sopenharmony_ci      .aspectMask = range->aspectMask,
2190bf215546Sopenharmony_ci      .colorAttachment = 0,
2191bf215546Sopenharmony_ci      .clearValue = *clear_val,
2192bf215546Sopenharmony_ci   };
2193bf215546Sopenharmony_ci
2194bf215546Sopenharmony_ci   if (vk_format_is_color(format)) {
2195bf215546Sopenharmony_ci      if (radv_can_fast_clear_color(cmd_buffer, &iview, image_layout, in_render_loop, &clear_rect,
2196bf215546Sopenharmony_ci                                    clear_att.clearValue.color, 0)) {
2197bf215546Sopenharmony_ci         radv_fast_clear_color(cmd_buffer, &iview, &clear_att, clear_att.colorAttachment, NULL,
2198bf215546Sopenharmony_ci                               NULL);
2199bf215546Sopenharmony_ci         fast_cleared = true;
2200bf215546Sopenharmony_ci      }
2201bf215546Sopenharmony_ci   } else {
2202bf215546Sopenharmony_ci      if (radv_can_fast_clear_depth(cmd_buffer, &iview, image_layout, in_render_loop,
2203bf215546Sopenharmony_ci                                    range->aspectMask, &clear_rect,
2204bf215546Sopenharmony_ci                                    clear_att.clearValue.depthStencil, 0)) {
2205bf215546Sopenharmony_ci         radv_fast_clear_depth(cmd_buffer, &iview, &clear_att, NULL, NULL);
2206bf215546Sopenharmony_ci         fast_cleared = true;
2207bf215546Sopenharmony_ci      }
2208bf215546Sopenharmony_ci   }
2209bf215546Sopenharmony_ci
2210bf215546Sopenharmony_ci   radv_image_view_finish(&iview);
2211bf215546Sopenharmony_ci   return fast_cleared;
2212bf215546Sopenharmony_ci}
2213bf215546Sopenharmony_ci
2214bf215546Sopenharmony_cistatic void
2215bf215546Sopenharmony_ciradv_cmd_clear_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image,
2216bf215546Sopenharmony_ci                     VkImageLayout image_layout, const VkClearValue *clear_value,
2217bf215546Sopenharmony_ci                     uint32_t range_count, const VkImageSubresourceRange *ranges, bool cs)
2218bf215546Sopenharmony_ci{
2219bf215546Sopenharmony_ci   VkFormat format = image->vk.format;
2220bf215546Sopenharmony_ci   VkClearValue internal_clear_value;
2221bf215546Sopenharmony_ci
2222bf215546Sopenharmony_ci   if (ranges->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
2223bf215546Sopenharmony_ci      internal_clear_value.color = clear_value->color;
2224bf215546Sopenharmony_ci   else
2225bf215546Sopenharmony_ci      internal_clear_value.depthStencil = clear_value->depthStencil;
2226bf215546Sopenharmony_ci
2227bf215546Sopenharmony_ci   bool disable_compression = false;
2228bf215546Sopenharmony_ci
2229bf215546Sopenharmony_ci   if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) {
2230bf215546Sopenharmony_ci      bool blendable;
2231bf215546Sopenharmony_ci      if (cs ? !radv_is_storage_image_format_supported(cmd_buffer->device->physical_device, format)
2232bf215546Sopenharmony_ci             : !radv_is_colorbuffer_format_supported(cmd_buffer->device->physical_device, format,
2233bf215546Sopenharmony_ci                                                     &blendable)) {
2234bf215546Sopenharmony_ci         format = VK_FORMAT_R32_UINT;
2235bf215546Sopenharmony_ci         internal_clear_value.color.uint32[0] = float3_to_rgb9e5(clear_value->color.float32);
2236bf215546Sopenharmony_ci
2237bf215546Sopenharmony_ci         uint32_t queue_mask = radv_image_queue_family_mask(image, cmd_buffer->qf,
2238bf215546Sopenharmony_ci                                                            cmd_buffer->qf);
2239bf215546Sopenharmony_ci
2240bf215546Sopenharmony_ci         for (uint32_t r = 0; r < range_count; r++) {
2241bf215546Sopenharmony_ci            const VkImageSubresourceRange *range = &ranges[r];
2242bf215546Sopenharmony_ci
2243bf215546Sopenharmony_ci            /* Don't use compressed image stores because they will use an incompatible format. */
2244bf215546Sopenharmony_ci            if (radv_layout_dcc_compressed(cmd_buffer->device, image, range->baseMipLevel,
2245bf215546Sopenharmony_ci                                           image_layout, false, queue_mask)) {
2246bf215546Sopenharmony_ci               disable_compression = cs;
2247bf215546Sopenharmony_ci               break;
2248bf215546Sopenharmony_ci            }
2249bf215546Sopenharmony_ci         }
2250bf215546Sopenharmony_ci      }
2251bf215546Sopenharmony_ci   }
2252bf215546Sopenharmony_ci
2253bf215546Sopenharmony_ci   if (format == VK_FORMAT_R4G4_UNORM_PACK8) {
2254bf215546Sopenharmony_ci      uint8_t r, g;
2255bf215546Sopenharmony_ci      format = VK_FORMAT_R8_UINT;
2256bf215546Sopenharmony_ci      r = float_to_ubyte(clear_value->color.float32[0]) >> 4;
2257bf215546Sopenharmony_ci      g = float_to_ubyte(clear_value->color.float32[1]) >> 4;
2258bf215546Sopenharmony_ci      internal_clear_value.color.uint32[0] = (r << 4) | (g & 0xf);
2259bf215546Sopenharmony_ci   }
2260bf215546Sopenharmony_ci
2261bf215546Sopenharmony_ci   for (uint32_t r = 0; r < range_count; r++) {
2262bf215546Sopenharmony_ci      const VkImageSubresourceRange *range = &ranges[r];
2263bf215546Sopenharmony_ci
2264bf215546Sopenharmony_ci      /* Try to perform a fast clear first, otherwise fallback to
2265bf215546Sopenharmony_ci       * the legacy path.
2266bf215546Sopenharmony_ci       */
2267bf215546Sopenharmony_ci      if (!cs && radv_fast_clear_range(cmd_buffer, image, format, image_layout, false, range,
2268bf215546Sopenharmony_ci                                       &internal_clear_value)) {
2269bf215546Sopenharmony_ci         continue;
2270bf215546Sopenharmony_ci      }
2271bf215546Sopenharmony_ci
2272bf215546Sopenharmony_ci      for (uint32_t l = 0; l < radv_get_levelCount(image, range); ++l) {
2273bf215546Sopenharmony_ci         const uint32_t layer_count = image->vk.image_type == VK_IMAGE_TYPE_3D
2274bf215546Sopenharmony_ci                                         ? radv_minify(image->info.depth, range->baseMipLevel + l)
2275bf215546Sopenharmony_ci                                         : radv_get_layerCount(image, range);
2276bf215546Sopenharmony_ci
2277bf215546Sopenharmony_ci         if (cs) {
2278bf215546Sopenharmony_ci            for (uint32_t s = 0; s < layer_count; ++s) {
2279bf215546Sopenharmony_ci               struct radv_meta_blit2d_surf surf;
2280bf215546Sopenharmony_ci               surf.format = format;
2281bf215546Sopenharmony_ci               surf.image = image;
2282bf215546Sopenharmony_ci               surf.level = range->baseMipLevel + l;
2283bf215546Sopenharmony_ci               surf.layer = range->baseArrayLayer + s;
2284bf215546Sopenharmony_ci               surf.aspect_mask = range->aspectMask;
2285bf215546Sopenharmony_ci               surf.disable_compression = disable_compression;
2286bf215546Sopenharmony_ci               radv_meta_clear_image_cs(cmd_buffer, &surf, &internal_clear_value.color);
2287bf215546Sopenharmony_ci            }
2288bf215546Sopenharmony_ci         } else {
2289bf215546Sopenharmony_ci            assert(!disable_compression);
2290bf215546Sopenharmony_ci            radv_clear_image_layer(cmd_buffer, image, image_layout, range, format, l, layer_count,
2291bf215546Sopenharmony_ci                                   &internal_clear_value);
2292bf215546Sopenharmony_ci         }
2293bf215546Sopenharmony_ci      }
2294bf215546Sopenharmony_ci   }
2295bf215546Sopenharmony_ci
2296bf215546Sopenharmony_ci   if (disable_compression) {
2297bf215546Sopenharmony_ci      enum radv_cmd_flush_bits flush_bits = 0;
2298bf215546Sopenharmony_ci      for (unsigned i = 0; i < range_count; i++) {
2299bf215546Sopenharmony_ci         if (radv_dcc_enabled(image, ranges[i].baseMipLevel))
2300bf215546Sopenharmony_ci            flush_bits |= radv_clear_dcc(cmd_buffer, image, &ranges[i], 0xffffffffu);
2301bf215546Sopenharmony_ci      }
2302bf215546Sopenharmony_ci      cmd_buffer->state.flush_bits |= flush_bits;
2303bf215546Sopenharmony_ci   }
2304bf215546Sopenharmony_ci}
2305bf215546Sopenharmony_ci
2306bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2307bf215546Sopenharmony_ciradv_CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image_h, VkImageLayout imageLayout,
2308bf215546Sopenharmony_ci                        const VkClearColorValue *pColor, uint32_t rangeCount,
2309bf215546Sopenharmony_ci                        const VkImageSubresourceRange *pRanges)
2310bf215546Sopenharmony_ci{
2311bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
2312bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_image, image, image_h);
2313bf215546Sopenharmony_ci   struct radv_meta_saved_state saved_state;
2314bf215546Sopenharmony_ci   bool cs;
2315bf215546Sopenharmony_ci
2316bf215546Sopenharmony_ci   cs = cmd_buffer->qf == RADV_QUEUE_COMPUTE ||
2317bf215546Sopenharmony_ci        !radv_image_is_renderable(cmd_buffer->device, image);
2318bf215546Sopenharmony_ci
2319bf215546Sopenharmony_ci   /* Clear commands (except vkCmdClearAttachments) should not be affected by conditional rendering.
2320bf215546Sopenharmony_ci    */
2321bf215546Sopenharmony_ci   enum radv_meta_save_flags save_flags = RADV_META_SAVE_CONSTANTS | RADV_META_SUSPEND_PREDICATING;
2322bf215546Sopenharmony_ci   if (cs)
2323bf215546Sopenharmony_ci      save_flags |= RADV_META_SAVE_COMPUTE_PIPELINE | RADV_META_SAVE_DESCRIPTORS;
2324bf215546Sopenharmony_ci   else
2325bf215546Sopenharmony_ci      save_flags |= RADV_META_SAVE_GRAPHICS_PIPELINE;
2326bf215546Sopenharmony_ci
2327bf215546Sopenharmony_ci   radv_meta_save(&saved_state, cmd_buffer, save_flags);
2328bf215546Sopenharmony_ci
2329bf215546Sopenharmony_ci   radv_cmd_clear_image(cmd_buffer, image, imageLayout, (const VkClearValue *)pColor, rangeCount,
2330bf215546Sopenharmony_ci                        pRanges, cs);
2331bf215546Sopenharmony_ci
2332bf215546Sopenharmony_ci   radv_meta_restore(&saved_state, cmd_buffer);
2333bf215546Sopenharmony_ci}
2334bf215546Sopenharmony_ci
2335bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2336bf215546Sopenharmony_ciradv_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image_h,
2337bf215546Sopenharmony_ci                               VkImageLayout imageLayout,
2338bf215546Sopenharmony_ci                               const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount,
2339bf215546Sopenharmony_ci                               const VkImageSubresourceRange *pRanges)
2340bf215546Sopenharmony_ci{
2341bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
2342bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_image, image, image_h);
2343bf215546Sopenharmony_ci   struct radv_meta_saved_state saved_state;
2344bf215546Sopenharmony_ci
2345bf215546Sopenharmony_ci   /* Clear commands (except vkCmdClearAttachments) should not be affected by conditional rendering. */
2346bf215546Sopenharmony_ci   radv_meta_save(
2347bf215546Sopenharmony_ci      &saved_state, cmd_buffer,
2348bf215546Sopenharmony_ci      RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_CONSTANTS | RADV_META_SUSPEND_PREDICATING);
2349bf215546Sopenharmony_ci
2350bf215546Sopenharmony_ci   radv_cmd_clear_image(cmd_buffer, image, imageLayout, (const VkClearValue *)pDepthStencil,
2351bf215546Sopenharmony_ci                        rangeCount, pRanges, false);
2352bf215546Sopenharmony_ci
2353bf215546Sopenharmony_ci   radv_meta_restore(&saved_state, cmd_buffer);
2354bf215546Sopenharmony_ci}
2355bf215546Sopenharmony_ci
2356bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2357bf215546Sopenharmony_ciradv_CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
2358bf215546Sopenharmony_ci                         const VkClearAttachment *pAttachments, uint32_t rectCount,
2359bf215546Sopenharmony_ci                         const VkClearRect *pRects)
2360bf215546Sopenharmony_ci{
2361bf215546Sopenharmony_ci   RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
2362bf215546Sopenharmony_ci   struct radv_meta_saved_state saved_state;
2363bf215546Sopenharmony_ci   enum radv_cmd_flush_bits pre_flush = 0;
2364bf215546Sopenharmony_ci   enum radv_cmd_flush_bits post_flush = 0;
2365bf215546Sopenharmony_ci
2366bf215546Sopenharmony_ci   if (!cmd_buffer->state.subpass)
2367bf215546Sopenharmony_ci      return;
2368bf215546Sopenharmony_ci
2369bf215546Sopenharmony_ci   radv_meta_save(&saved_state, cmd_buffer,
2370bf215546Sopenharmony_ci                  RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_CONSTANTS);
2371bf215546Sopenharmony_ci
2372bf215546Sopenharmony_ci   /* FINISHME: We can do better than this dumb loop. It thrashes too much
2373bf215546Sopenharmony_ci    * state.
2374bf215546Sopenharmony_ci    */
2375bf215546Sopenharmony_ci   for (uint32_t a = 0; a < attachmentCount; ++a) {
2376bf215546Sopenharmony_ci      for (uint32_t r = 0; r < rectCount; ++r) {
2377bf215546Sopenharmony_ci         emit_clear(cmd_buffer, &pAttachments[a], &pRects[r], &pre_flush, &post_flush,
2378bf215546Sopenharmony_ci                    cmd_buffer->state.subpass->view_mask, false);
2379bf215546Sopenharmony_ci      }
2380bf215546Sopenharmony_ci   }
2381bf215546Sopenharmony_ci
2382bf215546Sopenharmony_ci   radv_meta_restore(&saved_state, cmd_buffer);
2383bf215546Sopenharmony_ci   cmd_buffer->state.flush_bits |= post_flush;
2384bf215546Sopenharmony_ci}
2385