wined3d: Add some barriers between resource usage on different bind points.

A typical case would be between using a texture as render target and using it
as a shader resource.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2021-01-19 14:34:57 +01:00 committed by Alexandre Julliard
parent e2e776462d
commit 82a9e80063
6 changed files with 137 additions and 24 deletions

View File

@ -1561,6 +1561,37 @@ HRESULT wined3d_buffer_vk_init(struct wined3d_buffer_vk *buffer_vk, struct wined
return wined3d_buffer_init(&buffer_vk->b, device, desc, data, parent, parent_ops, &wined3d_buffer_vk_ops);
}
void wined3d_buffer_vk_barrier(struct wined3d_buffer_vk *buffer_vk,
struct wined3d_context_vk *context_vk, uint32_t bind_mask)
{
TRACE("buffer_vk %p, context_vk %p, bind_mask %s.\n",
buffer_vk, context_vk, wined3d_debug_bind_flags(bind_mask));
if (buffer_vk->bind_mask && buffer_vk->bind_mask != bind_mask)
{
const struct wined3d_vk_info *vk_info = context_vk->vk_info;
VkBufferMemoryBarrier vk_barrier;
TRACE(" %s -> %s.\n",
wined3d_debug_bind_flags(buffer_vk->bind_mask), wined3d_debug_bind_flags(bind_mask));
vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
vk_barrier.pNext = NULL;
vk_barrier.srcAccessMask = vk_access_mask_from_bind_flags(buffer_vk->bind_mask);
vk_barrier.dstAccessMask = vk_access_mask_from_bind_flags(bind_mask);
vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vk_barrier.buffer = buffer_vk->bo.vk_buffer;
vk_barrier.offset = buffer_vk->bo.buffer_offset;
vk_barrier.size = buffer_vk->b.resource.size;
VK_CALL(vkCmdPipelineBarrier(wined3d_context_vk_get_command_buffer(context_vk),
vk_pipeline_stage_mask_from_bind_flags(buffer_vk->bind_mask),
vk_pipeline_stage_mask_from_bind_flags(bind_mask),
0, 0, NULL, 1, &vk_barrier, 0, NULL));
}
buffer_vk->bind_mask = bind_mask;
}
HRESULT CDECL wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc,
const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops,
struct wined3d_buffer **buffer)

View File

