v3dv: implement vkCmdPipelineBarrier2

Added with KHR_synchronization2. The common code in Mesa will
rewrite vkCmdPipelineBarrier to vkCmdPipelineBarrier2.

With synchronization2 barriers now have a per-barrier stage
and access flags (previously these were shared by all the barriers
in a vkCmdPipelineBarrier commands), so we need to rewrite a bit
the logic to account for this.

Also, stage and access flag bits have been expanded and renamed.
Particularly, some new flags have been added that we need to account
for.

Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18290>
This commit is contained in:
Iago Toral Quiroga
2022-08-26 09:26:41 +02:00
committed by Marge Bot
parent a27111cdbd
commit 9cd81fb910
2 changed files with 145 additions and 96 deletions
+143 -94
View File
@@ -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,
+2 -2
View File
@@ -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 {