diff --git a/src/virtio/vulkan/vn_command_buffer.c b/src/virtio/vulkan/vn_command_buffer.c index 63962f64107..642f157ed71 100644 --- a/src/virtio/vulkan/vn_command_buffer.c +++ b/src/virtio/vulkan/vn_command_buffer.c @@ -134,6 +134,7 @@ vn_AllocateCommandBuffers(VkDevice device, vn_object_base_init(&cmd->base, VK_OBJECT_TYPE_COMMAND_BUFFER, &dev->base); cmd->device = dev; + cmd->allocator = pool->allocator; list_addtail(&cmd->head, &pool->command_buffers); @@ -170,6 +171,9 @@ vn_FreeCommandBuffers(VkDevice device, if (!cmd) continue; + if (cmd->image_barriers) + vk_free(alloc, cmd->image_barriers); + vn_cs_encoder_fini(&cmd->cs); list_del(&cmd->head); @@ -939,6 +943,51 @@ vn_CmdResetEvent(VkCommandBuffer commandBuffer, vn_encode_vkCmdResetEvent(&cmd->cs, 0, commandBuffer, event, stageMask); } +static const VkImageMemoryBarrier * +vn_get_intercepted_barriers(struct vn_command_buffer *cmd, + const VkImageMemoryBarrier *img_barriers, + uint32_t count) +{ + /* XXX drop the #ifdef after fixing common wsi */ +#ifdef ANDROID + bool has_present_src = false; + for (uint32_t i = 0; i < count; i++) { + if (img_barriers[i].oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR || + img_barriers[i].newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { + has_present_src = false; + break; + } + } + if (!has_present_src) + return img_barriers; + + size_t size = sizeof(VkImageMemoryBarrier) * count; + /* avoid shrinking in case of non efficient reallocation implementation */ + VkImageMemoryBarrier *barriers = cmd->image_barriers; + if (count > cmd->image_barrier_count) { + barriers = + vk_realloc(&cmd->allocator, cmd->image_barriers, size, + VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!barriers) + return img_barriers; + + /* update upon successful reallocation */ + cmd->image_barrier_count = count; + cmd->image_barriers = barriers; + } + memcpy(barriers, img_barriers, size); + for (uint32_t i = 0; i < count; i++) { + if (barriers[i].oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) + barriers[i].oldLayout = VK_IMAGE_LAYOUT_GENERAL; + if (barriers[i].newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) + barriers[i].newLayout = VK_IMAGE_LAYOUT_GENERAL; + } + return barriers; +#else + return img_barriers; +#endif +} + void vn_CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, @@ -963,13 +1012,14 @@ vn_CmdWaitEvents(VkCommandBuffer commandBuffer, if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size)) return; - /* XXX VK_IMAGE_LAYOUT_PRESENT_SRC_KHR */ + const VkImageMemoryBarrier *img_barriers = vn_get_intercepted_barriers( + cmd, pImageMemoryBarriers, imageMemoryBarrierCount); vn_encode_vkCmdWaitEvents(&cmd->cs, 0, commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, - pImageMemoryBarriers); + img_barriers); } void @@ -995,12 +1045,13 @@ vn_CmdPipelineBarrier(VkCommandBuffer commandBuffer, if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size)) return; - /* XXX VK_IMAGE_LAYOUT_PRESENT_SRC_KHR */ + const VkImageMemoryBarrier *img_barriers = vn_get_intercepted_barriers( + cmd, pImageMemoryBarriers, imageMemoryBarrierCount); vn_encode_vkCmdPipelineBarrier( &cmd->cs, 0, commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, - pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); + pBufferMemoryBarriers, imageMemoryBarrierCount, img_barriers); } void diff --git a/src/virtio/vulkan/vn_command_buffer.h b/src/virtio/vulkan/vn_command_buffer.h index 77ec43b27d4..ab74effe507 100644 --- a/src/virtio/vulkan/vn_command_buffer.h +++ b/src/virtio/vulkan/vn_command_buffer.h @@ -38,6 +38,11 @@ struct vn_command_buffer { struct vn_device *device; + /* for scrubbing VK_IMAGE_LAYOUT_PRESENT_SRC_KHR */ + VkAllocationCallbacks allocator; + uint32_t image_barrier_count; + VkImageMemoryBarrier *image_barriers; + struct list_head head; enum vn_command_buffer_state state; diff --git a/src/virtio/vulkan/vn_render_pass.c b/src/virtio/vulkan/vn_render_pass.c index 7411f5556a6..fa87a662fe0 100644 --- a/src/virtio/vulkan/vn_render_pass.c +++ b/src/virtio/vulkan/vn_render_pass.c @@ -17,6 +17,43 @@ /* render pass commands */ +static const VkAttachmentDescription * +vn_get_intercepted_attachments(const VkAttachmentDescription *attachments, + uint32_t count, + const VkAllocationCallbacks *alloc) +{ + /* XXX drop the #ifdef after fixing common wsi */ +#ifdef ANDROID + bool has_present_src = false; + for (uint32_t i = 0; i < count; i++) { + if (attachments[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR || + attachments[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { + has_present_src = true; + break; + } + } + if (!has_present_src) + return attachments; + + size_t size = sizeof(VkAttachmentDescription) * count; + VkAttachmentDescription *out_attachments = vk_alloc( + alloc, size, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (!out_attachments) + return NULL; + + memcpy(out_attachments, attachments, size); + for (uint32_t i = 0; i < count; i++) { + if (out_attachments[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) + out_attachments[i].initialLayout = VK_IMAGE_LAYOUT_GENERAL; + if (out_attachments[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) + out_attachments[i].finalLayout = VK_IMAGE_LAYOUT_GENERAL; + } + return out_attachments; +#else + return attachments; +#endif +} + VkResult vn_CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, @@ -35,17 +72,63 @@ vn_CreateRenderPass(VkDevice device, vn_object_base_init(&pass->base, VK_OBJECT_TYPE_RENDER_PASS, &dev->base); - /* XXX VK_IMAGE_LAYOUT_PRESENT_SRC_KHR */ + VkRenderPassCreateInfo local_pass_info = *pCreateInfo; + local_pass_info.pAttachments = vn_get_intercepted_attachments( + pCreateInfo->pAttachments, pCreateInfo->attachmentCount, alloc); + if (!local_pass_info.pAttachments) { + vk_free(alloc, pass); + return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); + } VkRenderPass pass_handle = vn_render_pass_to_handle(pass); - vn_async_vkCreateRenderPass(dev->instance, device, pCreateInfo, NULL, + vn_async_vkCreateRenderPass(dev->instance, device, &local_pass_info, NULL, &pass_handle); + if (local_pass_info.pAttachments != pCreateInfo->pAttachments) + vk_free(alloc, (void *)local_pass_info.pAttachments); + *pRenderPass = pass_handle; return VK_SUCCESS; } +static const VkAttachmentDescription2 * +vn_get_intercepted_attachments2(const VkAttachmentDescription2 *attachments, + uint32_t count, + const VkAllocationCallbacks *alloc) +{ + /* XXX drop the #ifdef after fixing common wsi */ +#ifdef ANDROID + bool has_present_src = false; + for (uint32_t i = 0; i < count; i++) { + if (attachments[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR || + attachments[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { + has_present_src = true; + break; + } + } + if (!has_present_src) + return attachments; + + size_t size = sizeof(VkAttachmentDescription2) * count; + VkAttachmentDescription2 *out_attachments = vk_alloc( + alloc, size, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (!out_attachments) + return NULL; + + memcpy(out_attachments, attachments, size); + for (uint32_t i = 0; i < count; i++) { + if (out_attachments[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) + out_attachments[i].initialLayout = VK_IMAGE_LAYOUT_GENERAL; + if (out_attachments[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) + out_attachments[i].finalLayout = VK_IMAGE_LAYOUT_GENERAL; + } + return out_attachments; +#else + return attachments; +#endif +} + VkResult vn_CreateRenderPass2(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo, @@ -64,12 +147,21 @@ vn_CreateRenderPass2(VkDevice device, vn_object_base_init(&pass->base, VK_OBJECT_TYPE_RENDER_PASS, &dev->base); - /* XXX VK_IMAGE_LAYOUT_PRESENT_SRC_KHR */ + VkRenderPassCreateInfo2 local_pass_info = *pCreateInfo; + local_pass_info.pAttachments = vn_get_intercepted_attachments2( + pCreateInfo->pAttachments, pCreateInfo->attachmentCount, alloc); + if (!local_pass_info.pAttachments) { + vk_free(alloc, pass); + return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); + } VkRenderPass pass_handle = vn_render_pass_to_handle(pass); - vn_async_vkCreateRenderPass2(dev->instance, device, pCreateInfo, NULL, + vn_async_vkCreateRenderPass2(dev->instance, device, &local_pass_info, NULL, &pass_handle); + if (local_pass_info.pAttachments != pCreateInfo->pAttachments) + vk_free(alloc, (void *)local_pass_info.pAttachments); + *pRenderPass = pass_handle; return VK_SUCCESS;