Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/texture.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 6663e788e9c..6ecec939964 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -859,6 +859,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 +880,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; @@ -2110,12 +2117,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) {
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) {
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/texture.c | 90 +++++++++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 27 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index ad96cf2ea65..75479f5066a 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -4845,12 +4845,16 @@ 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; + size_t dst_offset = 0; void *map_ptr;
TRACE("context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_box %s, dst_bo_addr %s, " @@ -4876,12 +4880,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", @@ -4923,11 +4921,37 @@ 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)) + /* 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 (!(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 + (size_t)dst_bo_addr->addr; + vk_barrier.size = sub_resource->size; + + bo_stage_flags = vk_pipeline_stage_mask_from_buffer_usage(dst_bo->usage); + dst_offset = (size_t)dst_bo_addr->addr; + + 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; @@ -4943,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 + dst_offset; region.bufferRowLength = 0; region.bufferImageHeight = 0; region.imageSubresource.aspectMask = vk_range.aspectMask; @@ -4958,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, @@ -4968,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 == &staging_bo) { - ERR("Failed to map staging bo.\n"); + 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); + + 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); - return; } + else + { + vk_barrier.dstAccessMask = vk_barrier.srcAccessMask; + vk_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- 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); + VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + bo_stage_flags, 0, 0, NULL, 1, &vk_barrier, 0, NULL)); + } }
static BOOL wined3d_texture_vk_load_texture(struct wined3d_texture_vk *texture_vk,
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/adapter_gl.c | 1 + dlls/wined3d/adapter_vk.c | 1 + dlls/wined3d/texture.c | 12 +++++------- dlls/wined3d/wined3d_private.h | 1 + 4 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 902b9620f30..f20e93df67e 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -5129,6 +5129,7 @@ static void wined3d_adapter_gl_init_d3d_info(struct wined3d_adapter_gl *adapter_ d3d_info->clip_control = !!gl_info->supported[ARB_CLIP_CONTROL]; d3d_info->full_ffp_varyings = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_FULL_FFP_VARYINGS); d3d_info->scaled_resolve = !!gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE_BLIT_SCALED]; + d3d_info->pbo = !!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]; d3d_info->feature_level = feature_level_from_caps(gl_info, &shader_caps, &fragment_caps);
if (gl_info->supported[ARB_TEXTURE_MULTISAMPLE]) diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 1db25a4d72f..74540134e10 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -2198,6 +2198,7 @@ static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_ d3d_info->clip_control = true; d3d_info->full_ffp_varyings = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_FULL_FFP_VARYINGS); d3d_info->scaled_resolve = false; + d3d_info->pbo = false; d3d_info->feature_level = feature_level_from_caps(&shader_caps);
d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 75479f5066a..1c885b72c10 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -47,10 +47,9 @@ struct wined3d_rect_f float b; };
-static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info) +static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_d3d_info *d3d_info) { - if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] - || texture->resource.format->conv_byte_count + if (!d3d_info->pbo || texture->resource.format->conv_byte_count || (texture->flags & (WINED3D_TEXTURE_PIN_SYSMEM | WINED3D_TEXTURE_COND_NP2_EMULATED))) return FALSE;
@@ -1962,7 +1961,7 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, unsig * If the surface didn't use PBOs previously but could now, don't * change it - whatever made us not use PBOs might come back, e.g. * color keys. */ - if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER && !wined3d_texture_use_pbo(texture, gl_info)) + if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER && !wined3d_texture_use_pbo(texture, d3d_info)) texture->resource.map_binding = WINED3D_LOCATION_SYSMEM;
wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_SYSMEM); @@ -3629,7 +3628,6 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc { const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; struct wined3d_device_parent *device_parent = device->device_parent; - const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; unsigned int sub_count, i, j, size, offset = 0; unsigned int pow2_width, pow2_height; const struct wined3d_format *format; @@ -3837,11 +3835,11 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc texture->pow2_matrix[15] = 1.0f; TRACE("x scale %.8e, y scale %.8e.\n", texture->pow2_matrix[0], texture->pow2_matrix[5]);
- if (wined3d_texture_use_pbo(texture, gl_info)) + if (wined3d_texture_use_pbo(texture, d3d_info)) texture->resource.map_binding = WINED3D_LOCATION_BUFFER;
if (desc->resource_type != WINED3D_RTYPE_TEXTURE_3D - || !wined3d_texture_use_pbo(texture, gl_info)) + || !wined3d_texture_use_pbo(texture, d3d_info)) { if (!wined3d_resource_prepare_sysmem(&texture->resource)) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 601fefd0145..508ad3634e2 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -239,6 +239,7 @@ struct wined3d_d3d_info uint32_t clip_control : 1; uint32_t full_ffp_varyings : 1; uint32_t scaled_resolve : 1; + uint32_t pbo : 1; enum wined3d_feature_level feature_level;
DWORD multisample_draw_location;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/adapter_vk.c | 2 +- dlls/wined3d/texture.c | 55 ++++++++++++++++++++++++++++------ dlls/wined3d/wined3d_private.h | 6 +++- 3 files changed, 52 insertions(+), 11 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 74540134e10..69a93f88435 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -2198,7 +2198,7 @@ static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_ d3d_info->clip_control = true; d3d_info->full_ffp_varyings = !!(shader_caps.wined3d_caps & WINED3D_SHADER_CAP_FULL_FFP_VARYINGS); d3d_info->scaled_resolve = false; - d3d_info->pbo = false; + d3d_info->pbo = true; d3d_info->feature_level = feature_level_from_caps(&shader_caps);
d3d_info->multisample_draw_location = WINED3D_LOCATION_TEXTURE_RGB; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 1c885b72c10..d4069361424 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -850,7 +850,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);
@@ -1986,7 +1986,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;
@@ -3152,7 +3152,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 +3289,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; @@ -5033,14 +5033,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, @@ -5051,7 +5051,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; @@ -5066,7 +5066,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, @@ -5182,6 +5182,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) { @@ -5194,6 +5214,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; @@ -5212,7 +5236,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)); @@ -5225,6 +5250,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));
@@ -5243,6 +5269,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 508ad3634e2..a415dc53372 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4294,7 +4294,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;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/adapter_vk.c | 43 +++++++++++++++++++--------------- dlls/wined3d/context_vk.c | 2 ++ dlls/wined3d/texture.c | 9 +++++++ dlls/wined3d/wined3d_private.h | 1 + 4 files changed, 36 insertions(+), 19 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 69a93f88435..18c73312daf 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 705f789ed5f..aeaeca322ff 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 d4069361424..219ccfae6a6 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -5019,6 +5019,12 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, vk_barrier.dstAccessMask = vk_barrier.srcAccessMask; vk_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ if (dst_bo->host_synced) + { + vk_barrier.srcAccessMask |= VK_ACCESS_HOST_READ_BIT; + bo_stage_flags |= VK_PIPELINE_STAGE_HOST_BIT; + } + VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, bo_stage_flags, 0, 0, NULL, 1, &vk_barrier, 0, NULL)); } @@ -5198,6 +5204,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 a415dc53372..6b69465c92b 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1626,6 +1626,7 @@ struct wined3d_bo_vk
struct list users; uint64_t command_buffer_id; + bool host_synced; };
struct wined3d_bo_slab_vk_key
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Load the source texture to WINED3D_LOCATION_BUFFER, so that the copy is GPU-side only.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/cs.c | 12 +++++++++--- dlls/wined3d/texture.c | 10 +++++++++- dlls/wined3d/wined3d_private.h | 2 ++ 3 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 51e5055c4ab..1f03833e0ed 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -2550,6 +2550,7 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * unsigned int row_pitch, slice_pitch; struct wined3d_context *context; struct wined3d_bo_address addr; + unsigned int location;
if (op->flags & ~WINED3D_BLT_RAW) { @@ -2582,11 +2583,16 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void *
context = context_acquire(cs->c.device, NULL, 0);
+ location = src_texture->resource.map_binding; + if (location == WINED3D_LOCATION_SYSMEM + && wined3d_texture_can_use_pbo(src_texture, &context->device->adapter->d3d_info)) + location = WINED3D_LOCATION_BUFFER; + if (!wined3d_texture_load_location(src_texture, op->src_sub_resource_idx, - context, src_texture->resource.map_binding)) + context, location)) { ERR("Failed to load source sub-resource into %s.\n", - wined3d_debug_location(src_texture->resource.map_binding)); + wined3d_debug_location(location)); context_release(context); goto error; } @@ -2607,7 +2613,7 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * goto error; }
- wined3d_texture_get_memory(src_texture, op->src_sub_resource_idx, &addr, src_texture->resource.map_binding); + wined3d_texture_get_memory(src_texture, op->src_sub_resource_idx, &addr, location); wined3d_texture_get_pitch(src_texture, op->src_sub_resource_idx % src_texture->level_count, &row_pitch, &slice_pitch);
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 219ccfae6a6..ab9cdcee6d6 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -47,12 +47,20 @@ struct wined3d_rect_f float b; };
-static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const struct wined3d_d3d_info *d3d_info) +BOOL wined3d_texture_can_use_pbo(const struct wined3d_texture *texture, const struct wined3d_d3d_info *d3d_info) { if (!d3d_info->pbo || texture->resource.format->conv_byte_count || (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_d3d_info *d3d_info) +{ + if (!wined3d_texture_can_use_pbo(texture, d3d_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) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 6b69465c92b..2e1fa3fd943 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4400,6 +4400,8 @@ 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_d3d_info *d3d_info) + 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;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com