wined3d: Implement support for buffer objects in wined3d_texture_vk_upload_data().

Signed-off-by: Jan Sikorski <jsikorski@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jan Sikorski 2021-09-10 15:58:38 +02:00 committed by Alexandre Julliard
parent 8e40f98c3e
commit 256a2a0913
3 changed files with 111 additions and 40 deletions

View File

@ -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;
}

View File

@ -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,38 +4718,68 @@ 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))
{
ERR("Failed to create staging bo.\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)))
{
ERR("Failed to map staging bo.\n");
wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
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);
range.offset = 0;
range.size = sub_resource->size;
wined3d_context_unmap_bo_address(context, &staging_bo_addr, 1, &range);
if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
{
ERR("Failed to get command buffer.\n");
wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
return;
}
/* 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))
{
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;
}
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;
}
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);
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
{
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;
vk_range.baseMipLevel = dst_level;
vk_range.levelCount = 1;
@ -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, &region));
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,

View File

@ -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)
{