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 } 792