panvk_cmd_buffer.c revision 7ec681f3
1/* 2 * Copyright © 2021 Collabora Ltd. 3 * 4 * Derived from tu_cmd_buffer.c which is: 5 * Copyright © 2016 Red Hat. 6 * Copyright © 2016 Bas Nieuwenhuizen 7 * Copyright © 2015 Intel Corporation 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the next 17 * paragraph) shall be included in all copies or substantial portions of the 18 * Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 */ 28 29#include "panvk_private.h" 30#include "panfrost-quirks.h" 31 32#include "pan_encoder.h" 33 34#include "util/rounding.h" 35#include "vk_format.h" 36 37void 38panvk_CmdBindVertexBuffers(VkCommandBuffer commandBuffer, 39 uint32_t firstBinding, 40 uint32_t bindingCount, 41 const VkBuffer *pBuffers, 42 const VkDeviceSize *pOffsets) 43{ 44 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 45 46 assert(firstBinding + bindingCount <= MAX_VBS); 47 48 for (uint32_t i = 0; i < bindingCount; i++) { 49 struct panvk_buffer *buf = panvk_buffer_from_handle(pBuffers[i]); 50 51 cmdbuf->state.vb.bufs[firstBinding + i].address = buf->bo->ptr.gpu + pOffsets[i]; 52 cmdbuf->state.vb.bufs[firstBinding + i].size = buf->size - pOffsets[i]; 53 } 54 cmdbuf->state.vb.count = MAX2(cmdbuf->state.vb.count, firstBinding + bindingCount); 55 cmdbuf->state.vb.attrib_bufs = cmdbuf->state.vb.attribs = 0; 56} 57 58void 59panvk_CmdBindIndexBuffer(VkCommandBuffer commandBuffer, 60 VkBuffer buffer, 61 VkDeviceSize offset, 62 VkIndexType indexType) 63{ 64 panvk_stub(); 65} 66 67void 68panvk_CmdBindDescriptorSets(VkCommandBuffer commandBuffer, 69 VkPipelineBindPoint pipelineBindPoint, 70 VkPipelineLayout _layout, 71 uint32_t firstSet, 72 uint32_t descriptorSetCount, 73 const VkDescriptorSet *pDescriptorSets, 74 uint32_t dynamicOffsetCount, 75 const uint32_t *pDynamicOffsets) 76{ 77 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 78 VK_FROM_HANDLE(panvk_pipeline_layout, layout, _layout); 79 80 struct panvk_descriptor_state *descriptors_state = 81 &cmdbuf->bind_points[pipelineBindPoint].desc_state; 82 83 for (unsigned i = 0; i < descriptorSetCount; ++i) { 84 unsigned idx = i + firstSet; 85 VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorSets[i]); 86 87 descriptors_state->sets[idx].set = set; 88 89 if (layout->num_dynoffsets) { 90 assert(dynamicOffsetCount >= set->layout->num_dynoffsets); 91 92 descriptors_state->sets[idx].dynoffsets = 93 pan_pool_alloc_aligned(&cmdbuf->desc_pool.base, 94 ALIGN(layout->num_dynoffsets, 4) * 95 sizeof(*pDynamicOffsets), 96 16); 97 memcpy(descriptors_state->sets[idx].dynoffsets.cpu, 98 pDynamicOffsets, 99 sizeof(*pDynamicOffsets) * set->layout->num_dynoffsets); 100 dynamicOffsetCount -= set->layout->num_dynoffsets; 101 pDynamicOffsets += set->layout->num_dynoffsets; 102 } 103 104 if (set->layout->num_ubos || set->layout->num_dynoffsets) 105 descriptors_state->ubos = 0; 106 107 if (set->layout->num_textures) 108 descriptors_state->textures = 0; 109 110 if (set->layout->num_samplers) 111 descriptors_state->samplers = 0; 112 } 113 114 assert(!dynamicOffsetCount); 115} 116 117void 118panvk_CmdPushConstants(VkCommandBuffer commandBuffer, 119 VkPipelineLayout layout, 120 VkShaderStageFlags stageFlags, 121 uint32_t offset, 122 uint32_t size, 123 const void *pValues) 124{ 125 panvk_stub(); 126} 127 128void 129panvk_CmdBindPipeline(VkCommandBuffer commandBuffer, 130 VkPipelineBindPoint pipelineBindPoint, 131 VkPipeline _pipeline) 132{ 133 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 134 VK_FROM_HANDLE(panvk_pipeline, pipeline, _pipeline); 135 136 cmdbuf->bind_points[pipelineBindPoint].pipeline = pipeline; 137 cmdbuf->state.fs_rsd = 0; 138 memset(cmdbuf->bind_points[pipelineBindPoint].desc_state.sysvals, 0, 139 sizeof(cmdbuf->bind_points[0].desc_state.sysvals)); 140 141 if (pipelineBindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS) { 142 cmdbuf->state.varyings = pipeline->varyings; 143 144 if (!(pipeline->dynamic_state_mask & BITFIELD_BIT(VK_DYNAMIC_STATE_VIEWPORT))) 145 cmdbuf->state.viewport = pipeline->viewport; 146 if (!(pipeline->dynamic_state_mask & BITFIELD_BIT(VK_DYNAMIC_STATE_SCISSOR))) 147 cmdbuf->state.scissor = pipeline->scissor; 148 } 149 150 /* Sysvals are passed through UBOs, we need dirty the UBO array if the 151 * pipeline contain shaders using sysvals. 152 */ 153 if (pipeline->num_sysvals) 154 cmdbuf->bind_points[pipelineBindPoint].desc_state.ubos = 0; 155} 156 157void 158panvk_CmdSetViewport(VkCommandBuffer commandBuffer, 159 uint32_t firstViewport, 160 uint32_t viewportCount, 161 const VkViewport *pViewports) 162{ 163 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 164 assert(viewportCount == 1); 165 assert(!firstViewport); 166 167 cmdbuf->state.viewport = pViewports[0]; 168 cmdbuf->state.vpd = 0; 169 cmdbuf->state.dirty |= PANVK_DYNAMIC_VIEWPORT; 170} 171 172void 173panvk_CmdSetScissor(VkCommandBuffer commandBuffer, 174 uint32_t firstScissor, 175 uint32_t scissorCount, 176 const VkRect2D *pScissors) 177{ 178 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 179 assert(scissorCount == 1); 180 assert(!firstScissor); 181 182 cmdbuf->state.scissor = pScissors[0]; 183 cmdbuf->state.vpd = 0; 184 cmdbuf->state.dirty |= PANVK_DYNAMIC_SCISSOR; 185} 186 187void 188panvk_CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) 189{ 190 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 191 192 cmdbuf->state.rast.line_width = lineWidth; 193 cmdbuf->state.dirty |= PANVK_DYNAMIC_LINE_WIDTH; 194} 195 196void 197panvk_CmdSetDepthBias(VkCommandBuffer commandBuffer, 198 float depthBiasConstantFactor, 199 float depthBiasClamp, 200 float depthBiasSlopeFactor) 201{ 202 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 203 204 cmdbuf->state.rast.depth_bias.constant_factor = depthBiasConstantFactor; 205 cmdbuf->state.rast.depth_bias.clamp = depthBiasClamp; 206 cmdbuf->state.rast.depth_bias.slope_factor = depthBiasSlopeFactor; 207 cmdbuf->state.dirty |= PANVK_DYNAMIC_DEPTH_BIAS; 208 cmdbuf->state.fs_rsd = 0; 209} 210 211void 212panvk_CmdSetBlendConstants(VkCommandBuffer commandBuffer, 213 const float blendConstants[4]) 214{ 215 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 216 217 for (unsigned i = 0; i < 4; i++) 218 cmdbuf->state.blend.constants[i] = CLAMP(blendConstants[i], 0.0f, 1.0f); 219 220 cmdbuf->state.dirty |= PANVK_DYNAMIC_BLEND_CONSTANTS; 221 cmdbuf->state.fs_rsd = 0; 222} 223 224void 225panvk_CmdSetDepthBounds(VkCommandBuffer commandBuffer, 226 float minDepthBounds, 227 float maxDepthBounds) 228{ 229 panvk_stub(); 230} 231 232void 233panvk_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, 234 VkStencilFaceFlags faceMask, 235 uint32_t compareMask) 236{ 237 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 238 239 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) 240 cmdbuf->state.zs.s_front.compare_mask = compareMask; 241 242 if (faceMask & VK_STENCIL_FACE_BACK_BIT) 243 cmdbuf->state.zs.s_back.compare_mask = compareMask; 244 245 cmdbuf->state.dirty |= PANVK_DYNAMIC_STENCIL_COMPARE_MASK; 246 cmdbuf->state.fs_rsd = 0; 247} 248 249void 250panvk_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, 251 VkStencilFaceFlags faceMask, 252 uint32_t writeMask) 253{ 254 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 255 256 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) 257 cmdbuf->state.zs.s_front.write_mask = writeMask; 258 259 if (faceMask & VK_STENCIL_FACE_BACK_BIT) 260 cmdbuf->state.zs.s_back.write_mask = writeMask; 261 262 cmdbuf->state.dirty |= PANVK_DYNAMIC_STENCIL_WRITE_MASK; 263 cmdbuf->state.fs_rsd = 0; 264} 265 266void 267panvk_CmdSetStencilReference(VkCommandBuffer commandBuffer, 268 VkStencilFaceFlags faceMask, 269 uint32_t reference) 270{ 271 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 272 273 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) 274 cmdbuf->state.zs.s_front.ref = reference; 275 276 if (faceMask & VK_STENCIL_FACE_BACK_BIT) 277 cmdbuf->state.zs.s_back.ref = reference; 278 279 cmdbuf->state.dirty |= PANVK_DYNAMIC_STENCIL_REFERENCE; 280 cmdbuf->state.fs_rsd = 0; 281} 282 283void 284panvk_CmdExecuteCommands(VkCommandBuffer commandBuffer, 285 uint32_t commandBufferCount, 286 const VkCommandBuffer *pCmdBuffers) 287{ 288 panvk_stub(); 289} 290 291VkResult 292panvk_CreateCommandPool(VkDevice _device, 293 const VkCommandPoolCreateInfo *pCreateInfo, 294 const VkAllocationCallbacks *pAllocator, 295 VkCommandPool *pCmdPool) 296{ 297 VK_FROM_HANDLE(panvk_device, device, _device); 298 struct panvk_cmd_pool *pool; 299 300 pool = vk_object_alloc(&device->vk, pAllocator, sizeof(*pool), 301 VK_OBJECT_TYPE_COMMAND_POOL); 302 if (pool == NULL) 303 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 304 305 if (pAllocator) 306 pool->alloc = *pAllocator; 307 else 308 pool->alloc = device->vk.alloc; 309 310 list_inithead(&pool->active_cmd_buffers); 311 list_inithead(&pool->free_cmd_buffers); 312 313 pool->queue_family_index = pCreateInfo->queueFamilyIndex; 314 panvk_bo_pool_init(&pool->desc_bo_pool); 315 panvk_bo_pool_init(&pool->varying_bo_pool); 316 panvk_bo_pool_init(&pool->tls_bo_pool); 317 *pCmdPool = panvk_cmd_pool_to_handle(pool); 318 return VK_SUCCESS; 319} 320 321static void 322panvk_cmd_prepare_clear_values(struct panvk_cmd_buffer *cmdbuf, 323 const VkClearValue *in) 324{ 325 for (unsigned i = 0; i < cmdbuf->state.pass->attachment_count; i++) { 326 const struct panvk_render_pass_attachment *attachment = 327 &cmdbuf->state.pass->attachments[i]; 328 enum pipe_format fmt = attachment->format; 329 330 if (util_format_is_depth_or_stencil(fmt)) { 331 if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR || 332 attachment->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { 333 cmdbuf->state.clear[i].depth = in[i].depthStencil.depth; 334 cmdbuf->state.clear[i].stencil = in[i].depthStencil.stencil; 335 } else { 336 cmdbuf->state.clear[i].depth = 0; 337 cmdbuf->state.clear[i].stencil = 0; 338 } 339 } else { 340 if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { 341 union pipe_color_union *col = (union pipe_color_union *) &in[i].color; 342 pan_pack_color(cmdbuf->state.clear[i].color, col, fmt, false); 343 } else { 344 memset(cmdbuf->state.clear[i].color, 0, sizeof(cmdbuf->state.clear[0].color)); 345 } 346 } 347 } 348} 349 350void 351panvk_cmd_fb_info_set_subpass(struct panvk_cmd_buffer *cmdbuf) 352{ 353 const struct panvk_subpass *subpass = cmdbuf->state.subpass; 354 struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info; 355 const struct panvk_framebuffer *fb = cmdbuf->state.framebuffer; 356 const struct panvk_clear_value *clears = cmdbuf->state.clear; 357 struct panvk_image_view *view; 358 359 fbinfo->nr_samples = 1; 360 fbinfo->rt_count = subpass->color_count; 361 memset(&fbinfo->bifrost.pre_post.dcds, 0, sizeof(fbinfo->bifrost.pre_post.dcds)); 362 363 for (unsigned cb = 0; cb < subpass->color_count; cb++) { 364 int idx = subpass->color_attachments[cb].idx; 365 view = idx != VK_ATTACHMENT_UNUSED ? 366 fb->attachments[idx].iview : NULL; 367 if (!view) 368 continue; 369 fbinfo->rts[cb].view = &view->pview; 370 fbinfo->rts[cb].clear = subpass->color_attachments[cb].clear; 371 fbinfo->rts[cb].preload = subpass->color_attachments[cb].preload; 372 fbinfo->rts[cb].crc_valid = &cmdbuf->state.fb.crc_valid[cb]; 373 374 memcpy(fbinfo->rts[cb].clear_value, clears[idx].color, 375 sizeof(fbinfo->rts[cb].clear_value)); 376 fbinfo->nr_samples = 377 MAX2(fbinfo->nr_samples, view->pview.image->layout.nr_samples); 378 } 379 380 if (subpass->zs_attachment.idx != VK_ATTACHMENT_UNUSED) { 381 view = fb->attachments[subpass->zs_attachment.idx].iview; 382 const struct util_format_description *fdesc = 383 util_format_description(view->pview.format); 384 385 fbinfo->nr_samples = 386 MAX2(fbinfo->nr_samples, view->pview.image->layout.nr_samples); 387 388 if (util_format_has_depth(fdesc)) { 389 fbinfo->zs.clear.z = subpass->zs_attachment.clear; 390 fbinfo->zs.clear_value.depth = clears[subpass->zs_attachment.idx].depth; 391 fbinfo->zs.view.zs = &view->pview; 392 } 393 394 if (util_format_has_stencil(fdesc)) { 395 fbinfo->zs.clear.s = subpass->zs_attachment.clear; 396 fbinfo->zs.clear_value.stencil = clears[subpass->zs_attachment.idx].stencil; 397 if (!fbinfo->zs.view.zs) 398 fbinfo->zs.view.s = &view->pview; 399 } 400 } 401} 402 403void 404panvk_cmd_fb_info_init(struct panvk_cmd_buffer *cmdbuf) 405{ 406 struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info; 407 const struct panvk_framebuffer *fb = cmdbuf->state.framebuffer; 408 409 memset(cmdbuf->state.fb.crc_valid, 0, sizeof(cmdbuf->state.fb.crc_valid)); 410 411 *fbinfo = (struct pan_fb_info) { 412 .width = fb->width, 413 .height = fb->height, 414 .extent.maxx = fb->width - 1, 415 .extent.maxy = fb->height - 1, 416 }; 417} 418 419void 420panvk_CmdBeginRenderPass2(VkCommandBuffer commandBuffer, 421 const VkRenderPassBeginInfo *pRenderPassBegin, 422 const VkSubpassBeginInfo *pSubpassBeginInfo) 423{ 424 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 425 VK_FROM_HANDLE(panvk_render_pass, pass, pRenderPassBegin->renderPass); 426 VK_FROM_HANDLE(panvk_framebuffer, fb, pRenderPassBegin->framebuffer); 427 428 cmdbuf->state.pass = pass; 429 cmdbuf->state.subpass = pass->subpasses; 430 cmdbuf->state.framebuffer = fb; 431 cmdbuf->state.render_area = pRenderPassBegin->renderArea; 432 cmdbuf->state.batch = vk_zalloc(&cmdbuf->pool->alloc, 433 sizeof(*cmdbuf->state.batch), 8, 434 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 435 util_dynarray_init(&cmdbuf->state.batch->jobs, NULL); 436 util_dynarray_init(&cmdbuf->state.batch->event_ops, NULL); 437 assert(pRenderPassBegin->clearValueCount <= pass->attachment_count); 438 cmdbuf->state.clear = 439 vk_zalloc(&cmdbuf->pool->alloc, 440 sizeof(*cmdbuf->state.clear) * pass->attachment_count, 441 8, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 442 panvk_cmd_prepare_clear_values(cmdbuf, pRenderPassBegin->pClearValues); 443 panvk_cmd_fb_info_init(cmdbuf); 444 panvk_cmd_fb_info_set_subpass(cmdbuf); 445} 446 447void 448panvk_CmdBeginRenderPass(VkCommandBuffer cmd, 449 const VkRenderPassBeginInfo *info, 450 VkSubpassContents contents) 451{ 452 VkSubpassBeginInfo subpass_info = { 453 .sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO, 454 .contents = contents 455 }; 456 457 return panvk_CmdBeginRenderPass2(cmd, info, &subpass_info); 458} 459 460void 461panvk_cmd_preload_fb_after_batch_split(struct panvk_cmd_buffer *cmdbuf) 462{ 463 for (unsigned i = 0; i < cmdbuf->state.fb.info.rt_count; i++) { 464 if (cmdbuf->state.fb.info.rts[i].view) { 465 cmdbuf->state.fb.info.rts[i].clear = false; 466 cmdbuf->state.fb.info.rts[i].preload = true; 467 } 468 } 469 470 if (cmdbuf->state.fb.info.zs.view.zs) { 471 cmdbuf->state.fb.info.zs.clear.z = false; 472 cmdbuf->state.fb.info.zs.preload.z = true; 473 } 474 475 if (cmdbuf->state.fb.info.zs.view.s || 476 (cmdbuf->state.fb.info.zs.view.zs && 477 util_format_is_depth_and_stencil(cmdbuf->state.fb.info.zs.view.zs->format))) { 478 cmdbuf->state.fb.info.zs.clear.s = false; 479 cmdbuf->state.fb.info.zs.preload.s = true; 480 } 481} 482 483struct panvk_batch * 484panvk_cmd_open_batch(struct panvk_cmd_buffer *cmdbuf) 485{ 486 assert(!cmdbuf->state.batch); 487 cmdbuf->state.batch = vk_zalloc(&cmdbuf->pool->alloc, 488 sizeof(*cmdbuf->state.batch), 8, 489 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 490 assert(cmdbuf->state.batch); 491 return cmdbuf->state.batch; 492} 493 494void 495panvk_CmdDrawIndexed(VkCommandBuffer commandBuffer, 496 uint32_t indexCount, 497 uint32_t instanceCount, 498 uint32_t firstIndex, 499 int32_t vertexOffset, 500 uint32_t firstInstance) 501{ 502 panvk_stub(); 503} 504 505void 506panvk_CmdDrawIndirect(VkCommandBuffer commandBuffer, 507 VkBuffer _buffer, 508 VkDeviceSize offset, 509 uint32_t drawCount, 510 uint32_t stride) 511{ 512 panvk_stub(); 513} 514 515void 516panvk_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, 517 VkBuffer _buffer, 518 VkDeviceSize offset, 519 uint32_t drawCount, 520 uint32_t stride) 521{ 522 panvk_stub(); 523} 524 525void 526panvk_CmdDispatchBase(VkCommandBuffer commandBuffer, 527 uint32_t base_x, 528 uint32_t base_y, 529 uint32_t base_z, 530 uint32_t x, 531 uint32_t y, 532 uint32_t z) 533{ 534 panvk_stub(); 535} 536 537void 538panvk_CmdDispatch(VkCommandBuffer commandBuffer, 539 uint32_t x, 540 uint32_t y, 541 uint32_t z) 542{ 543 panvk_stub(); 544} 545 546void 547panvk_CmdDispatchIndirect(VkCommandBuffer commandBuffer, 548 VkBuffer _buffer, 549 VkDeviceSize offset) 550{ 551 panvk_stub(); 552} 553 554void 555panvk_CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) 556{ 557 panvk_stub(); 558} 559