diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c index f4f3896cefa..dcd5bdd3798 100644 --- a/src/broadcom/vulkan/v3dv_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c @@ -2661,15 +2661,15 @@ cmd_buffer_binning_sync_required(struct v3dv_cmd_buffer *cmd_buffer, cmd_buffer->state.barrier.bcl_buffer_access; if (buffer_access) { /* Index buffer read */ - if (indexed && (buffer_access & VK_ACCESS_INDEX_READ_BIT)) + if (indexed && (buffer_access & VK_ACCESS_2_INDEX_READ_BIT)) return true; /* Indirect buffer read */ - if (indirect && (buffer_access & VK_ACCESS_INDIRECT_COMMAND_READ_BIT)) + if (indirect && (buffer_access & VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT)) return true; /* Attribute read */ - if (buffer_access & VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT) { + if (buffer_access & VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT) { const struct v3d_vs_prog_data *prog_data = pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX_BIN]->prog_data.vs; @@ -2680,9 +2680,10 @@ cmd_buffer_binning_sync_required(struct v3dv_cmd_buffer *cmd_buffer, } /* UBO / SSBO read */ - if (buffer_access & (VK_ACCESS_UNIFORM_READ_BIT | - VK_ACCESS_SHADER_READ_BIT | - VK_ACCESS_MEMORY_READ_BIT)) { + if (buffer_access & (VK_ACCESS_2_UNIFORM_READ_BIT | + VK_ACCESS_2_SHADER_READ_BIT | + VK_ACCESS_2_MEMORY_READ_BIT | + VK_ACCESS_2_SHADER_STORAGE_READ_BIT)) { if (vs_bin_maps->ubo_map.num_desc > 0 || vs_bin_maps->ssbo_map.num_desc > 0) { @@ -2696,24 +2697,37 @@ cmd_buffer_binning_sync_required(struct v3dv_cmd_buffer *cmd_buffer, } /* SSBO write */ - if (buffer_access & (VK_ACCESS_SHADER_WRITE_BIT | - VK_ACCESS_MEMORY_WRITE_BIT)) { + if (buffer_access & (VK_ACCESS_2_SHADER_WRITE_BIT | + VK_ACCESS_2_MEMORY_WRITE_BIT | + VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT)) { if (vs_bin_maps->ssbo_map.num_desc > 0) return true; if (gs_bin_maps && gs_bin_maps->ssbo_map.num_desc > 0) return true; } + + /* Texel Buffer read */ + if (buffer_access & (VK_ACCESS_2_SHADER_SAMPLED_READ_BIT)) { + if (vs_bin_maps->texture_map.num_desc > 0) + return true; + + if (gs_bin_maps && gs_bin_maps->texture_map.num_desc > 0) + return true; + } } VkAccessFlags image_access = cmd_buffer->state.barrier.bcl_image_access; if (image_access) { /* Image load / store */ - if (image_access & (VK_ACCESS_SHADER_READ_BIT | - VK_ACCESS_SHADER_WRITE_BIT | - VK_ACCESS_MEMORY_READ_BIT | - VK_ACCESS_MEMORY_WRITE_BIT)) { + if (image_access & (VK_ACCESS_2_SHADER_READ_BIT | + VK_ACCESS_2_SHADER_WRITE_BIT | + VK_ACCESS_2_SHADER_SAMPLED_READ_BIT | + VK_ACCESS_2_SHADER_STORAGE_READ_BIT | + VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT | + VK_ACCESS_2_MEMORY_READ_BIT | + VK_ACCESS_2_MEMORY_WRITE_BIT)) { if (vs_bin_maps->texture_map.num_desc > 0 || vs_bin_maps->sampler_map.num_desc > 0) { return true; @@ -3058,110 +3072,145 @@ v3dv_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, } } -VKAPI_ATTR void VKAPI_CALL -v3dv_CmdPipelineBarrier(VkCommandBuffer commandBuffer, - VkPipelineStageFlags srcStageMask, - VkPipelineStageFlags dstStageMask, - VkDependencyFlags dependencyFlags, - uint32_t memoryBarrierCount, - const VkMemoryBarrier *pMemoryBarriers, - uint32_t bufferBarrierCount, - const VkBufferMemoryBarrier *pBufferBarriers, - uint32_t imageBarrierCount, - const VkImageMemoryBarrier *pImageBarriers) +static void +handle_barrier(VkPipelineStageFlags2 srcStageMask, VkAccessFlags2 srcAccessMask, + VkPipelineStageFlags2 dstStageMask, VkAccessFlags2 dstAccessMask, + bool is_image_barrier, bool is_buffer_barrier, + struct v3dv_barrier_state *state) { - V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer); - - /* We can safely skip barriers for image layout transitions from UNDEFINED - * layout. - */ - if (imageBarrierCount > 0) { - bool all_undefined = true; - for (int i = 0; all_undefined && i < imageBarrierCount; i++) { - if (pImageBarriers[i].oldLayout != VK_IMAGE_LAYOUT_UNDEFINED) - all_undefined = false; - } - if (all_undefined) - imageBarrierCount = 0; - } - - if (memoryBarrierCount + bufferBarrierCount + imageBarrierCount == 0) - return; - /* We only care about barriers between GPU jobs */ - if (srcStageMask == VK_PIPELINE_STAGE_HOST_BIT || - dstStageMask == VK_PIPELINE_STAGE_HOST_BIT) { + if (srcStageMask == VK_PIPELINE_STAGE_2_HOST_BIT || + dstStageMask == VK_PIPELINE_STAGE_2_HOST_BIT) { return; } - /* If we have a recording job, finish it here */ - struct v3dv_job *job = cmd_buffer->state.job; - if (job) - v3dv_cmd_buffer_finish_job(cmd_buffer); - - /* Track the source of the barrier */ + /* Track source of the barrier */ uint8_t src_mask = 0; - if (srcStageMask & (VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)) { + + const VkPipelineStageFlags2 compute_mask = + VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; + if (srcStageMask & (compute_mask | VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT)) src_mask |= V3DV_BARRIER_COMPUTE_BIT; - } - if (srcStageMask & (VK_PIPELINE_STAGE_TRANSFER_BIT | - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)) { + const VkPipelineStageFlags2 transfer_mask = + VK_PIPELINE_STAGE_2_TRANSFER_BIT | + VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT | + VK_PIPELINE_STAGE_2_COPY_BIT | + VK_PIPELINE_STAGE_2_BLIT_BIT | + VK_PIPELINE_STAGE_2_CLEAR_BIT; + if (srcStageMask & (transfer_mask | VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT)) src_mask |= V3DV_BARRIER_TRANSFER_BIT; - } - if (srcStageMask & (~(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | - VK_PIPELINE_STAGE_TRANSFER_BIT))) { + const VkPipelineStageFlags2 graphics_mask = ~(compute_mask | transfer_mask); + if (srcStageMask & (graphics_mask | VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT)) src_mask |= V3DV_BARRIER_GRAPHICS_BIT; - } /* Track consumer of the barrier */ - if (dstStageMask & (VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)) { - cmd_buffer->state.barrier.dst_mask |= V3DV_BARRIER_COMPUTE_BIT; - cmd_buffer->state.barrier.src_mask_compute |= src_mask; + if (dstStageMask & (compute_mask | VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT)) { + state->dst_mask |= V3DV_BARRIER_COMPUTE_BIT; + state->src_mask_compute |= src_mask; } - if (dstStageMask & (VK_PIPELINE_STAGE_TRANSFER_BIT | - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)) { - cmd_buffer->state.barrier.dst_mask |= V3DV_BARRIER_TRANSFER_BIT; - cmd_buffer->state.barrier.src_mask_transfer |= src_mask; + if (dstStageMask & (transfer_mask | VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT)) { + state->dst_mask |= V3DV_BARRIER_TRANSFER_BIT; + state->src_mask_transfer |= src_mask; } - if (dstStageMask & (~(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | - VK_PIPELINE_STAGE_TRANSFER_BIT))) { - cmd_buffer->state.barrier.dst_mask |= V3DV_BARRIER_GRAPHICS_BIT; - cmd_buffer->state.barrier.src_mask_graphics |= src_mask; + if (dstStageMask & (graphics_mask | VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT)) { + state->dst_mask |= V3DV_BARRIER_GRAPHICS_BIT; + state->src_mask_graphics |= src_mask; - if (dstStageMask & (VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | - VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | - VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | - VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | - VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | - VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | - VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | - VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)) { - for (int i = 0; i < memoryBarrierCount; i++) { - cmd_buffer->state.barrier.bcl_buffer_access |= - pMemoryBarriers[i].dstAccessMask; - cmd_buffer->state.barrier.bcl_image_access |= - pMemoryBarriers[i].dstAccessMask; - } - for (int i = 0; i < bufferBarrierCount; i++) { - cmd_buffer->state.barrier.bcl_buffer_access |= - pBufferBarriers[i].dstAccessMask; - } - for (int i = 0; i < imageBarrierCount; i++) { - if (pImageBarriers[i].oldLayout != VK_IMAGE_LAYOUT_UNDEFINED) { - cmd_buffer->state.barrier.bcl_image_access |= - pImageBarriers[i].dstAccessMask; - } - } + if (dstStageMask & (VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT | + VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT | + VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT | + VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT | + VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT | + VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT | + VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT | + VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT | + VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT | + VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT | + VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT | + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT)) { + if (is_image_barrier) + state->bcl_image_access |= dstAccessMask; + + if (is_buffer_barrier) + state->bcl_buffer_access |= dstAccessMask; } } } +static void +pipeline_barrier(struct v3dv_cmd_buffer *cmd_buffer, + const VkDependencyInfoKHR *info) +{ + uint32_t imageBarrierCount = info->imageMemoryBarrierCount; + const VkImageMemoryBarrier2 *pImageBarriers = info->pImageMemoryBarriers; + + uint32_t bufferBarrierCount = info->bufferMemoryBarrierCount; + const VkBufferMemoryBarrier2 *pBufferBarriers = info->pBufferMemoryBarriers; + + uint32_t memoryBarrierCount = info->memoryBarrierCount; + const VkMemoryBarrier2 *pMemoryBarriers = info->pMemoryBarriers; + + struct v3dv_barrier_state state = { 0 }; + for (uint32_t i = 0; i < imageBarrierCount; i++) { + /* We can safely skip barriers for image layout transitions from UNDEFINED + * layout. + * + * Notice that KHR_synchronization2 allows to specify barriers that don't + * involve a layout transition by making oldLayout and newLayout the same, + * including UNDEFINED. + */ + if (pImageBarriers[i].oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && + pImageBarriers[i].oldLayout != pImageBarriers[i].newLayout) { + continue; + } + + handle_barrier(pImageBarriers[i].srcStageMask, + pImageBarriers[i].srcAccessMask, + pImageBarriers[i].dstStageMask, + pImageBarriers[i].dstAccessMask, + true, false, &state); + } + + for (uint32_t i = 0; i < bufferBarrierCount; i++) { + handle_barrier(pBufferBarriers[i].srcStageMask, + pBufferBarriers[i].srcAccessMask, + pBufferBarriers[i].dstStageMask, + pBufferBarriers[i].dstAccessMask, + false, true, &state); + } + + for (uint32_t i = 0; i < memoryBarrierCount; i++) { + handle_barrier(pMemoryBarriers[i].srcStageMask, + pMemoryBarriers[i].srcAccessMask, + pMemoryBarriers[i].dstStageMask, + pMemoryBarriers[i].dstAccessMask, + true, true, &state); + } + + /* Bail if we don't relevant barriers */ + if (!state.dst_mask) + return; + + /* If we have a recording job, finish it here */ + if (cmd_buffer->state.job) + v3dv_cmd_buffer_finish_job(cmd_buffer); + + /* Update barrier state in the command buffer */ + v3dv_cmd_buffer_merge_barrier_state(&cmd_buffer->state.barrier, &state); +} + +VKAPI_ATTR void VKAPI_CALL +v3dv_CmdPipelineBarrier2(VkCommandBuffer commandBuffer, + const VkDependencyInfoKHR *pDependencyInfo) +{ + V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer); + pipeline_barrier(cmd_buffer, pDependencyInfo); +} + VKAPI_ATTR void VKAPI_CALL v3dv_CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index 43f53b93d49..182ec53688b 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -1301,8 +1301,8 @@ struct v3dv_barrier_state { /* For graphics barriers, access masks involved. Used to decide if we need * to execute a binning or render barrier. */ - VkAccessFlags bcl_buffer_access; - VkAccessFlags bcl_image_access; + VkAccessFlags2 bcl_buffer_access; + VkAccessFlags2 bcl_image_access; }; struct v3dv_cmd_buffer_state {