@ -2161,6 +2161,7 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
rtv_vk = wined3d_rendertarget_view_vk(view);
vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_RENDER_TARGET);
wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
if (view->width < fb_width)
@ -2177,6 +2178,7 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
{
rtv_vk = wined3d_rendertarget_view_vk(view);
vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_DEPTH_STENCIL);
wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
if (view->width < fb_width)
@ -2807,6 +2809,7 @@ static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk *
else
context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER);
}
wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_CONSTANT_BUFFER);
break;
case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
@ -2830,6 +2833,7 @@ static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk *
{
wined3d_texture_load(texture_from_resource(srv->resource), &context_vk->c, FALSE);
}
wined3d_shader_resource_view_vk_barrier(srv_vk, context_vk, WINED3D_BIND_SHADER_RESOURCE);
break;
case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
@ -2856,6 +2860,7 @@ static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk *
wined3d_texture_load(texture_from_resource(uav->resource), &context_vk->c, FALSE);
wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_TEXTURE_RGB);
}
wined3d_unordered_access_view_vk_barrier(uav_vk, context_vk, WINED3D_BIND_UNORDERED_ACCESS);
break;
case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
@ -2879,6 +2884,7 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c
struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
const struct wined3d_vk_info *vk_info = context_vk->vk_info;
struct wined3d_rendertarget_view *dsv;
struct wined3d_buffer_vk *buffer_vk;
VkSampleCountFlagBits sample_count;
VkCommandBuffer vk_command_buffer;
struct wined3d_buffer *buffer;
@ -2958,8 +2964,10 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c
if (!(buffer = state->streams[i].buffer))
continue;
wined3d_buffer_load(buffer, &context_vk->c, state);
if (!wined3d_buffer_vk(buffer)->bo_user.valid)
buffer_vk = wined3d_buffer_vk(buffer);
wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_VERTEX_BUFFER);
if (!buffer_vk->bo_user.valid)
context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
}
@ -2970,9 +2978,11 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c
if (!(buffer = state->stream_output[i].buffer))
continue;
wined3d_buffer_load(buffer, &context_vk->c, state);
wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER);
if (!wined3d_buffer_vk(buffer)->bo_user.valid)
buffer_vk = wined3d_buffer_vk(buffer);
wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_STREAM_OUTPUT);
wined3d_buffer_invalidate_location(&buffer_vk->b, ~WINED3D_LOCATION_BUFFER);
if (!buffer_vk->bo_user.valid)
context_vk->update_stream_output = 1;
}
context_vk->c.transform_feedback_active = 1;
@ -2980,13 +2990,18 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c
if (indexed || (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer))
{
wined3d_buffer_load(state->index_buffer, &context_vk->c, state);
if (!wined3d_buffer_vk(state->index_buffer)->bo_user.valid)
buffer_vk = wined3d_buffer_vk(state->index_buffer);
wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_INDEX_BUFFER);
if (!buffer_vk->bo_user.valid)
context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
}
if (indirect_vk)
{
wined3d_buffer_load(&indirect_vk->b, &context_vk->c, state);
wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
}
if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
{
@ -3031,7 +3046,6 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c
if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer)
{
struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(state->index_buffer);
const VkDescriptorBufferInfo *buffer_info;
VkIndexType idx_type;
@ -3039,6 +3053,7 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c
idx_type = VK_INDEX_TYPE_UINT16;
else
idx_type = VK_INDEX_TYPE_UINT32;
buffer_vk = wined3d_buffer_vk(state->index_buffer);
buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
VK_CALL(vkCmdBindIndexBuffer(vk_command_buffer, buffer_info->buffer,
@ -3108,7 +3123,10 @@ VkCommandBuffer wined3d_context_vk_apply_compute_state(struct wined3d_context_vk
wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_COMPUTE);
if (indirect_vk)
{
wined3d_buffer_load_location(&indirect_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
}
if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
{

View File

@ -577,7 +577,29 @@ VkAccessFlags vk_access_mask_from_bind_flags(uint32_t bind_flags)
if (bind_flags & WINED3D_BIND_DEPTH_STENCIL)
flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
if (bind_flags & WINED3D_BIND_STREAM_OUTPUT)
FIXME("Ignoring some bind flags %#x.\n", bind_flags);
flags |= VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT;
return flags;
}
VkPipelineStageFlags vk_pipeline_stage_mask_from_bind_flags(uint32_t bind_flags)
{
VkPipelineStageFlags flags = 0;
if (bind_flags & (WINED3D_BIND_VERTEX_BUFFER | WINED3D_BIND_INDEX_BUFFER))
flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
if (bind_flags & (WINED3D_BIND_CONSTANT_BUFFER | WINED3D_BIND_SHADER_RESOURCE | WINED3D_BIND_UNORDERED_ACCESS))
flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
| VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
if (bind_flags & WINED3D_BIND_INDIRECT_BUFFER)
flags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
if (bind_flags & WINED3D_BIND_RENDER_TARGET)
flags |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
if (bind_flags & WINED3D_BIND_DEPTH_STENCIL)
flags |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
if (bind_flags & WINED3D_BIND_STREAM_OUTPUT)
flags |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
return flags;
}

View File

@ -1057,6 +1057,7 @@ static void wined3d_swapchain_vk_blit(struct wined3d_swapchain_vk *swapchain_vk,
vk_access_mask_from_bind_flags(back_buffer_vk->t.resource.bind_flags),
vk_layout, back_buffer_vk->layout,
back_buffer_vk->vk_image, VK_IMAGE_ASPECT_COLOR_BIT);
back_buffer_vk->bind_mask = 0;
swapchain_vk->vk_semaphores[present_idx].command_buffer_id = context_vk->current_command_buffer.id;
wined3d_context_vk_submit_command_buffer(context_vk,

View File

@ -5185,6 +5185,26 @@ HRESULT wined3d_texture_vk_init(struct wined3d_texture_vk *texture_vk, struct wi
flags, device, parent, parent_ops, &texture_vk[1], &wined3d_texture_vk_ops);
}
void wined3d_texture_vk_barrier(struct wined3d_texture_vk *texture_vk,
struct wined3d_context_vk *context_vk, uint32_t bind_mask)
{
TRACE("texture_vk %p, context_vk %p, bind_mask %s.\n",
texture_vk, context_vk, wined3d_debug_bind_flags(bind_mask));
if (texture_vk->bind_mask && texture_vk->bind_mask != bind_mask)
{
TRACE(" %s -> %s.\n",
wined3d_debug_bind_flags(texture_vk->bind_mask), wined3d_debug_bind_flags(bind_mask));
wined3d_context_vk_image_barrier(context_vk, wined3d_context_vk_get_command_buffer(context_vk),
vk_pipeline_stage_mask_from_bind_flags(texture_vk->bind_mask),
vk_pipeline_stage_mask_from_bind_flags(bind_mask),
vk_access_mask_from_bind_flags(texture_vk->bind_mask), vk_access_mask_from_bind_flags(bind_mask),
texture_vk->layout, texture_vk->layout, texture_vk->vk_image,
vk_aspect_mask_from_format(texture_vk->t.resource.format));
}
texture_vk->bind_mask = bind_mask;
}
static void ffp_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context)
{
struct wined3d_blitter *next;
@ -6081,7 +6101,6 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
struct wined3d_rendertarget_view_vk *rtv_vk;
struct wined3d_rendertarget_view *view;
const struct wined3d_vk_info *vk_info;
struct wined3d_texture_vk *texture_vk;
struct wined3d_device_vk *device_vk;
VkCommandBuffer vk_command_buffer;
VkRenderPassBeginInfo begin_desc;
@ -6120,6 +6139,7 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
rtv_vk = wined3d_rendertarget_view_vk(view);
views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_RENDER_TARGET);
c = &clear_values[attachment_count].color;
if (view->format_flags & WINED3DFMT_FLAG_INTEGER)
@ -6154,6 +6174,7 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
rtv_vk = wined3d_rendertarget_view_vk(view);
views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_DEPTH_STENCIL);
clear_values[attachment_count].depthStencil.depth = depth;
clear_values[attachment_count].depthStencil.stencil = stencil;
@ -6231,26 +6252,12 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
continue;
wined3d_context_vk_reference_rendertarget_view(context_vk, wined3d_rendertarget_view_vk(view));
texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(view->resource));
wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
texture_vk->layout, texture_vk->layout,
texture_vk->vk_image, VK_IMAGE_ASPECT_COLOR_BIT);
}
if (depth_stencil)
{
view = fb->depth_stencil;
wined3d_context_vk_reference_rendertarget_view(context_vk, wined3d_rendertarget_view_vk(view));
texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(view->resource));
wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
texture_vk->layout, texture_vk->layout,
texture_vk->vk_image, vk_aspect_mask_from_format(texture_vk->t.resource.format));
}
}

