Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/adapter_vk.c | 29 ++++++++- dlls/wined3d/texture.c | 104 ++++++++++++++++++++++----------- dlls/wined3d/wined3d_private.h | 8 +++ 3 files changed, 106 insertions(+), 35 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index c7da02865ea..1db25a4d72f 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -856,7 +856,7 @@ void wined3d_bo_slab_vk_unmap(struct wined3d_bo_slab_vk *slab_vk, struct wined3d slab_vk->map_ptr = NULL; }
-static VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage) +VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage) { VkAccessFlags flags = 0;
@@ -877,6 +877,33 @@ static VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage) if (usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT) flags |= VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT; + if (usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT) + flags |= VK_ACCESS_TRANSFER_READ_BIT; + if (usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT) + flags |= VK_ACCESS_TRANSFER_WRITE_BIT; + + return flags; +} + +VkPipelineStageFlags vk_pipeline_stage_mask_from_buffer_usage(VkBufferUsageFlags usage) +{ + VkPipelineStageFlags flags = 0; + + if (usage & (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT)) + flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; + if (usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT + | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) + flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT + | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT + | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT + | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT; + if (usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) + flags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; + if (usage & (VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT + | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT)) + flags |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT; + if (usage & (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)) + flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
return flags; } diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 6ecec939964..ad96cf2ea65 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -4658,11 +4658,14 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, unsigned int dst_level, dst_row_pitch, dst_slice_pitch; struct wined3d_texture_sub_resource *sub_resource; struct wined3d_bo_address staging_bo_addr; + VkPipelineStageFlags bo_stage_flags = 0; const struct wined3d_vk_info *vk_info; VkCommandBuffer vk_command_buffer; + VkBufferMemoryBarrier vk_barrier; VkImageSubresourceRange vk_range; struct wined3d_bo_vk staging_bo; VkImageAspectFlags aspect_mask; + struct wined3d_bo_vk *src_bo; struct wined3d_range range; VkBufferImageCopy region; size_t src_offset; @@ -4674,12 +4677,6 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, src_row_pitch, src_slice_pitch, dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), dst_x, dst_y, dst_z);
- if (src_bo_addr->buffer_object) - { - FIXME("Unhandled buffer object %#lx.\n", src_bo_addr->buffer_object); - return; - } - if (src_format->id != dst_texture->resource.format->id) { FIXME("Unhandled format conversion (%s -> %s).\n", @@ -4721,36 +4718,66 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, + (src_box->top / src_format->block_height) * src_row_pitch + (src_box->left / src_format->block_width) * src_format->block_byte_count;
- if (!wined3d_context_vk_create_bo(context_vk, sub_resource->size, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo)) + if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk))) { - ERR("Failed to create staging bo.\n"); + ERR("Failed to get command buffer.\n"); return; }
- staging_bo_addr.buffer_object = (uintptr_t)&staging_bo; - staging_bo_addr.addr = NULL; - if (!(map_ptr = wined3d_context_map_bo_address(context, &staging_bo_addr, - sub_resource->size, WINED3D_MAP_DISCARD | WINED3D_MAP_WRITE))) + /* We need to be outside of a render pass for vkCmdPipelineBarrier() and vkCmdCopyBufferToImage() calls below. */ + wined3d_context_vk_end_current_render_pass(context_vk); + + if (!(src_bo = (struct wined3d_bo_vk *)src_bo_addr->buffer_object)) { - ERR("Failed to map staging bo.\n"); - wined3d_context_vk_destroy_bo(context_vk, &staging_bo); - return; - } + if (!wined3d_context_vk_create_bo(context_vk, sub_resource->size, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo)) + { + ERR("Failed to create staging bo.\n"); + return; + }
- wined3d_format_copy_data(src_format, src_bo_addr->addr + src_offset, src_row_pitch, - src_slice_pitch, map_ptr, dst_row_pitch, dst_slice_pitch, src_box->right - src_box->left, - src_box->bottom - src_box->top, src_box->back - src_box->front); + staging_bo_addr.buffer_object = (uintptr_t)&staging_bo; + staging_bo_addr.addr = NULL; + if (!(map_ptr = wined3d_context_map_bo_address(context, &staging_bo_addr, + sub_resource->size, WINED3D_MAP_DISCARD | WINED3D_MAP_WRITE))) + { + ERR("Failed to map staging bo.\n"); + wined3d_context_vk_destroy_bo(context_vk, &staging_bo); + return; + }
- range.offset = 0; - range.size = sub_resource->size; - wined3d_context_unmap_bo_address(context, &staging_bo_addr, 1, &range); + wined3d_format_copy_data(src_format, src_bo_addr->addr + src_offset, src_row_pitch, + src_slice_pitch, map_ptr, dst_row_pitch, dst_slice_pitch, src_box->right - src_box->left, + src_box->bottom - src_box->top, src_box->back - src_box->front);
- if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk))) + range.offset = 0; + range.size = sub_resource->size; + wined3d_context_unmap_bo_address(context, &staging_bo_addr, 1, &range); + + src_bo = &staging_bo; + + src_offset = 0; + src_row_pitch = dst_row_pitch; + src_slice_pitch = dst_slice_pitch; + } + else { - ERR("Failed to get command buffer.\n"); - wined3d_context_vk_destroy_bo(context_vk, &staging_bo); - return; + vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + vk_barrier.pNext = NULL; + vk_barrier.srcAccessMask = vk_access_mask_from_buffer_usage(src_bo->usage) & ~WINED3D_READ_ONLY_ACCESS_FLAGS; + vk_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vk_barrier.buffer = src_bo->vk_buffer; + vk_barrier.offset = src_bo->buffer_offset + (size_t)src_bo_addr->addr; + vk_barrier.size = sub_resource->size; + + src_offset += (size_t)src_bo_addr->addr; + + bo_stage_flags = vk_pipeline_stage_mask_from_buffer_usage(src_bo->usage); + if (vk_barrier.srcAccessMask) + VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, bo_stage_flags, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL)); }
vk_range.aspectMask = aspect_mask; @@ -4766,10 +4793,10 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, dst_texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_texture_vk->image.vk_image, &vk_range);
- region.bufferOffset = staging_bo.buffer_offset; - region.bufferRowLength = (dst_row_pitch / src_format->block_byte_count) * src_format->block_width; - if (dst_row_pitch) - region.bufferImageHeight = (dst_slice_pitch / dst_row_pitch) * src_format->block_height; + region.bufferOffset = src_bo->buffer_offset + src_offset; + region.bufferRowLength = (src_row_pitch / src_format->block_byte_count) * src_format->block_width; + if (src_row_pitch) + region.bufferImageHeight = (src_slice_pitch / src_row_pitch) * src_format->block_height; else region.bufferImageHeight = 1; region.imageSubresource.aspectMask = vk_range.aspectMask; @@ -4783,7 +4810,7 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, region.imageExtent.height = src_box->bottom - src_box->top; region.imageExtent.depth = src_box->back - src_box->front;
- VK_CALL(vkCmdCopyBufferToImage(vk_command_buffer, staging_bo.vk_buffer, + VK_CALL(vkCmdCopyBufferToImage(vk_command_buffer, src_bo->vk_buffer, dst_texture_vk->image.vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion));
wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, @@ -4793,8 +4820,17 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_texture_vk->layout, dst_texture_vk->image.vk_image, &vk_range); wined3d_context_vk_reference_texture(context_vk, dst_texture_vk); - wined3d_context_vk_reference_bo(context_vk, &staging_bo); - wined3d_context_vk_destroy_bo(context_vk, &staging_bo); + wined3d_context_vk_reference_bo(context_vk, src_bo); + + if (src_bo == &staging_bo) + { + wined3d_context_vk_destroy_bo(context_vk, &staging_bo); + } + else if (vk_barrier.srcAccessMask) + { + VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + bo_stage_flags, 0, 0, NULL, 0, NULL, 0, NULL)); + } }
static void wined3d_texture_vk_download_data(struct wined3d_context *context, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 86c053df0db..601fefd0145 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -313,12 +313,20 @@ extern const GLenum magLookup[WINED3D_TEXF_LINEAR + 1] DECLSPEC_HIDDEN; static const uint32_t WINED3D_READ_ONLY_BIND_MASK = WINED3D_BIND_VERTEX_BUFFER | WINED3D_BIND_INDEX_BUFFER | WINED3D_BIND_CONSTANT_BUFFER | WINED3D_BIND_SHADER_RESOURCE | WINED3D_BIND_INDIRECT_BUFFER;
+static const VkAccessFlags WINED3D_READ_ONLY_ACCESS_FLAGS = VK_ACCESS_INDIRECT_COMMAND_READ_BIT + | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT + | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_HOST_READ_BIT + | VK_ACCESS_MEMORY_READ_BIT; + GLenum wined3d_gl_compare_func(enum wined3d_cmp_func f) DECLSPEC_HIDDEN; VkAccessFlags vk_access_mask_from_bind_flags(uint32_t bind_flags) DECLSPEC_HIDDEN; VkCompareOp vk_compare_op_from_wined3d(enum wined3d_cmp_func op) DECLSPEC_HIDDEN; VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type, uint32_t flags) DECLSPEC_HIDDEN; VkPipelineStageFlags vk_pipeline_stage_mask_from_bind_flags(uint32_t bind_flags) DECLSPEC_HIDDEN; VkShaderStageFlagBits vk_shader_stage_from_wined3d(enum wined3d_shader_type shader_type) DECLSPEC_HIDDEN; +VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage) DECLSPEC_HIDDEN; +VkPipelineStageFlags vk_pipeline_stage_mask_from_buffer_usage(VkBufferUsageFlags usage) DECLSPEC_HIDDEN;
static inline enum wined3d_cmp_func wined3d_sanitize_cmp_func(enum wined3d_cmp_func func) {