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 "nir/nir_builder.h" 30#include "sid.h" 31/** 32 * Vertex attributes used by all pipelines. 33 */ 34struct vertex_attrs { 35 float position[2]; /**< 3DPRIM_RECTLIST */ 36}; 37 38/* passthrough vertex shader */ 39static nir_shader * 40build_nir_vs(void) 41{ 42 const struct glsl_type *vec4 = glsl_vec4_type(); 43 44 nir_builder b; 45 nir_variable *a_position; 46 nir_variable *v_position; 47 48 nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_VERTEX, NULL); 49 b.shader->info->name = ralloc_strdup(b.shader, "meta_fast_clear_vs"); 50 51 a_position = nir_variable_create(b.shader, nir_var_shader_in, vec4, 52 "a_position"); 53 a_position->data.location = VERT_ATTRIB_GENERIC0; 54 55 v_position = nir_variable_create(b.shader, nir_var_shader_out, vec4, 56 "gl_Position"); 57 v_position->data.location = VARYING_SLOT_POS; 58 59 nir_copy_var(&b, v_position, a_position); 60 61 return b.shader; 62} 63 64/* simple passthrough shader */ 65static nir_shader * 66build_nir_fs(void) 67{ 68 nir_builder b; 69 70 nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, NULL); 71 b.shader->info->name = ralloc_asprintf(b.shader, 72 "meta_fast_clear_noop_fs"); 73 74 return b.shader; 75} 76 77static VkResult 78create_pass(struct radv_device *device) 79{ 80 VkResult result; 81 VkDevice device_h = radv_device_to_handle(device); 82 const VkAllocationCallbacks *alloc = &device->meta_state.alloc; 83 VkAttachmentDescription attachment; 84 85 attachment.format = VK_FORMAT_UNDEFINED; 86 attachment.samples = 1; 87 attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 88 attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 89 attachment.initialLayout = VK_IMAGE_LAYOUT_GENERAL; 90 attachment.finalLayout = VK_IMAGE_LAYOUT_GENERAL; 91 92 result = radv_CreateRenderPass(device_h, 93 &(VkRenderPassCreateInfo) { 94 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 95 .attachmentCount = 1, 96 .pAttachments = &attachment, 97 .subpassCount = 1, 98 .pSubpasses = &(VkSubpassDescription) { 99 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, 100 .inputAttachmentCount = 0, 101 .colorAttachmentCount = 1, 102 .pColorAttachments = (VkAttachmentReference[]) { 103 { 104 .attachment = 0, 105 .layout = VK_IMAGE_LAYOUT_GENERAL, 106 }, 107 }, 108 .pResolveAttachments = NULL, 109 .pDepthStencilAttachment = &(VkAttachmentReference) { 110 .attachment = VK_ATTACHMENT_UNUSED, 111 }, 112 .preserveAttachmentCount = 0, 113 .pPreserveAttachments = NULL, 114 }, 115 .dependencyCount = 0, 116 }, 117 alloc, 118 &device->meta_state.fast_clear_flush.pass); 119 120 return result; 121} 122 123static VkResult 124create_pipeline(struct radv_device *device, 125 VkShaderModule vs_module_h) 126{ 127 VkResult result; 128 VkDevice device_h = radv_device_to_handle(device); 129 130 struct radv_shader_module fs_module = { 131 .nir = build_nir_fs(), 132 }; 133 134 if (!fs_module.nir) { 135 /* XXX: Need more accurate error */ 136 result = VK_ERROR_OUT_OF_HOST_MEMORY; 137 goto cleanup; 138 } 139 140 const VkPipelineShaderStageCreateInfo stages[2] = { 141 { 142 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 143 .stage = VK_SHADER_STAGE_VERTEX_BIT, 144 .module = vs_module_h, 145 .pName = "main", 146 }, 147 { 148 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 149 .stage = VK_SHADER_STAGE_FRAGMENT_BIT, 150 .module = radv_shader_module_to_handle(&fs_module), 151 .pName = "main", 152 }, 153 }; 154 155 const VkPipelineVertexInputStateCreateInfo vi_state = { 156 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 157 .vertexBindingDescriptionCount = 1, 158 .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) { 159 { 160 .binding = 0, 161 .stride = sizeof(struct vertex_attrs), 162 .inputRate = VK_VERTEX_INPUT_RATE_VERTEX 163 }, 164 }, 165 .vertexAttributeDescriptionCount = 1, 166 .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) { 167 { 168 /* Position */ 169 .location = 0, 170 .binding = 0, 171 .format = VK_FORMAT_R32G32_SFLOAT, 172 .offset = offsetof(struct vertex_attrs, position), 173 }, 174 } 175 }; 176 177 const VkPipelineInputAssemblyStateCreateInfo ia_state = { 178 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 179 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 180 .primitiveRestartEnable = false, 181 }; 182 183 const VkPipelineColorBlendStateCreateInfo blend_state = { 184 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 185 .logicOpEnable = false, 186 .attachmentCount = 1, 187 .pAttachments = (VkPipelineColorBlendAttachmentState []) { 188 { 189 .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | 190 VK_COLOR_COMPONENT_G_BIT | 191 VK_COLOR_COMPONENT_B_BIT | 192 VK_COLOR_COMPONENT_A_BIT, 193 }, 194 } 195 }; 196 const VkPipelineRasterizationStateCreateInfo rs_state = { 197 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 198 .depthClampEnable = false, 199 .rasterizerDiscardEnable = false, 200 .polygonMode = VK_POLYGON_MODE_FILL, 201 .cullMode = VK_CULL_MODE_NONE, 202 .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, 203 }; 204 205 result = radv_graphics_pipeline_create(device_h, 206 radv_pipeline_cache_to_handle(&device->meta_state.cache), 207 &(VkGraphicsPipelineCreateInfo) { 208 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 209 .stageCount = 2, 210 .pStages = stages, 211 212 .pVertexInputState = &vi_state, 213 .pInputAssemblyState = &ia_state, 214 215 .pViewportState = &(VkPipelineViewportStateCreateInfo) { 216 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 217 .viewportCount = 0, 218 .scissorCount = 0, 219 }, 220 .pRasterizationState = &rs_state, 221 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) { 222 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 223 .rasterizationSamples = 1, 224 .sampleShadingEnable = false, 225 .pSampleMask = NULL, 226 .alphaToCoverageEnable = false, 227 .alphaToOneEnable = false, 228 }, 229 .pColorBlendState = &blend_state, 230 .pDynamicState = NULL, 231 .renderPass = device->meta_state.fast_clear_flush.pass, 232 .subpass = 0, 233 }, 234 &(struct radv_graphics_pipeline_create_info) { 235 .use_rectlist = true, 236 .custom_blend_mode = V_028808_CB_ELIMINATE_FAST_CLEAR, 237 }, 238 &device->meta_state.alloc, 239 &device->meta_state.fast_clear_flush.cmask_eliminate_pipeline); 240 if (result != VK_SUCCESS) 241 goto cleanup; 242 243 result = radv_graphics_pipeline_create(device_h, 244 radv_pipeline_cache_to_handle(&device->meta_state.cache), 245 &(VkGraphicsPipelineCreateInfo) { 246 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 247 .stageCount = 2, 248 .pStages = stages, 249 250 .pVertexInputState = &vi_state, 251 .pInputAssemblyState = &ia_state, 252 253 .pViewportState = &(VkPipelineViewportStateCreateInfo) { 254 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 255 .viewportCount = 0, 256 .scissorCount = 0, 257 }, 258 .pRasterizationState = &rs_state, 259 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) { 260 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 261 .rasterizationSamples = 1, 262 .sampleShadingEnable = false, 263 .pSampleMask = NULL, 264 .alphaToCoverageEnable = false, 265 .alphaToOneEnable = false, 266 }, 267 .pColorBlendState = &blend_state, 268 .pDynamicState = NULL, 269 .renderPass = device->meta_state.fast_clear_flush.pass, 270 .subpass = 0, 271 }, 272 &(struct radv_graphics_pipeline_create_info) { 273 .use_rectlist = true, 274 .custom_blend_mode = V_028808_CB_FMASK_DECOMPRESS, 275 }, 276 &device->meta_state.alloc, 277 &device->meta_state.fast_clear_flush.fmask_decompress_pipeline); 278 if (result != VK_SUCCESS) 279 goto cleanup_cmask; 280 281 goto cleanup; 282cleanup_cmask: 283 radv_DestroyPipeline(device_h, device->meta_state.fast_clear_flush.cmask_eliminate_pipeline, &device->meta_state.alloc); 284cleanup: 285 ralloc_free(fs_module.nir); 286 return result; 287} 288 289void 290radv_device_finish_meta_fast_clear_flush_state(struct radv_device *device) 291{ 292 struct radv_meta_state *state = &device->meta_state; 293 VkDevice device_h = radv_device_to_handle(device); 294 VkRenderPass pass_h = device->meta_state.fast_clear_flush.pass; 295 const VkAllocationCallbacks *alloc = &device->meta_state.alloc; 296 297 if (pass_h) 298 radv_DestroyRenderPass(device_h, pass_h, 299 &device->meta_state.alloc); 300 301 VkPipeline pipeline_h = state->fast_clear_flush.cmask_eliminate_pipeline; 302 if (pipeline_h) { 303 radv_DestroyPipeline(device_h, pipeline_h, alloc); 304 } 305 306 pipeline_h = state->fast_clear_flush.fmask_decompress_pipeline; 307 if (pipeline_h) { 308 radv_DestroyPipeline(device_h, pipeline_h, alloc); 309 } 310} 311 312VkResult 313radv_device_init_meta_fast_clear_flush_state(struct radv_device *device) 314{ 315 VkResult res = VK_SUCCESS; 316 317 zero(device->meta_state.fast_clear_flush); 318 319 struct radv_shader_module vs_module = { .nir = build_nir_vs() }; 320 if (!vs_module.nir) { 321 /* XXX: Need more accurate error */ 322 res = VK_ERROR_OUT_OF_HOST_MEMORY; 323 goto fail; 324 } 325 326 res = create_pass(device); 327 if (res != VK_SUCCESS) 328 goto fail; 329 330 VkShaderModule vs_module_h = radv_shader_module_to_handle(&vs_module); 331 res = create_pipeline(device, vs_module_h); 332 if (res != VK_SUCCESS) 333 goto fail; 334 335 goto cleanup; 336 337fail: 338 radv_device_finish_meta_fast_clear_flush_state(device); 339 340cleanup: 341 ralloc_free(vs_module.nir); 342 343 return res; 344} 345 346static void 347emit_fast_clear_flush(struct radv_cmd_buffer *cmd_buffer, 348 const VkExtent2D *resolve_extent, 349 bool fmask_decompress) 350{ 351 struct radv_device *device = cmd_buffer->device; 352 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer); 353 uint32_t offset; 354 const struct vertex_attrs vertex_data[3] = { 355 { 356 .position = { 357 0, 358 0, 359 }, 360 }, 361 { 362 .position = { 363 0, 364 resolve_extent->height, 365 }, 366 }, 367 { 368 .position = { 369 resolve_extent->width, 370 0, 371 }, 372 }, 373 }; 374 375 cmd_buffer->state.flush_bits |= (RADV_CMD_FLAG_FLUSH_AND_INV_CB | 376 RADV_CMD_FLAG_FLUSH_AND_INV_CB_META); 377 radv_cmd_buffer_upload_data(cmd_buffer, sizeof(vertex_data), 16, vertex_data, &offset); 378 struct radv_buffer vertex_buffer = { 379 .device = device, 380 .size = sizeof(vertex_data), 381 .bo = cmd_buffer->upload.upload_bo, 382 .offset = offset, 383 }; 384 385 VkBuffer vertex_buffer_h = radv_buffer_to_handle(&vertex_buffer); 386 387 radv_CmdBindVertexBuffers(cmd_buffer_h, 388 /*firstBinding*/ 0, 389 /*bindingCount*/ 1, 390 (VkBuffer[]) { vertex_buffer_h }, 391 (VkDeviceSize[]) { 0 }); 392 393 VkPipeline pipeline_h; 394 if (fmask_decompress) 395 pipeline_h = device->meta_state.fast_clear_flush.fmask_decompress_pipeline; 396 else 397 pipeline_h = device->meta_state.fast_clear_flush.cmask_eliminate_pipeline; 398 RADV_FROM_HANDLE(radv_pipeline, pipeline, pipeline_h); 399 400 if (cmd_buffer->state.pipeline != pipeline) { 401 radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, 402 pipeline_h); 403 } 404 405 radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0); 406 cmd_buffer->state.flush_bits |= (RADV_CMD_FLAG_FLUSH_AND_INV_CB | 407 RADV_CMD_FLAG_FLUSH_AND_INV_CB_META); 408 si_emit_cache_flush(cmd_buffer); 409} 410 411/** 412 */ 413void 414radv_fast_clear_flush_image_inplace(struct radv_cmd_buffer *cmd_buffer, 415 struct radv_image *image) 416{ 417 struct radv_meta_saved_state saved_state; 418 struct radv_meta_saved_pass_state saved_pass_state; 419 VkDevice device_h = radv_device_to_handle(cmd_buffer->device); 420 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer); 421 422 assert(cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL); 423 radv_meta_save_pass(&saved_pass_state, cmd_buffer); 424 radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer); 425 426 struct radv_image_view iview; 427 radv_image_view_init(&iview, cmd_buffer->device, 428 &(VkImageViewCreateInfo) { 429 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 430 .image = radv_image_to_handle(image), 431 .format = image->vk_format, 432 .subresourceRange = { 433 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 434 .baseMipLevel = 0, 435 .levelCount = 1, 436 .baseArrayLayer = 0, 437 .layerCount = 1, 438 }, 439 }, 440 cmd_buffer, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); 441 442 VkFramebuffer fb_h; 443 radv_CreateFramebuffer(device_h, 444 &(VkFramebufferCreateInfo) { 445 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 446 .attachmentCount = 1, 447 .pAttachments = (VkImageView[]) { 448 radv_image_view_to_handle(&iview) 449 }, 450 .width = image->extent.width, 451 .height = image->extent.height, 452 .layers = 1 453 }, 454 &cmd_buffer->pool->alloc, 455 &fb_h); 456 457 radv_CmdBeginRenderPass(cmd_buffer_h, 458 &(VkRenderPassBeginInfo) { 459 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 460 .renderPass = cmd_buffer->device->meta_state.fast_clear_flush.pass, 461 .framebuffer = fb_h, 462 .renderArea = { 463 .offset = { 464 0, 465 0, 466 }, 467 .extent = { 468 image->extent.width, 469 image->extent.height, 470 } 471 }, 472 .clearValueCount = 0, 473 .pClearValues = NULL, 474 }, 475 VK_SUBPASS_CONTENTS_INLINE); 476 477 emit_fast_clear_flush(cmd_buffer, 478 &(VkExtent2D) { image->extent.width, image->extent.height }, 479 image->fmask.size > 0); 480 radv_CmdEndRenderPass(cmd_buffer_h); 481 482 radv_DestroyFramebuffer(device_h, fb_h, 483 &cmd_buffer->pool->alloc); 484 485 radv_meta_restore(&saved_state, cmd_buffer); 486 radv_meta_restore_pass(&saved_pass_state, cmd_buffer); 487} 488