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 static VkResult 32 create_pass(struct radv_device *device, 33 uint32_t samples, 34 VkRenderPass *pass) 35 { 36 VkResult result; 37 VkDevice device_h = radv_device_to_handle(device); 38 const VkAllocationCallbacks *alloc = &device->meta_state.alloc; 39 VkAttachmentDescription attachment; 40 41 attachment.flags = 0; 42 attachment.format = VK_FORMAT_D32_SFLOAT_S8_UINT; 43 attachment.samples = samples; 44 attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 45 attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 46 attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 47 attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; 48 attachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 49 attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 50 51 result = radv_CreateRenderPass(device_h, 52 &(VkRenderPassCreateInfo) { 53 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 54 .attachmentCount = 1, 55 .pAttachments = &attachment, 56 .subpassCount = 1, 57 .pSubpasses = &(VkSubpassDescription) { 58 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, 59 .inputAttachmentCount = 0, 60 .colorAttachmentCount = 0, 61 .pColorAttachments = NULL, 62 .pResolveAttachments = NULL, 63 .pDepthStencilAttachment = &(VkAttachmentReference) { 64 .attachment = 0, 65 .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 66 }, 67 .preserveAttachmentCount = 0, 68 .pPreserveAttachments = NULL, 69 }, 70 .dependencyCount = 0, 71 }, 72 alloc, 73 pass); 74 75 return result; 76 } 77 78 static VkResult 79 create_pipeline_layout(struct radv_device *device, VkPipelineLayout *layout) 80 { 81 VkPipelineLayoutCreateInfo pl_create_info = { 82 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 83 .setLayoutCount = 0, 84 .pSetLayouts = NULL, 85 .pushConstantRangeCount = 0, 86 .pPushConstantRanges = NULL, 87 }; 88 89 return radv_CreatePipelineLayout(radv_device_to_handle(device), 90 &pl_create_info, 91 &device->meta_state.alloc, 92 layout); 93 } 94 95 static VkResult 96 create_pipeline(struct radv_device *device, 97 VkShaderModule vs_module_h, 98 uint32_t samples, 99 VkRenderPass pass, 100 VkPipelineLayout layout, 101 VkPipeline *decompress_pipeline, 102 VkPipeline *resummarize_pipeline) 103 { 104 VkResult result; 105 VkDevice device_h = radv_device_to_handle(device); 106 107 struct radv_shader_module fs_module = { 108 .nir = radv_meta_build_nir_fs_noop(), 109 }; 110 111 if (!fs_module.nir) { 112 /* XXX: Need more accurate error */ 113 result = VK_ERROR_OUT_OF_HOST_MEMORY; 114 goto cleanup; 115 } 116 117 const VkGraphicsPipelineCreateInfo pipeline_create_info = { 118 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 119 .stageCount = 2, 120 .pStages = (VkPipelineShaderStageCreateInfo[]) { 121 { 122 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 123 .stage = VK_SHADER_STAGE_VERTEX_BIT, 124 .module = vs_module_h, 125 .pName = "main", 126 }, 127 { 128 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 129 .stage = VK_SHADER_STAGE_FRAGMENT_BIT, 130 .module = radv_shader_module_to_handle(&fs_module), 131 .pName = "main", 132 }, 133 }, 134 .pVertexInputState = &(VkPipelineVertexInputStateCreateInfo) { 135 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 136 .vertexBindingDescriptionCount = 0, 137 .vertexAttributeDescriptionCount = 0, 138 }, 139 .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) { 140 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 141 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 142 .primitiveRestartEnable = false, 143 }, 144 .pViewportState = &(VkPipelineViewportStateCreateInfo) { 145 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 146 .viewportCount = 1, 147 .scissorCount = 1, 148 }, 149 .pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) { 150 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 151 .depthClampEnable = false, 152 .rasterizerDiscardEnable = false, 153 .polygonMode = VK_POLYGON_MODE_FILL, 154 .cullMode = VK_CULL_MODE_NONE, 155 .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, 156 }, 157 .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) { 158 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 159 .rasterizationSamples = samples, 160 .sampleShadingEnable = false, 161 .pSampleMask = NULL, 162 .alphaToCoverageEnable = false, 163 .alphaToOneEnable = false, 164 }, 165 .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) { 166 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 167 .logicOpEnable = false, 168 .attachmentCount = 0, 169 .pAttachments = NULL, 170 }, 171 .pDepthStencilState = &(VkPipelineDepthStencilStateCreateInfo) { 172 .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 173 .depthTestEnable = false, 174 .depthWriteEnable = false, 175 .depthBoundsTestEnable = false, 176 .stencilTestEnable = false, 177 }, 178 .pDynamicState = &(VkPipelineDynamicStateCreateInfo) { 179 .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, 180 .dynamicStateCount = 2, 181 .pDynamicStates = (VkDynamicState[]) { 182 VK_DYNAMIC_STATE_VIEWPORT, 183 VK_DYNAMIC_STATE_SCISSOR, 184 }, 185 }, 186 .layout = layout, 187 .renderPass = pass, 188 .subpass = 0, 189 }; 190 191 result = radv_graphics_pipeline_create(device_h, 192 radv_pipeline_cache_to_handle(&device->meta_state.cache), 193 &pipeline_create_info, 194 &(struct radv_graphics_pipeline_create_info) { 195 .use_rectlist = true, 196 .db_flush_depth_inplace = true, 197 .db_flush_stencil_inplace = true, 198 }, 199 &device->meta_state.alloc, 200 decompress_pipeline); 201 if (result != VK_SUCCESS) 202 goto cleanup; 203 204 result = radv_graphics_pipeline_create(device_h, 205 radv_pipeline_cache_to_handle(&device->meta_state.cache), 206 &pipeline_create_info, 207 &(struct radv_graphics_pipeline_create_info) { 208 .use_rectlist = true, 209 .db_flush_depth_inplace = true, 210 .db_flush_stencil_inplace = true, 211 .db_resummarize = true, 212 }, 213 &device->meta_state.alloc, 214 resummarize_pipeline); 215 if (result != VK_SUCCESS) 216 goto cleanup; 217 218 goto cleanup; 219 220 cleanup: 221 ralloc_free(fs_module.nir); 222 return result; 223 } 224 225 void 226 radv_device_finish_meta_depth_decomp_state(struct radv_device *device) 227 { 228 struct radv_meta_state *state = &device->meta_state; 229 230 for (uint32_t i = 0; i < ARRAY_SIZE(state->depth_decomp); ++i) { 231 radv_DestroyRenderPass(radv_device_to_handle(device), 232 state->depth_decomp[i].pass, 233 &state->alloc); 234 radv_DestroyPipelineLayout(radv_device_to_handle(device), 235 state->depth_decomp[i].p_layout, 236 &state->alloc); 237 radv_DestroyPipeline(radv_device_to_handle(device), 238 state->depth_decomp[i].decompress_pipeline, 239 &state->alloc); 240 radv_DestroyPipeline(radv_device_to_handle(device), 241 state->depth_decomp[i].resummarize_pipeline, 242 &state->alloc); 243 } 244 } 245 246 VkResult 247 radv_device_init_meta_depth_decomp_state(struct radv_device *device) 248 { 249 struct radv_meta_state *state = &device->meta_state; 250 VkResult res = VK_SUCCESS; 251 252 struct radv_shader_module vs_module = { .nir = radv_meta_build_nir_vs_generate_vertices() }; 253 if (!vs_module.nir) { 254 /* XXX: Need more accurate error */ 255 res = VK_ERROR_OUT_OF_HOST_MEMORY; 256 goto fail; 257 } 258 259 VkShaderModule vs_module_h = radv_shader_module_to_handle(&vs_module); 260 261 for (uint32_t i = 0; i < ARRAY_SIZE(state->depth_decomp); ++i) { 262 uint32_t samples = 1 << i; 263 264 res = create_pass(device, samples, &state->depth_decomp[i].pass); 265 if (res != VK_SUCCESS) 266 goto fail; 267 268 res = create_pipeline_layout(device, 269 &state->depth_decomp[i].p_layout); 270 if (res != VK_SUCCESS) 271 goto fail; 272 273 res = create_pipeline(device, vs_module_h, samples, 274 state->depth_decomp[i].pass, 275 state->depth_decomp[i].p_layout, 276 &state->depth_decomp[i].decompress_pipeline, 277 &state->depth_decomp[i].resummarize_pipeline); 278 if (res != VK_SUCCESS) 279 goto fail; 280 } 281 282 goto cleanup; 283 284 fail: 285 radv_device_finish_meta_depth_decomp_state(device); 286 287 cleanup: 288 ralloc_free(vs_module.nir); 289 290 return res; 291 } 292 293 static void 294 emit_depth_decomp(struct radv_cmd_buffer *cmd_buffer, 295 const VkExtent2D *depth_decomp_extent, 296 VkPipeline pipeline_h) 297 { 298 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer); 299 300 radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS, 301 pipeline_h); 302 303 radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) { 304 .x = 0, 305 .y = 0, 306 .width = depth_decomp_extent->width, 307 .height = depth_decomp_extent->height, 308 .minDepth = 0.0f, 309 .maxDepth = 1.0f 310 }); 311 312 radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkRect2D) { 313 .offset = { 0, 0 }, 314 .extent = *depth_decomp_extent, 315 }); 316 317 radv_CmdDraw(cmd_buffer_h, 3, 1, 0, 0); 318 } 319 320 321 enum radv_depth_op { 322 DEPTH_DECOMPRESS, 323 DEPTH_RESUMMARIZE, 324 }; 325 326 static void radv_process_depth_image_inplace(struct radv_cmd_buffer *cmd_buffer, 327 struct radv_image *image, 328 VkImageSubresourceRange *subresourceRange, 329 enum radv_depth_op op) 330 { 331 struct radv_meta_saved_state saved_state; 332 VkDevice device_h = radv_device_to_handle(cmd_buffer->device); 333 VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer); 334 uint32_t width = radv_minify(image->info.width, 335 subresourceRange->baseMipLevel); 336 uint32_t height = radv_minify(image->info.height, 337 subresourceRange->baseMipLevel); 338 uint32_t samples = image->info.samples; 339 uint32_t samples_log2 = ffs(samples) - 1; 340 struct radv_meta_state *meta_state = &cmd_buffer->device->meta_state; 341 VkPipeline pipeline_h; 342 343 if (!image->surface.htile_size) 344 return; 345 346 radv_meta_save(&saved_state, cmd_buffer, 347 RADV_META_SAVE_GRAPHICS_PIPELINE | 348 RADV_META_SAVE_PASS); 349 350 switch (op) { 351 case DEPTH_DECOMPRESS: 352 pipeline_h = meta_state->depth_decomp[samples_log2].decompress_pipeline; 353 break; 354 case DEPTH_RESUMMARIZE: 355 pipeline_h = meta_state->depth_decomp[samples_log2].resummarize_pipeline; 356 break; 357 default: 358 unreachable("unknown operation"); 359 } 360 361 for (uint32_t layer = 0; layer < radv_get_layerCount(image, subresourceRange); layer++) { 362 struct radv_image_view iview; 363 364 radv_image_view_init(&iview, cmd_buffer->device, 365 &(VkImageViewCreateInfo) { 366 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 367 .image = radv_image_to_handle(image), 368 .viewType = radv_meta_get_view_type(image), 369 .format = image->vk_format, 370 .subresourceRange = { 371 .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, 372 .baseMipLevel = subresourceRange->baseMipLevel, 373 .levelCount = 1, 374 .baseArrayLayer = subresourceRange->baseArrayLayer + layer, 375 .layerCount = 1, 376 }, 377 }); 378 379 380 VkFramebuffer fb_h; 381 radv_CreateFramebuffer(device_h, 382 &(VkFramebufferCreateInfo) { 383 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 384 .attachmentCount = 1, 385 .pAttachments = (VkImageView[]) { 386 radv_image_view_to_handle(&iview) 387 }, 388 .width = width, 389 .height = height, 390 .layers = 1 391 }, 392 &cmd_buffer->pool->alloc, 393 &fb_h); 394 395 radv_CmdBeginRenderPass(cmd_buffer_h, 396 &(VkRenderPassBeginInfo) { 397 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 398 .renderPass = meta_state->depth_decomp[samples_log2].pass, 399 .framebuffer = fb_h, 400 .renderArea = { 401 .offset = { 402 0, 403 0, 404 }, 405 .extent = { 406 width, 407 height, 408 } 409 }, 410 .clearValueCount = 0, 411 .pClearValues = NULL, 412 }, 413 VK_SUBPASS_CONTENTS_INLINE); 414 415 emit_depth_decomp(cmd_buffer, &(VkExtent2D){width, height}, pipeline_h); 416 radv_CmdEndRenderPass(cmd_buffer_h); 417 418 radv_DestroyFramebuffer(device_h, fb_h, 419 &cmd_buffer->pool->alloc); 420 } 421 radv_meta_restore(&saved_state, cmd_buffer); 422 } 423 424 void radv_decompress_depth_image_inplace(struct radv_cmd_buffer *cmd_buffer, 425 struct radv_image *image, 426 VkImageSubresourceRange *subresourceRange) 427 { 428 assert(cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL); 429 radv_process_depth_image_inplace(cmd_buffer, image, subresourceRange, DEPTH_DECOMPRESS); 430 } 431 432 void radv_resummarize_depth_image_inplace(struct radv_cmd_buffer *cmd_buffer, 433 struct radv_image *image, 434 VkImageSubresourceRange *subresourceRange) 435 { 436 assert(cmd_buffer->queue_family_index == RADV_QUEUE_GENERAL); 437 radv_process_depth_image_inplace(cmd_buffer, image, subresourceRange, DEPTH_RESUMMARIZE); 438 } 439