View File

@ -308,6 +308,7 @@ 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;
static inline enum wined3d_cmp_func wined3d_sanitize_cmp_func(enum wined3d_cmp_func func)
@ -4446,6 +4447,7 @@ struct wined3d_texture_vk
struct wined3d_allocator_block *memory;
VkDeviceMemory vk_memory;
enum VkImageLayout layout;
uint32_t bind_mask;
uint64_t command_buffer_id;
VkDescriptorImageInfo default_image_info;
@ -4456,6 +4458,8 @@ static inline struct wined3d_texture_vk *wined3d_texture_vk(struct wined3d_textu
return CONTAINING_RECORD(texture, struct wined3d_texture_vk, t);
}
void wined3d_texture_vk_barrier(struct wined3d_texture_vk *texture_vk,
struct wined3d_context_vk *context_vk, uint32_t bind_mask) DECLSPEC_HIDDEN;
const VkDescriptorImageInfo *wined3d_texture_vk_get_default_image_info(struct wined3d_texture_vk *texture_vk,
struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
HRESULT wined3d_texture_vk_init(struct wined3d_texture_vk *texture_vk, struct wined3d_device *device,
@ -4915,6 +4919,7 @@ struct wined3d_buffer_vk
struct wined3d_bo_vk bo;
struct wined3d_bo_user bo_user;
VkDescriptorBufferInfo buffer_info;
uint32_t bind_mask;
};
static inline struct wined3d_buffer_vk *wined3d_buffer_vk(struct wined3d_buffer *buffer)
@ -4922,11 +4927,22 @@ static inline struct wined3d_buffer_vk *wined3d_buffer_vk(struct wined3d_buffer
return CONTAINING_RECORD(buffer, struct wined3d_buffer_vk, b);
}
void wined3d_buffer_vk_barrier(struct wined3d_buffer_vk *buffer_vk,
struct wined3d_context_vk *context_vk, uint32_t bind_mask) DECLSPEC_HIDDEN;
const VkDescriptorBufferInfo *wined3d_buffer_vk_get_buffer_info(struct wined3d_buffer_vk *buffer_vk) DECLSPEC_HIDDEN;
HRESULT wined3d_buffer_vk_init(struct wined3d_buffer_vk *buffer_vk, struct wined3d_device *device,
const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
static inline void wined3d_resource_vk_barrier(struct wined3d_resource *resource,
struct wined3d_context_vk *context_vk, uint32_t bind_mask)
{
if (resource->type == WINED3D_RTYPE_BUFFER)
wined3d_buffer_vk_barrier(wined3d_buffer_vk(buffer_from_resource(resource)), context_vk, bind_mask);
else
wined3d_texture_vk_barrier(wined3d_texture_vk(texture_from_resource(resource)), context_vk, bind_mask);
}
struct wined3d_rendertarget_view
{
LONG refcount;
@ -4992,6 +5008,12 @@ static inline struct wined3d_rendertarget_view_vk *wined3d_rendertarget_view_vk(
return CONTAINING_RECORD(view, struct wined3d_rendertarget_view_vk, v);
}
static inline void wined3d_rendertarget_view_vk_barrier(struct wined3d_rendertarget_view_vk *rtv_vk,
struct wined3d_context_vk *context_vk, uint32_t bind_mask)
{
wined3d_resource_vk_barrier(rtv_vk->v.resource, context_vk, bind_mask);
}
static inline VkImageView wined3d_rendertarget_view_vk_get_image_view(struct wined3d_rendertarget_view_vk *rtv_vk,
struct wined3d_context_vk *context_vk)
{
@ -5068,6 +5090,12 @@ static inline struct wined3d_shader_resource_view_vk *wined3d_shader_resource_vi
return CONTAINING_RECORD(view, struct wined3d_shader_resource_view_vk, v);
}
static inline void wined3d_shader_resource_view_vk_barrier(struct wined3d_shader_resource_view_vk *srv_vk,
struct wined3d_context_vk *context_vk, uint32_t bind_mask)
{
wined3d_resource_vk_barrier(srv_vk->v.resource, context_vk, bind_mask);
}
HRESULT wined3d_shader_resource_view_vk_init(struct wined3d_shader_resource_view_vk *view_vk,
const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
@ -5133,6 +5161,12 @@ static inline struct wined3d_unordered_access_view_vk *wined3d_unordered_access_
return CONTAINING_RECORD(view, struct wined3d_unordered_access_view_vk, v);
}
static inline void wined3d_unordered_access_view_vk_barrier(struct wined3d_unordered_access_view_vk *uav_vk,
struct wined3d_context_vk *context_vk, uint32_t bind_mask)
{
wined3d_resource_vk_barrier(uav_vk->v.resource, context_vk, bind_mask);
}
void wined3d_unordered_access_view_vk_clear_uint(struct wined3d_unordered_access_view_vk *view_vk,
const struct wined3d_uvec4 *clear_value, struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
HRESULT wined3d_unordered_access_view_vk_init(struct wined3d_unordered_access_view_vk *view_vk,