radv: Make color meta operations layout aware.
[mesa.git] / src / amd / vulkan / radv_meta_fast_clear.c
1 /*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <assert.h>
25 #include <stdbool.h>
26
27 #include "radv_meta.h"
28 #include "radv_private.h"
29 #include "sid.h"
30
31
32 static nir_shader *
33 build_dcc_decompress_compute_shader(struct radv_device *dev)
34 {
35 nir_builder b;
36 const struct glsl_type *buf_type = glsl_sampler_type(GLSL_SAMPLER_DIM_2D,
37 false,
38 false,
39 GLSL_TYPE_FLOAT);
40 const struct glsl_type *img_type = glsl_sampler_type(GLSL_SAMPLER_DIM_2D,
41 false,
42 false,
43 GLSL_TYPE_FLOAT);
44 nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_COMPUTE, NULL);
45 b.shader->info.name = ralloc_strdup(b.shader, "dcc_decompress_compute");
46
47 /* We need at least 16/16/1 to cover an entire DCC block in a single workgroup. */
48 b.shader->info.cs.local_size[0] = 16;
49 b.shader->info.cs.local_size[1] = 16;
50 b.shader->info.cs.local_size[2] = 1;
51 nir_variable *input_img = nir_variable_create(b.shader, nir_var_uniform,
52 buf_type, "s_tex");
53 input_img->data.descriptor_set = 0;
54 input_img->data.binding = 0;
55
56 nir_variable *output_img = nir_variable_create(b.shader, nir_var_uniform,
57 img_type, "out_img");
58 output_img->data.descriptor_set = 0;
59 output_img->data.binding = 1;
60
61 nir_ssa_def *invoc_id = nir_load_system_value(&b, nir_intrinsic_load_local_invocation_id, 0);
62 nir_ssa_def *wg_id = nir_load_system_value(&b, nir_intrinsic_load_work_group_id, 0);
63 nir_ssa_def *block_size = nir_imm_ivec4(&b,
64 b.shader->info.cs.local_size[0],
65 b.shader->info.cs.local_size[1],
66 b.shader->info.cs.local_size[2], 0);
67
68 nir_ssa_def *global_id = nir_iadd(&b, nir_imul(&b, wg_id, block_size), invoc_id);
69
70 nir_tex_instr *tex = nir_tex_instr_create(b.shader, 2);
71 tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
72 tex->op = nir_texop_txf;
73 tex->src[0].src_type = nir_tex_src_coord;
74 tex->src[0].src = nir_src_for_ssa(nir_channels(&b, global_id, 3));
75 tex->src[1].src_type = nir_tex_src_lod;
76 tex->src[1].src = nir_src_for_ssa(nir_imm_int(&b, 0));
77 tex->dest_type = nir_type_float;
78 tex->is_array = false;
79 tex->coord_components = 2;
80 tex->texture = nir_deref_var_create(tex, input_img);
81 tex->sampler = NULL;
82
83 nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, "tex");
84 nir_builder_instr_insert(&b, &tex->instr);
85
86 nir_intrinsic_instr *membar = nir_intrinsic_instr_create(b.shader, nir_intrinsic_memory_barrier);
87 nir_builder_instr_insert(&b, &membar->instr);
88
89 nir_intrinsic_instr *bar = nir_intrinsic_instr_create(b.shader, nir_intrinsic_barrier);
90 nir_builder_instr_insert(&b, &bar->instr);
91
92 nir_ssa_def *outval = &tex->dest.ssa;
93 nir_intrinsic_instr *store = nir_intrinsic_instr_create(b.shader, nir_intrinsic_image_store);
94 store->src[0] = nir_src_for_ssa(global_id);
95 store->src[1] = nir_src_for_ssa(nir_ssa_undef(&b, 1, 32));
96 store->src[2] = nir_src_for_ssa(outval);
97 store->variables[0] = nir_deref_var_create(store, output_img);
98
99 nir_builder_instr_insert(&b, &store->instr);
100 return b.shader;
101 }
102
103 static VkResult
104 create_dcc_compress_compute(struct radv_device *device)
105 {
106 VkResult result = VK_SUCCESS;
107 struct radv_shader_module cs = { .nir = NULL };
108
109 cs.nir = build_dcc_decompress_compute_shader(device);
110
111 VkDescriptorSetLayoutCreateInfo ds_create_info = {
112 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
113 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
114 .bindingCount = 2,
115 .pBindings = (VkDescriptorSetLayoutBinding[]) {
116 {
117 .binding = 0,
118 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
119 .descriptorCount = 1,
120 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
121 .pImmutableSamplers = NULL
122 },
123 {
124 .binding = 1,
125 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
126 .descriptorCount = 1,
127 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
128 .pImmutableSamplers = NULL
129 },
130 }
131 };
132
133 result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device),
134 &ds_create_info,
135 &device->meta_state.alloc,
136 &device->meta_state.fast_clear_flush.dcc_decompress_compute_ds_layout);
137 if (result != VK_SUCCESS)
138 goto cleanup;
139
140
141 VkPipelineLayoutCreateInfo pl_create_info = {
142 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
143 .setLayoutCount = 1,
144 .pSetLayouts = &device->meta_state.fast_clear_flush.dcc_decompress_compute_ds_layout,
145 .pushConstantRangeCount = 1,
146 .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_COMPUTE_BIT, 0, 8},
147 };
148
149 result = radv_CreatePipelineLayout(radv_device_to_handle(device),
150 &pl_create_info,
151 &device->meta_state.alloc,
152 &device->meta_state.fast_clear_flush.dcc_decompress_compute_p_layout);
153 if (result != VK_SUCCESS)
154 goto cleanup;
155
156 /* compute shader */
157
158 VkPipelineShaderStageCreateInfo pipeline_shader_stage = {
159 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
160 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
161 .module = radv_shader_module_to_handle(&cs),
162 .pName = "main",
163 .pSpecializationInfo = NULL,
164 };
165
166 VkComputePipelineCreateInfo vk_pipeline_info = {
167 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
168 .stage = pipeline_shader_stage,
169 .flags = 0,
170 .layout = device->meta_state.fast_clear_flush.dcc_decompress_compute_p_layout,
171 };
172
173 result = radv_CreateComputePipelines(radv_device_to_handle(device),
174 radv_pipeline_cache_to_handle(&device->meta_state.cache),
175 1, &vk_pipeline_info, NULL,
176 &device->meta_state.fast_clear_flush.dcc_decompress_compute_pipeline);
177 if (result != VK_SUCCESS)
178 goto cleanup;
179
180 cleanup:
181 ralloc_free(cs.nir);
182 return result;
183 }
184
185 static VkResult
186 create_pass(struct radv_device *device)
187 {
188 VkResult result;
189 VkDevice device_h = radv_device_to_handle(device);
190 const VkAllocationCallbacks *alloc = &device->meta_state.alloc;
191 VkAttachmentDescription attachment;
192
193 attachment.format = VK_FORMAT_UNDEFINED;
194 attachment.samples = 1;
195 attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
196 attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
197 attachment.initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
198 attachment.finalLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
199
200 result = radv_CreateRenderPass(device_h,
201 &(VkRenderPassCreateInfo) {
202 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
203 .attachmentCount = 1,
204 .pAttachments = &attachment,
205 .subpassCount = 1,
206 .pSubpasses = &(VkSubpassDescription) {
207 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
208 .inputAttachmentCount = 0,
209 .colorAttachmentCount = 1,
210 .pColorAttachments = (VkAttachmentReference[]) {
211 {
212 .attachment = 0,
213 .layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
214 },
215 },
216 .pResolveAttachments = NULL,
217 .pDepthStencilAttachment = &(VkAttachmentReference) {
218 .attachment = VK_ATTACHMENT_UNUSED,
219 },
220 .preserveAttachmentCount = 0,
221 .pPreserveAttachments = NULL,
222 },
223 .dependencyCount = 0,
224 },
225 alloc,
226 &device->meta_state.fast_clear_flush.pass);
227
228 return result;
229 }
230
231 static VkResult
232 create_pipeline_layout(struct radv_device *device, VkPipelineLayout *layout)
233 {
234 VkPipelineLayoutCreateInfo pl_create_info = {
235 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
236 .setLayoutCount = 0,
237 .pSetLayouts = NULL,
238 .pushConstantRangeCount = 0,
239 .pPushConstantRanges = NULL,
240 };
241
242 return radv_CreatePipelineLayout(radv_device_to_handle(device),
243 &pl_create_info,
244 &device->meta_state.alloc,
245 layout);
246 }
247
248 static VkResult
249 create_pipeline(struct radv_device *device,
250 VkShaderModule vs_module_h,
251 VkPipelineLayout layout)
252 {
253 VkResult result;
254 VkDevice device_h = radv_device_to_handle(device);
255
256 struct radv_shader_module fs_module = {
257 .nir = radv_meta_build_nir_fs_noop(),
258 };
259
260 if (!fs_module.nir) {
261 /* XXX: Need more accurate error */
262 result = VK_ERROR_OUT_OF_HOST_MEMORY;
263 goto cleanup;
264 }
265
266 const VkPipelineShaderStageCreateInfo stages[2] = {
267 {
268 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
269 .stage = VK_SHADER_STAGE_VERTEX_BIT,
270 .module = vs_module_h,
271 .pName = "main",
272 },
273 {
274 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
275 .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
276 .module = radv_shader_module_to_handle(&fs_module),
277 .pName = "main",
278 },
279 };
280
281 const VkPipelineVertexInputStateCreateInfo vi_state = {
282 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
283 .vertexBindingDescriptionCount = 0,
284 .vertexAttributeDescriptionCount = 0,
285 };
286
287 const VkPipelineInputAssemblyStateCreateInfo ia_state = {
288 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
289 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
290 .primitiveRestartEnable = false,
291 };
292
293 const VkPipelineColorBlendStateCreateInfo blend_state = {
294 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
295 .logicOpEnable = false,
296 .attachmentCount = 1,
297 .pAttachments = (VkPipelineColorBlendAttachmentState []) {
298 {
299 .colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
300 VK_COLOR_COMPONENT_G_BIT |
301 VK_COLOR_COMPONENT_B_BIT |
302 VK_COLOR_COMPONENT_A_BIT,
303 },
304 }
305 };
306 const VkPipelineRasterizationStateCreateInfo rs_state = {
307 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
308 .depthClampEnable = false,
309 .rasterizerDiscardEnable = false,
310 .polygonMode = VK_POLYGON_MODE_FILL,
311 .cullMode = VK_CULL_MODE_NONE,
312 .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
313 };
314
315 result = radv_graphics_pipeline_create(device_h,
316 radv_pipeline_cache_to_handle(&device->meta_state.cache),
317 &(VkGraphicsPipelineCreateInfo) {
318 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
319 .stageCount = 2,
320 .pStages = stages,
321
322 .pVertexInputState = &vi_state,
323 .pInputAssemblyState = &ia_state,
324
325 .pViewportState = &(VkPipelineViewportStateCreateInfo) {
326 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
327 .viewportCount = 1,
328 .scissorCount = 1,
329 },
330 .pRasterizationState = &rs_state,
331 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
332 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
333 .rasterizationSamples = 1,
334 .sampleShadingEnable = false,
335 .pSampleMask = NULL,
336 .alphaToCoverageEnable = false,
337 .alphaToOneEnable = false,
338 },
339 .pColorBlendState = &blend_state,
340 .pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
341 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
342 .dynamicStateCount = 2,
343 .pDynamicStates = (VkDynamicState[]) {
344 VK_DYNAMIC_STATE_VIEWPORT,
345 VK_DYNAMIC_STATE_SCISSOR,
346 },
347 },
348 .layout = layout,
349 .renderPass = device->meta_state.fast_clear_flush.pass,
350 .subpass = 0,
351 },
352 &(struct radv_graphics_pipeline_create_info) {
353 .use_rectlist = true,
354 .custom_blend_mode = V_028808_CB_ELIMINATE_FAST_CLEAR,
355 },
356 &device->meta_state.alloc,
357 &device->meta_state.fast_clear_flush.cmask_eliminate_pipeline);
358 if (result != VK_SUCCESS)
359 goto cleanup;
360
361 result = radv_graphics_pipeline_create(device_h,
362 radv_pipeline_cache_to_handle(&device->meta_state.cache),
363 &(VkGraphicsPipelineCreateInfo) {
364 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
365 .stageCount = 2,
366 .pStages = stages,
367
368 .pVertexInputState = &vi_state,
369 .pInputAssemblyState = &ia_state,
370
371 .pViewportState = &(VkPipelineViewportStateCreateInfo) {
372 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
373 .viewportCount = 1,
374 .scissorCount = 1,
375 },
376 .pRasterizationState = &rs_state,
377 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
378 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
379 .rasterizationSamples = 1,
380 .sampleShadingEnable = false,
381 .pSampleMask = NULL,
382 .alphaToCoverageEnable = false,
383 .alphaToOneEnable = false,
384 },
385 .pColorBlendState = &blend_state,
386 .pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
387 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
388 .dynamicStateCount = 2,
389 .pDynamicStates = (VkDynamicState[]) {
390 VK_DYNAMIC_STATE_VIEWPORT,
391 VK_DYNAMIC_STATE_SCISSOR,
392 },
393 },
394 .layout = layout,
395 .renderPass = device->meta_state.fast_clear_flush.pass,
396 .subpass = 0,
397 },
398 &(struct radv_graphics_pipeline_create_info) {
399 .use_rectlist = true,
400 .custom_blend_mode = V_028808_CB_FMASK_DECOMPRESS,
401 },
402 &device->meta_state.alloc,
403 &device->meta_state.fast_clear_flush.fmask_decompress_pipeline);
404 if (result != VK_SUCCESS)
405 goto cleanup;
406
407 result = radv_graphics_pipeline_create(device_h,
408 radv_pipeline_cache_to_handle(&device->meta_state.cache),
409 &(VkGraphicsPipelineCreateInfo) {
410 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
411 .stageCount = 2,
412 .pStages = stages,
413
414 .pVertexInputState = &vi_state,
415 .pInputAssemblyState = &ia_state,
416
417 .pViewportState = &(VkPipelineViewportStateCreateInfo) {
418 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
419 .viewportCount = 1,
420 .scissorCount = 1,
421 },
422 .pRasterizationState = &rs_state,
423 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
424 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
425 .rasterizationSamples = 1,
426 .sampleShadingEnable = false,
427 .pSampleMask = NULL,
428 .alphaToCoverageEnable = false,
429 .alphaToOneEnable = false,
430 },
431 .pColorBlendState = &blend_state,
432 .pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
433 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
434 .dynamicStateCount = 2,
435 .pDynamicStates = (VkDynamicState[]) {
436 VK_DYNAMIC_STATE_VIEWPORT,
437 VK_DYNAMIC_STATE_SCISSOR,
438 },
439 },
440 .layout = layout,
441 .renderPass = device->meta_state.fast_clear_flush.pass,
442 .subpass = 0,
443 },
444 &(struct radv_graphics_pipeline_create_info) {
445 .use_rectlist = true,
446 .custom_blend_mode = V_028808_CB_DCC_DECOMPRESS,
447 },
448 &device->meta_state.alloc,
449 &device->meta_state.fast_clear_flush.dcc_decompress_pipeline);
450 if (result != VK_SUCCESS)
451 goto cleanup;
452
453 goto cleanup;
454
455 cleanup:
456 ralloc_free(fs_module.nir);
457 return result;
458 }
459
460 void
461 radv_device_finish_meta_fast_clear_flush_state(struct radv_device *device)
462 {
463 struct radv_meta_state *state = &device->meta_state;
464
465 radv_DestroyPipeline(radv_device_to_handle(device),
466 state->fast_clear_flush.dcc_decompress_pipeline,
467 &state->alloc);
468 radv_DestroyPipeline(radv_device_to_handle(device),
469 state->fast_clear_flush.fmask_decompress_pipeline,
470 &state->alloc);
471 radv_DestroyPipeline(radv_device_to_handle(device),
472 state->fast_clear_flush.cmask_eliminate_pipeline,
473 &state->alloc);
474 radv_DestroyRenderPass(radv_device_to_handle(device),
475 state->fast_clear_flush.pass, &state->alloc);
476 radv_DestroyPipelineLayout(radv_device_to_handle(device),
477 state->fast_clear_flush.p_layout,
478 &state->alloc);
479
480 radv_DestroyPipeline(radv_device_to_handle(device),
481 state->fast_clear_flush.dcc_decompress_compute_pipeline,
482 &state->alloc);
483 radv_DestroyPipelineLayout(radv_device_to_handle(device),
484 state->fast_clear_flush.dcc_decompress_compute_p_layout,
485 &state->alloc);
486 radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
487 state->fast_clear_flush.dcc_decompress_compute_ds_layout,
488 &state->alloc);
489 }
490
491 VkResult
492 radv_device_init_meta_fast_clear_flush_state(struct radv_device *device)
493 {
494 VkResult res = VK_SUCCESS;
495
496 struct radv_shader_module vs_module = { .nir = radv_meta_build_nir_vs_generate_vertices() };
497 if (!vs_module.nir) {
498 /* XXX: Need more accurate error */
499 res = VK_ERROR_OUT_OF_HOST_MEMORY;
500 goto fail;
501 }
502
503 res = create_pass(device);
504 if (res != VK_SUCCESS)
505 goto fail;
506
507 res = create_pipeline_layout(device,
508 &device->meta_state.fast_clear_flush.p_layout);
509 if (res != VK_SUCCESS)
510 goto fail;
511
512 VkShaderModule vs_module_h = radv_shader_module_to_handle(&vs_module);
513 res = create_pipeline(device, vs_module_h,
514 device->meta_state.fast_clear_flush.p_layout);
515 if (res != VK_SUCCESS)
516 goto fail;
517
518 res = create_dcc_compress_compute(device);
519 if (res != VK_SUCCESS)
520 goto fail;
521
522 goto cleanup;
523
524 fail:
525 radv_device_finish_meta_fast_clear_flush_state(device);
526
527 cleanup:
528 ralloc_free(vs_module.nir);
529
530 return res;
531 }
532
533 static void
534 emit_fast_clear_flush(struct radv_cmd_buffer *cmd_buffer,
535 const VkExtent2D *resolve_extent,
536 VkPipeline pipeline)
537 {
538 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
539
540 radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
541 pipeline);
542
543 radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) {
544 .x = 0,
545 .y = 0,
546 .width = resolve_extent->width,
547 .height = resolve_extent->height,
548 .minDepth = 0.0f,
549 .maxDepth = 1.0f
550 });
551
552 radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkRect2D) {
553 .offset = (VkOffset2D) { 0, 0 },
554 .extent = (VkExtent2D) { resolve_extent->width, resolve_extent->height },
555 });
556
557 radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0);
558 cmd_buffer->state.flush_bits |= (RADV_CMD_FLAG_FLUSH_AND_INV_CB |
559 RADV_CMD_FLAG_FLUSH_AND_INV_CB_META);
560 }
561
562 static void
563 radv_emit_set_predication_state_from_image(struct radv_cmd_buffer *cmd_buffer,
564 struct radv_image *image, bool value)
565 {
566 uint64_t va = 0;
567
568 if (value) {
569 va = radv_buffer_get_va(image->bo) + image->offset;
570 va += image->dcc_pred_offset;
571 }
572
573 si_emit_set_predication_state(cmd_buffer, va);
574 }
575
576 /**
577 */
578 static void
579 radv_emit_color_decompress(struct radv_cmd_buffer *cmd_buffer,
580 struct radv_image *image,
581 const VkImageSubresourceRange *subresourceRange,
582 bool decompress_dcc)
583 {
584 struct radv_meta_saved_state saved_state;
585 VkDevice device_h = radv_device_to_handle(cmd_buffer->device);
586 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
587 uint32_t layer_count = radv_get_layerCount(image, subresourceRange);
588 VkPipeline pipeline;
589
590 assert(cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL);
591
592 radv_meta_save(&saved_state, cmd_buffer,
593 RADV_META_SAVE_GRAPHICS_PIPELINE |
594 RADV_META_SAVE_PASS);
595
596 if (decompress_dcc && image->surface.dcc_size) {
597 pipeline = cmd_buffer->device->meta_state.fast_clear_flush.dcc_decompress_pipeline;
598 } else if (image->fmask.size > 0) {
599 pipeline = cmd_buffer->device->meta_state.fast_clear_flush.fmask_decompress_pipeline;
600 } else {
601 pipeline = cmd_buffer->device->meta_state.fast_clear_flush.cmask_eliminate_pipeline;
602 }
603
604 if (!decompress_dcc && image->surface.dcc_size) {
605 radv_emit_set_predication_state_from_image(cmd_buffer, image, true);
606 cmd_buffer->state.predicating = true;
607 }
608 for (uint32_t layer = 0; layer < layer_count; ++layer) {
609 struct radv_image_view iview;
610
611 radv_image_view_init(&iview, cmd_buffer->device,
612 &(VkImageViewCreateInfo) {
613 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
614 .image = radv_image_to_handle(image),
615 .viewType = radv_meta_get_view_type(image),
616 .format = image->vk_format,
617 .subresourceRange = {
618 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
619 .baseMipLevel = 0,
620 .levelCount = 1,
621 .baseArrayLayer = subresourceRange->baseArrayLayer + layer,
622 .layerCount = 1,
623 },
624 });
625
626 VkFramebuffer fb_h;
627 radv_CreateFramebuffer(device_h,
628 &(VkFramebufferCreateInfo) {
629 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
630 .attachmentCount = 1,
631 .pAttachments = (VkImageView[]) {
632 radv_image_view_to_handle(&iview)
633 },
634 .width = image->info.width,
635 .height = image->info.height,
636 .layers = 1
637 },
638 &cmd_buffer->pool->alloc,
639 &fb_h);
640
641 radv_CmdBeginRenderPass(cmd_buffer_h,
642 &(VkRenderPassBeginInfo) {
643 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
644 .renderPass = cmd_buffer->device->meta_state.fast_clear_flush.pass,
645 .framebuffer = fb_h,
646 .renderArea = {
647 .offset = {
648 0,
649 0,
650 },
651 .extent = {
652 image->info.width,
653 image->info.height,
654 }
655 },
656 .clearValueCount = 0,
657 .pClearValues = NULL,
658 },
659 VK_SUBPASS_CONTENTS_INLINE);
660
661 emit_fast_clear_flush(cmd_buffer,
662 &(VkExtent2D) { image->info.width, image->info.height },
663 pipeline);
664 radv_CmdEndRenderPass(cmd_buffer_h);
665
666 radv_DestroyFramebuffer(device_h, fb_h,
667 &cmd_buffer->pool->alloc);
668
669 }
670 if (image->surface.dcc_size) {
671 cmd_buffer->state.predicating = false;
672 radv_emit_set_predication_state_from_image(cmd_buffer, image, false);
673 }
674 radv_meta_restore(&saved_state, cmd_buffer);
675 }
676
677 void
678 radv_fast_clear_flush_image_inplace(struct radv_cmd_buffer *cmd_buffer,
679 struct radv_image *image,
680 const VkImageSubresourceRange *subresourceRange)
681 {
682 radv_emit_color_decompress(cmd_buffer, image, subresourceRange, false);
683 }
684
685 static void
686 radv_decompress_dcc_gfx(struct radv_cmd_buffer *cmd_buffer,
687 struct radv_image *image,
688 const VkImageSubresourceRange *subresourceRange)
689 {
690 radv_emit_color_decompress(cmd_buffer, image, subresourceRange, true);
691 }
692
693 static void
694 radv_decompress_dcc_compute(struct radv_cmd_buffer *cmd_buffer,
695 struct radv_image *image,
696 const VkImageSubresourceRange *subresourceRange)
697 {
698 struct radv_meta_saved_state saved_state;
699 struct radv_image_view iview = {0};
700 struct radv_device *device = cmd_buffer->device;
701
702 /* This assumes the image is 2d with 1 layer and 1 mipmap level */
703 struct radv_cmd_state *state = &cmd_buffer->state;
704
705 state->flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB |
706 RADV_CMD_FLAG_FLUSH_AND_INV_CB_META;
707
708 radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_DESCRIPTORS |
709 RADV_META_SAVE_COMPUTE_PIPELINE);
710
711 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
712 VK_PIPELINE_BIND_POINT_COMPUTE,
713 device->meta_state.fast_clear_flush.dcc_decompress_compute_pipeline);
714
715 radv_image_view_init(&iview, cmd_buffer->device,
716 &(VkImageViewCreateInfo) {
717 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
718 .image = radv_image_to_handle(image),
719 .viewType = VK_IMAGE_VIEW_TYPE_2D,
720 .format = image->vk_format,
721 .subresourceRange = {
722 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
723 .baseMipLevel = 0,
724 .levelCount = 1,
725 .baseArrayLayer = 0,
726 .layerCount = 1
727 },
728 });
729
730 radv_meta_push_descriptor_set(cmd_buffer,
731 VK_PIPELINE_BIND_POINT_COMPUTE,
732 device->meta_state.fast_clear_flush.dcc_decompress_compute_p_layout,
733 0, /* set */
734 2, /* descriptorWriteCount */
735 (VkWriteDescriptorSet[]) {
736 {
737 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
738 .dstBinding = 0,
739 .dstArrayElement = 0,
740 .descriptorCount = 1,
741 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
742 .pImageInfo = (VkDescriptorImageInfo[]) {
743 {
744 .sampler = VK_NULL_HANDLE,
745 .imageView = radv_image_view_to_handle(&iview),
746 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
747 },
748 }
749 },
750 {
751 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
752 .dstBinding = 1,
753 .dstArrayElement = 0,
754 .descriptorCount = 1,
755 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
756 .pImageInfo = (VkDescriptorImageInfo[]) {
757 {
758 .sampler = VK_NULL_HANDLE,
759 .imageView = radv_image_view_to_handle(&iview),
760 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
761 },
762 }
763 }
764 });
765
766 radv_unaligned_dispatch(cmd_buffer, image->info.width, image->info.height, 1);
767
768 /* The fill buffer below does its own saving */
769 radv_meta_restore(&saved_state, cmd_buffer);
770
771 state->flush_bits |= RADV_CMD_FLAG_CS_PARTIAL_FLUSH |
772 RADV_CMD_FLAG_INV_VMEM_L1;
773
774 state->flush_bits |= radv_fill_buffer(cmd_buffer, image->bo,
775 image->offset + image->dcc_offset,
776 image->surface.dcc_size, 0xffffffff);
777
778 state->flush_bits |= RADV_CMD_FLAG_FLUSH_AND_INV_CB |
779 RADV_CMD_FLAG_FLUSH_AND_INV_CB_META;
780 }
781
782 void
783 radv_decompress_dcc(struct radv_cmd_buffer *cmd_buffer,
784 struct radv_image *image,
785 const VkImageSubresourceRange *subresourceRange)
786 {
787 if (cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL)
788 radv_decompress_dcc_gfx(cmd_buffer, image, subresourceRange);
789 else
790 radv_decompress_dcc_compute(cmd_buffer, image, subresourceRange);
791 }