Use wined3d_context_copy_bo_address() instead.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/texture.c | 58 ++++++++---------------------------------- 1 file changed, 11 insertions(+), 47 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index f5f7fab49a6..6663e788e9c 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -745,52 +745,6 @@ void wined3d_texture_clear_dirty_regions(struct wined3d_texture *texture) } }
-static BOOL wined3d_texture_copy_sysmem_location(struct wined3d_texture *texture, - unsigned int sub_resource_idx, struct wined3d_context *context, DWORD location) -{ - unsigned int size = texture->sub_resources[sub_resource_idx].size; - struct wined3d_device *device = texture->resource.device; - const struct wined3d_gl_info *gl_info; - struct wined3d_bo_gl *src_bo, *dst_bo; - struct wined3d_bo_address dst, src; - - if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, location)) - return FALSE; - - wined3d_texture_get_memory(texture, sub_resource_idx, &dst, location); - wined3d_texture_get_memory(texture, sub_resource_idx, &src, - texture->sub_resources[sub_resource_idx].locations); - - if ((dst_bo = (struct wined3d_bo_gl *)dst.buffer_object)) - { - context = context_acquire(device, NULL, 0); - gl_info = wined3d_context_gl(context)->gl_info; - GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, dst_bo->id)); - GL_EXTCALL(glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, size, src.addr)); - GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); - wined3d_context_gl_reference_bo(wined3d_context_gl(context), dst_bo); - checkGLcall("PBO upload"); - context_release(context); - return TRUE; - } - - if ((src_bo = (struct wined3d_bo_gl *)src.buffer_object)) - { - context = context_acquire(device, NULL, 0); - gl_info = wined3d_context_gl(context)->gl_info; - GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, src_bo->id)); - GL_EXTCALL(glGetBufferSubData(GL_PIXEL_PACK_BUFFER, 0, size, dst.addr)); - GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)); - wined3d_context_gl_reference_bo(wined3d_context_gl(context), src_bo); - checkGLcall("PBO download"); - context_release(context); - return TRUE; - } - - memcpy(dst.addr, src.addr, size); - return TRUE; -} - /* Context activation is done by the caller. Context may be NULL in * WINED3D_NO3D mode. */ BOOL wined3d_texture_load_location(struct wined3d_texture *texture, @@ -837,7 +791,17 @@ BOOL wined3d_texture_load_location(struct wined3d_texture *texture, }
if ((location & wined3d_texture_sysmem_locations) && (current & wined3d_texture_sysmem_locations)) - ret = wined3d_texture_copy_sysmem_location(texture, sub_resource_idx, context, location); + { + unsigned int size = texture->sub_resources[sub_resource_idx].size; + struct wined3d_bo_address source, destination; + + if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, location)) + return FALSE; + wined3d_texture_get_memory(texture, sub_resource_idx, &source, current); + wined3d_texture_get_memory(texture, sub_resource_idx, &destination, location); + wined3d_context_copy_bo_address(context, &destination, &source, size); + ret = TRUE; + } else ret = texture->texture_ops->texture_load_location(texture, sub_resource_idx, context, location);
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/adapter_vk.c | 29 +++- dlls/wined3d/texture.c | 270 +++++++++++++++++++++++---------- dlls/wined3d/wined3d_private.h | 14 +- 3 files changed, 231 insertions(+), 82 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 6663e788e9c..49a8d4ead8b 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -49,8 +49,10 @@ struct wined3d_rect_f
static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info) { - if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] - || texture->resource.format->conv_byte_count + if (gl_info->selected_gl_version && !gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) + return FALSE; + + if (texture->resource.format->conv_byte_count || (texture->flags & (WINED3D_TEXTURE_PIN_SYSMEM | WINED3D_TEXTURE_COND_NP2_EMULATED))) return FALSE;
@@ -851,7 +853,7 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su static void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context_gl *context_gl) { - struct wined3d_bo_gl *bo = &texture->sub_resources[sub_resource_idx].bo; + struct wined3d_bo_gl *bo = &texture->sub_resources[sub_resource_idx].bo.gl;
TRACE("texture %p, sub_resource_idx %u, context_gl %p.\n", texture, sub_resource_idx, context_gl);
@@ -859,6 +861,12 @@ static void wined3d_texture_remove_buffer_object(struct wined3d_texture *texture wined3d_texture_invalidate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER); }
+static void wined3d_texture_unload_location(struct wined3d_texture *texture, + struct wined3d_context *context, unsigned int location) +{ + texture->texture_ops->texture_unload_location(texture, context, location); +} + static void wined3d_texture_update_map_binding(struct wined3d_texture *texture) { unsigned int sub_count = texture->level_count * texture->layer_count; @@ -874,10 +882,11 @@ static void wined3d_texture_update_map_binding(struct wined3d_texture *texture) if (texture->sub_resources[i].locations == texture->resource.map_binding && !wined3d_texture_load_location(texture, i, context, map_binding)) ERR("Failed to load location %s.\n", wined3d_debug_location(map_binding)); - if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER) - wined3d_texture_remove_buffer_object(texture, i, wined3d_context_gl(context)); }
+ if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER) + wined3d_texture_unload_location(texture, context, WINED3D_LOCATION_BUFFER); + context_release(context);
texture->resource.map_binding = map_binding; @@ -1980,7 +1989,7 @@ static void wined3d_texture_gl_prepare_buffer_object(struct wined3d_texture_gl * struct wined3d_bo_gl *bo;
sub_resource = &texture_gl->t.sub_resources[sub_resource_idx]; - bo = &sub_resource->bo; + bo = &sub_resource->bo.gl; if (bo->id) return;
@@ -2110,12 +2119,6 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, return texture->texture_ops->texture_prepare_location(texture, sub_resource_idx, context, location); }
-static void wined3d_texture_unload_location(struct wined3d_texture *texture, - struct wined3d_context *context, unsigned int location) -{ - texture->texture_ops->texture_unload_location(texture, context, location); -} - static struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(struct wined3d_texture *texture, unsigned int sub_resource_idx) { @@ -3152,7 +3155,7 @@ static BOOL wined3d_texture_gl_load_texture(struct wined3d_texture_gl *texture_g /* Don't use PBOs for converted surfaces. During PBO conversion we look at * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is * getting called. */ - if (conversion && sub_resource->bo.id) + if (conversion && sub_resource->bo.gl.id) { TRACE("Removing the pbo attached to texture %p, %u.\n", texture_gl, sub_resource_idx);
@@ -3289,7 +3292,7 @@ static void wined3d_texture_gl_unload_location(struct wined3d_texture *texture, sub_count = texture->level_count * texture->layer_count; for (i = 0; i < sub_count; ++i) { - if (texture_gl->t.sub_resources[i].bo.id) + if (texture_gl->t.sub_resources[i].bo.gl.id) wined3d_texture_remove_buffer_object(&texture_gl->t, i, context_gl); } break; @@ -4657,11 +4660,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; @@ -4673,12 +4679,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", @@ -4720,36 +4720,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"); + if (!src_bo_addr->buffer_object) + wined3d_context_vk_destroy_bo(context_vk, &staging_bo); 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))) + 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; + vk_barrier.size = src_bo->size; + + 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; @@ -4765,10 +4795,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; @@ -4782,7 +4812,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, @@ -4792,8 +4822,18 @@ 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_addr->buffer_object) + { + 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)); + } + else + { + wined3d_context_vk_destroy_bo(context_vk, &staging_bo); + } }
static void wined3d_texture_vk_download_data(struct wined3d_context *context, @@ -4808,11 +4848,14 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, struct wined3d_texture_sub_resource *sub_resource; unsigned int src_row_pitch, src_slice_pitch; struct wined3d_bo_address staging_bo_addr; + VkPipelineStageFlags bo_stage_flags = 0; const struct wined3d_vk_info *vk_info; VkCommandBuffer vk_command_buffer; VkImageSubresourceRange vk_range; + VkBufferMemoryBarrier vk_barrier; struct wined3d_bo_vk staging_bo; VkImageAspectFlags aspect_mask; + struct wined3d_bo_vk *dst_bo; VkBufferImageCopy region; void *map_ptr;
@@ -4839,12 +4882,6 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, return; }
- if (dst_bo_addr->buffer_object) - { - FIXME("Unhandled buffer object %#lx.\n", dst_bo_addr->buffer_object); - return; - } - if (dst_format->id != src_texture->resource.format->id) { FIXME("Unhandled format conversion (%s -> %s).\n", @@ -4886,11 +4923,35 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, return; }
- if (!wined3d_context_vk_create_bo(context_vk, sub_resource->size, - VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo)) + wined3d_context_vk_end_current_render_pass(context_vk); + + if (!(dst_bo = (struct wined3d_bo_vk *)dst_bo_addr->buffer_object)) { - ERR("Failed to create staging bo.\n"); - return; + if (!wined3d_context_vk_create_bo(context_vk, sub_resource->size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_bo)) + { + ERR("Failed to create staging bo.\n"); + return; + } + + dst_bo = &staging_bo; + } + else + { + vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + vk_barrier.pNext = NULL; + vk_barrier.srcAccessMask = vk_access_mask_from_buffer_usage(dst_bo->usage); + vk_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vk_barrier.buffer = dst_bo->vk_buffer; + vk_barrier.offset = dst_bo->buffer_offset; + vk_barrier.size = dst_bo->size; + + bo_stage_flags = vk_pipeline_stage_mask_from_buffer_usage(dst_bo->usage); + + 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; @@ -4906,7 +4967,7 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, src_texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, src_texture_vk->image.vk_image, &vk_range);
- region.bufferOffset = staging_bo.buffer_offset; + region.bufferOffset = dst_bo->buffer_offset; region.bufferRowLength = 0; region.bufferImageHeight = 0; region.imageSubresource.aspectMask = vk_range.aspectMask; @@ -4921,7 +4982,7 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, region.imageExtent.depth = src_depth;
VK_CALL(vkCmdCopyImageToBuffer(vk_command_buffer, src_texture_vk->image.vk_image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, staging_bo.vk_buffer, 1, ®ion)); + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_bo->vk_buffer, 1, ®ion));
wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, @@ -4931,26 +4992,38 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, src_texture_vk->image.vk_image, &vk_range);
wined3d_context_vk_reference_texture(context_vk, src_texture_vk); - wined3d_context_vk_reference_bo(context_vk, &staging_bo); - wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL); - wined3d_context_vk_wait_command_buffer(context_vk, src_texture_vk->image.command_buffer_id); + wined3d_context_vk_reference_bo(context_vk, dst_bo);
- 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_READ))) + if (dst_bo_addr->buffer_object) { - ERR("Failed to map staging bo.\n"); - wined3d_context_vk_destroy_bo(context_vk, &staging_bo); - return; + vk_barrier.dstAccessMask = vk_barrier.srcAccessMask | VK_ACCESS_HOST_READ_BIT; + vk_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + + VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + bo_stage_flags | VK_PIPELINE_STAGE_HOST_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL)); } + else + { + wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL); + wined3d_context_vk_wait_command_buffer(context_vk, src_texture_vk->image.command_buffer_id);
- wined3d_format_copy_data(dst_format, map_ptr, src_row_pitch, src_slice_pitch, - dst_bo_addr->addr, 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_READ))) + { + ERR("Failed to map staging bo.\n"); + wined3d_context_vk_destroy_bo(context_vk, &staging_bo); + return; + } + + wined3d_format_copy_data(dst_format, map_ptr, src_row_pitch, src_slice_pitch, + dst_bo_addr->addr, dst_row_pitch, dst_slice_pitch, src_box->right - src_box->left, + src_box->bottom - src_box->top, src_box->back - src_box->front);
- wined3d_context_unmap_bo_address(context, &staging_bo_addr, 0, NULL); - wined3d_context_vk_destroy_bo(context_vk, &staging_bo); + wined3d_context_unmap_bo_address(context, &staging_bo_addr, 0, NULL); + wined3d_context_vk_destroy_bo(context_vk, &staging_bo); + } }
static BOOL wined3d_texture_vk_load_texture(struct wined3d_texture_vk *texture_vk, @@ -4962,14 +5035,14 @@ static BOOL wined3d_texture_vk_load_texture(struct wined3d_texture_vk *texture_v struct wined3d_box src_box;
sub_resource = &texture_vk->t.sub_resources[sub_resource_idx]; - if (!(sub_resource->locations & WINED3D_LOCATION_SYSMEM)) + if (!(sub_resource->locations & wined3d_texture_sysmem_locations)) { ERR("Unimplemented load from %s.\n", wined3d_debug_location(sub_resource->locations)); return FALSE; }
level = sub_resource_idx % texture_vk->t.level_count; - wined3d_texture_get_memory(&texture_vk->t, sub_resource_idx, &data, WINED3D_LOCATION_SYSMEM); + wined3d_texture_get_memory(&texture_vk->t, sub_resource_idx, &data, sub_resource->locations); wined3d_texture_get_level_box(&texture_vk->t, level, &src_box); wined3d_texture_get_pitch(&texture_vk->t, level, &row_pitch, &slice_pitch); wined3d_texture_vk_upload_data(context, wined3d_const_bo_address(&data), texture_vk->t.resource.format, @@ -4980,7 +5053,7 @@ static BOOL wined3d_texture_vk_load_texture(struct wined3d_texture_vk *texture_v }
static BOOL wined3d_texture_vk_load_sysmem(struct wined3d_texture_vk *texture_vk, - unsigned int sub_resource_idx, struct wined3d_context *context) + unsigned int sub_resource_idx, struct wined3d_context *context, unsigned int location) { struct wined3d_texture_sub_resource *sub_resource; unsigned int level, row_pitch, slice_pitch; @@ -4995,7 +5068,7 @@ static BOOL wined3d_texture_vk_load_sysmem(struct wined3d_texture_vk *texture_vk }
level = sub_resource_idx % texture_vk->t.level_count; - wined3d_texture_get_memory(&texture_vk->t, sub_resource_idx, &data, WINED3D_LOCATION_SYSMEM); + wined3d_texture_get_memory(&texture_vk->t, sub_resource_idx, &data, location); wined3d_texture_get_level_box(&texture_vk->t, level, &src_box); wined3d_texture_get_pitch(&texture_vk->t, level, &row_pitch, &slice_pitch); wined3d_texture_vk_download_data(context, &texture_vk->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, @@ -5111,6 +5184,26 @@ BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *texture_vk, return TRUE; }
+static BOOL wined3d_texture_vk_prepare_buffer_object(struct wined3d_texture_vk *texture_vk, + unsigned int sub_resource_idx, struct wined3d_context_vk *context_vk) +{ + struct wined3d_texture_sub_resource *sub_resource; + struct wined3d_bo_vk *bo; + + sub_resource = &texture_vk->t.sub_resources[sub_resource_idx]; + bo = &sub_resource->bo.vk; + if (bo->vk_buffer) + return TRUE; + + if (!wined3d_context_vk_create_bo(context_vk, sub_resource->size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bo)) + return FALSE; + + TRACE("Created buffer object %p for texture %p, sub-resource %u.\n", bo, texture_vk, sub_resource_idx); + return TRUE; +} + static BOOL wined3d_texture_vk_prepare_location(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context *context, unsigned int location) { @@ -5123,6 +5216,10 @@ static BOOL wined3d_texture_vk_prepare_location(struct wined3d_texture *texture, case WINED3D_LOCATION_TEXTURE_RGB: return wined3d_texture_vk_prepare_texture(wined3d_texture_vk(texture), wined3d_context_vk(context));
+ case WINED3D_LOCATION_BUFFER: + return wined3d_texture_vk_prepare_buffer_object(wined3d_texture_vk(texture), sub_resource_idx, + wined3d_context_vk(context)); + default: FIXME("Unhandled location %s.\n", wined3d_debug_location(location)); return FALSE; @@ -5141,7 +5238,8 @@ static BOOL wined3d_texture_vk_load_location(struct wined3d_texture *texture, return wined3d_texture_vk_load_texture(wined3d_texture_vk(texture), sub_resource_idx, context);
case WINED3D_LOCATION_SYSMEM: - return wined3d_texture_vk_load_sysmem(wined3d_texture_vk(texture), sub_resource_idx, context); + case WINED3D_LOCATION_BUFFER: + return wined3d_texture_vk_load_sysmem(wined3d_texture_vk(texture), sub_resource_idx, context, location);
default: FIXME("Unimplemented location %s.\n", wined3d_debug_location(location)); @@ -5154,6 +5252,7 @@ static void wined3d_texture_vk_unload_location(struct wined3d_texture *texture, { struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture); struct wined3d_context_vk *context_vk = wined3d_context_vk(context); + unsigned int i, sub_count;
TRACE("texture %p, context %p, location %s.\n", texture, context, wined3d_debug_location(location));
@@ -5172,6 +5271,17 @@ static void wined3d_texture_vk_unload_location(struct wined3d_texture *texture, break;
case WINED3D_LOCATION_BUFFER: + sub_count = texture->level_count * texture->layer_count; + for (i = 0; i < sub_count; ++i) + { + if (texture->sub_resources[i].bo.vk.vk_buffer) + { + wined3d_context_vk_destroy_bo(context_vk, &texture->sub_resources[i].bo.vk); + texture->sub_resources[i].bo.vk.vk_buffer = VK_NULL_HANDLE; + } + } + break; + case WINED3D_LOCATION_TEXTURE_SRGB: case WINED3D_LOCATION_RB_MULTISAMPLE: case WINED3D_LOCATION_RB_RESOLVED: diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 6e9f3884724..dab19383b2d 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) { @@ -4287,7 +4295,11 @@ struct wined3d_texture unsigned int map_count; uint32_t map_flags; DWORD locations; - struct wined3d_bo_gl bo; + union + { + struct wined3d_bo_gl gl; + struct wined3d_bo_vk vk; + } bo;
void *user_memory; } *sub_resources;
On Thu, 2 Sept 2021 at 15:14, Jan Sikorski jsikorski@codeweavers.com wrote:
static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info) {
- if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]
|| texture->resource.format->conv_byte_count
- if (gl_info->selected_gl_version && !gl_info->supported[ARB_PIXEL_BUFFER_OBJECT])
return FALSE;
It's perhaps a bit of a hack that the existing code was never updated to avoid using "gl_info" in what is now backend independent code, but this change doesn't make it better. This should probably just store something in the wined3d_d3d_info structure, similar to what we do with e.g. "texture_npot".
@@ -874,10 +882,11 @@ static void wined3d_texture_update_map_binding(struct wined3d_texture *texture) if (texture->sub_resources[i].locations == texture->resource.map_binding && !wined3d_texture_load_location(texture, i, context, map_binding)) ERR("Failed to load location %s.\n", wined3d_debug_location(map_binding));
if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER)
}wined3d_texture_remove_buffer_object(texture, i, wined3d_context_gl(context));
- if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER)
wined3d_texture_unload_location(texture, context, WINED3D_LOCATION_BUFFER);
This seems fine, but is somewhat of an independent change.
@@ -4673,12 +4679,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;
- }
Likewise, I think it would make sense for "Implement support for buffer objects in wined3d_texture_vk_upload_data()" to be a separate commit.
- 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");
if (!src_bo_addr->buffer_object)
}wined3d_context_vk_destroy_bo(context_vk, &staging_bo); return;
The staging bo would not have been created yet above.
- 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)))
- wined3d_context_vk_end_current_render_pass(context_vk);
I assume we're ending the current render pass (if any) for vkCmdCopyBufferToImage(). In principle wined3d_context_vk_image_barrier() already takes care of that, but I suppose it makes sense to be explicit about it. Perhaps it wouldn't hurt to add a comment mentioning the reason we need to end the render pass; I didn't add those for the existing instances of wined3d_context_vk_end_current_render_pass(), and that may have been a mistake. In any case, this too is somewhat of an independent change.
{
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;
vk_barrier.size = src_bo->size;
This adds a barrier for the entire bo, not just the part we're reading from. Perhaps that's ok though.
- 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;
That ignores "src_bo_addr->addr". Currently that's probably always going to be 0 in practice, but it wouldn't necessarily be if we e.g. switched to using a single bo per texture instead of using a bo for each sub-resource.
- if (src_bo_addr->buffer_object)
- {
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));
- }
- else
- {
wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
- }
Alternatively, we also sometimes write checks like these as "if (src_bo == &staging_bo)". That may be slightly clearer, but I don't feel strongly about it.
@@ -4839,12 +4882,6 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, return; }
- if (dst_bo_addr->buffer_object)
- {
FIXME("Unhandled buffer object %#lx.\n", dst_bo_addr->buffer_object);
return;
- }
Some of the comments for wined3d_texture_vk_upload_data() apply to wined3d_texture_vk_download_data() as well.
- if (dst_bo_addr->buffer_object) {
ERR("Failed to map staging bo.\n");
wined3d_context_vk_destroy_bo(context_vk, &staging_bo);
return;
vk_barrier.dstAccessMask = vk_barrier.srcAccessMask | VK_ACCESS_HOST_READ_BIT;
vk_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
}bo_stage_flags | VK_PIPELINE_STAGE_HOST_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL));
Do we need the HOST_READ bits in this patch? This seems like something that belongs in 3/4, and should probably only be done for bo's that have the "host_synced" flag set.
@@ -4287,7 +4295,11 @@ struct wined3d_texture unsigned int map_count; uint32_t map_flags; DWORD locations;
struct wined3d_bo_gl bo;
union
{
struct wined3d_bo_gl gl;
struct wined3d_bo_vk vk;
} bo;
This is probably fine for the moment, but ideally we'd avoid backend specific fields in the wined3d_texture_sub_resource structure. Relatedly, we may want to use a single bo for the entire texture, similar to how we use a single allocation for the system memory location.
Thanks, I’ll address these in v2, just one point.
On 9 Sep 2021, at 18:55, Henri Verbeet hverbeet@gmail.com wrote: I assume we're ending the current render pass (if any) for vkCmdCopyBufferToImage(). In principle wined3d_context_vk_image_barrier() already takes care of that, but I suppose it makes sense to be explicit about it. Perhaps it wouldn't hurt to add a comment mentioning the reason we need to end the render pass; I didn't add those for the existing instances of wined3d_context_vk_end_current_render_pass(), and that may have been a mistake. In any case, this too is somewhat of an independent change.
Actually it’s for the vkCmdPipelineBarrier() call, so not really independent. But yeah, I put it early in the function for the extra explicitness - I’ll add the comment.
- Jan
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/adapter_vk.c | 43 +++++++++++++++++++--------------- dlls/wined3d/context_vk.c | 2 ++ dlls/wined3d/texture.c | 3 +++ dlls/wined3d/wined3d_private.h | 1 + 4 files changed, 30 insertions(+), 19 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 1db25a4d72f..7342ebe3959 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -934,9 +934,11 @@ static void *adapter_vk_map_bo_address(struct wined3d_context *context, { if (wined3d_context_vk_create_bo(context_vk, bo->size, bo->usage, bo->memory_type, &tmp)) { + bool host_synced = bo->host_synced; list_move_head(&tmp.users, &bo->users); wined3d_context_vk_destroy_bo(context_vk, bo); *bo = tmp; + bo->host_synced = host_synced; list_init(&bo->users); list_move_head(&bo->users, &tmp.users); LIST_FOR_EACH_ENTRY(bo_user, &bo->users, struct wined3d_bo_user, entry) @@ -952,25 +954,30 @@ static void *adapter_vk_map_bo_address(struct wined3d_context *context,
if (map_flags & WINED3D_MAP_READ) { - if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk))) + if (!bo->host_synced) { - ERR("Failed to get command buffer.\n"); - return NULL; - } - - wined3d_context_vk_end_current_render_pass(context_vk); + if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk))) + { + ERR("Failed to get command buffer.\n"); + return NULL; + }
- vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - vk_barrier.pNext = NULL; - vk_barrier.srcAccessMask = vk_access_mask_from_buffer_usage(bo->usage); - vk_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT; - vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - vk_barrier.buffer = bo->vk_buffer; - vk_barrier.offset = bo->buffer_offset + (uintptr_t)data->addr; - vk_barrier.size = size; - VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_HOST_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL)); + wined3d_context_vk_end_current_render_pass(context_vk); + + vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + vk_barrier.pNext = NULL; + vk_barrier.srcAccessMask = vk_access_mask_from_buffer_usage(bo->usage); + vk_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT; + vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + vk_barrier.buffer = bo->vk_buffer; + vk_barrier.offset = bo->buffer_offset + (uintptr_t)data->addr; + vk_barrier.size = size; + VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_HOST_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL)); + + wined3d_context_vk_reference_bo(context_vk, bo); + }
if (!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { @@ -981,8 +988,6 @@ static void *adapter_vk_map_bo_address(struct wined3d_context *context, range.size = size; VK_CALL(vkInvalidateMappedMemoryRanges(device_vk->vk_device, 1, &range)); } - - wined3d_context_vk_reference_bo(context_vk, bo); }
if (bo->command_buffer_id == context_vk->current_command_buffer.id) diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 8df416851f2..86e9306e301 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -415,6 +415,7 @@ static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context bo->size = size; list_init(&bo->users); bo->command_buffer_id = 0; + bo->host_synced = false;
TRACE("Using buffer 0x%s, memory 0x%s, offset 0x%s for bo %p.\n", wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory), @@ -494,6 +495,7 @@ BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDevic list_init(&bo->users); bo->command_buffer_id = 0; bo->slab = NULL; + bo->host_synced = false;
TRACE("Created buffer 0x%s, memory 0x%s for bo %p.\n", wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory), bo); diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 49a8d4ead8b..2cf1a44a213 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -5200,6 +5200,9 @@ static BOOL wined3d_texture_vk_prepare_buffer_object(struct wined3d_texture_vk * VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bo)) return FALSE;
+ /* Texture buffer objects receive a barrier to HOST_READ in wined3d_texture_vk_download_data(), + * so they don't need it when they are mapped for reading. */ + bo->host_synced = true; TRACE("Created buffer object %p for texture %p, sub-resource %u.\n", bo, texture_vk, sub_resource_idx); return TRUE; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index dab19383b2d..4b7087a3807 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1625,6 +1625,7 @@ struct wined3d_bo_vk
struct list users; uint64_t command_buffer_id; + bool host_synced; };
struct wined3d_bo_slab_vk_key
Change the source texture's map_binding to BUFFER, so that the copy is GPU-side only.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/cs.c | 4 ++++ dlls/wined3d/texture.c | 12 ++++++++++-- dlls/wined3d/wined3d_private.h | 3 +++ 3 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 51e5055c4ab..0b72284615d 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -2582,6 +2582,10 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void *
context = context_acquire(cs->c.device, NULL, 0);
+ if (src_texture->resource.map_binding != WINED3D_LOCATION_BUFFER + && wined3d_texture_can_use_pbo(src_texture, &context->device->adapter->gl_info)) + wined3d_texture_set_map_binding(src_texture, WINED3D_LOCATION_BUFFER); + if (!wined3d_texture_load_location(src_texture, op->src_sub_resource_idx, context, src_texture->resource.map_binding)) { diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 2cf1a44a213..e924083301b 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -47,7 +47,7 @@ struct wined3d_rect_f float b; };
-static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info) +BOOL wined3d_texture_can_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info) { if (gl_info->selected_gl_version && !gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return FALSE; @@ -56,6 +56,14 @@ static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const || (texture->flags & (WINED3D_TEXTURE_PIN_SYSMEM | WINED3D_TEXTURE_COND_NP2_EMULATED))) return FALSE;
+ return TRUE; +} + +static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info) +{ + if (!wined3d_texture_can_use_pbo(texture, gl_info)) + return FALSE; + /* Use a PBO for dynamic textures and read-only staging textures. */ return (!(texture->resource.access & WINED3D_RESOURCE_ACCESS_CPU) && texture->resource.usage & WINED3DUSAGE_DYNAMIC) @@ -893,7 +901,7 @@ static void wined3d_texture_update_map_binding(struct wined3d_texture *texture) texture->update_map_binding = 0; }
-static void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding) +void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding) { texture->update_map_binding = map_binding; if (!texture->resource.map_count) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 4b7087a3807..97b4bb45215 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4401,6 +4401,9 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; void wined3d_texture_set_swapchain(struct wined3d_texture *texture, struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; +BOOL wined3d_texture_can_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info) + DECLSPEC_HIDDEN; +void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding) DECLSPEC_HIDDEN; void wined3d_texture_sub_resources_destroyed(struct wined3d_texture *texture) DECLSPEC_HIDDEN; void wined3d_texture_translate_drawable_coords(const struct wined3d_texture *texture, HWND window, RECT *rect) DECLSPEC_HIDDEN;
On Thu, 2 Sept 2021 at 15:14, Jan Sikorski jsikorski@codeweavers.com wrote:
@@ -2582,6 +2582,10 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void *
context = context_acquire(cs->c.device, NULL, 0);
if (src_texture->resource.map_binding != WINED3D_LOCATION_BUFFER
&& wined3d_texture_can_use_pbo(src_texture, &context->device->adapter->gl_info))
wined3d_texture_set_map_binding(src_texture, WINED3D_LOCATION_BUFFER);
Does it really make sense to change the map binding here? Presumably it would already have been set to BUFFER during texture creation for the cases where that makes sense. For the other cases, we should still be able to wined3d_texture_load_location(..., BUFFER) without changing the map binding, provided that location is supported.