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:
committed by
Marge Bot
parent
a27111cdbd
commit
9cd81fb910
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user