Stefan Dösinger : wined3d: Tell Vulkan about discarded and cleared framebuffer attachments.
Alexandre Julliard
julliard at winehq.org
Mon Apr 25 16:30:33 CDT 2022
Module: wine
Branch: master
Commit: 2a283004abfbd94d9d967b929ddff9d86b11fa8c
URL: https://source.winehq.org/git/wine.git/?a=commit;h=2a283004abfbd94d9d967b929ddff9d86b11fa8c
Author: Stefan Dösinger <stefan at codeweavers.com>
Date: Sun Apr 24 19:24:47 2022 +0300
wined3d: Tell Vulkan about discarded and cleared framebuffer attachments.
Signed-off-by: Stefan Dösinger <stefan at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/wined3d/context_vk.c | 53 +++++++++++++++++++++++++++++++++++-------
dlls/wined3d/view.c | 23 ++++++++++++++++++
dlls/wined3d/wined3d_private.h | 9 ++++++-
3 files changed, 76 insertions(+), 9 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index c3108811e2c..059c44fee9a 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -1250,6 +1250,7 @@ static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *k
struct wined3d_render_pass_attachment_vk *a;
struct wined3d_rendertarget_view *view;
unsigned int i;
+ DWORD location;
memset(key, 0, sizeof(*key));
@@ -1262,6 +1263,15 @@ static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *k
a->vk_format = wined3d_format_vk(view->format)->vk_format;
a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
+ location = wined3d_rendertarget_view_get_locations(view);
+
+ if (clear_flags & WINED3DCLEAR_TARGET)
+ a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C;
+ else if (location & WINED3D_LOCATION_DISCARDED)
+ a->flags = WINED3D_FB_ATTACHMENT_FLAG_DISCARDED;
+ else if (location & WINED3D_LOCATION_CLEARED)
+ a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C;
+
key->rt_mask |= 1u << i;
}
@@ -1271,10 +1281,19 @@ static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *k
a->vk_format = wined3d_format_vk(view->format)->vk_format;
a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
+ location = wined3d_rendertarget_view_get_locations(view);
key->rt_mask |= 1u << WINED3D_MAX_RENDER_TARGETS;
- }
- key->clear_flags = clear_flags;
+ if (clear_flags & WINED3DCLEAR_STENCIL)
+ a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S;
+ if (clear_flags & WINED3DCLEAR_ZBUFFER)
+ a->flags |= WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z;
+
+ if (!a->flags && (location & WINED3D_LOCATION_DISCARDED))
+ a->flags = WINED3D_FB_ATTACHMENT_FLAG_DISCARDED;
+ else if (location & WINED3D_LOCATION_CLEARED)
+ a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S | WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z;
+ }
}
static void wined3d_render_pass_vk_cleanup(struct wined3d_render_pass_vk *pass,
@@ -1315,10 +1334,14 @@ static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
attachment->flags = 0;
attachment->format = a->vk_format;
attachment->samples = a->vk_samples;
- if (key->clear_flags & WINED3DCLEAR_TARGET)
+
+ if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_DISCARDED)
+ attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ else if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C)
attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
else
attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+
attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
@@ -1348,15 +1371,22 @@ static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
attachment->flags = 0;
attachment->format = a->vk_format;
attachment->samples = a->vk_samples;
- if (key->clear_flags & WINED3DCLEAR_ZBUFFER)
+
+ if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_DISCARDED)
+ attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ else if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z)
attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
else
attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- if (key->clear_flags & WINED3DCLEAR_STENCIL)
+
+ if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_DISCARDED)
+ attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ else if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S)
attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
else
attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+
+ attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment->initialLayout = a->vk_layout;
attachment->finalLayout = a->vk_layout;
@@ -2464,6 +2494,7 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
{
struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
+ static const VkClearValue clear_values[WINED3D_MAX_RENDER_TARGETS + 1];
VkImageView vk_views[WINED3D_MAX_RENDER_TARGETS + 1];
unsigned int fb_width, fb_height, fb_layer_count;
struct wined3d_rendertarget_view_vk *rtv_vk;
@@ -2485,6 +2516,7 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
attachment_count = 0;
context_vk->rt_count = 0;
+ begin_info.clearValueCount = 0;
for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
{
if (!(view = state->fb.render_targets[i]) || view->format->id == WINED3DFMT_NULL)
@@ -2503,6 +2535,9 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
fb_layer_count = view->layer_count;
context_vk->rt_count = i + 1;
++attachment_count;
+
+ if (wined3d_rendertarget_view_get_locations(view) & WINED3D_LOCATION_CLEARED)
+ begin_info.clearValueCount = attachment_count;
}
if ((view = state->fb.depth_stencil))
@@ -2519,6 +2554,9 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
if (view->layer_count < fb_layer_count)
fb_layer_count = view->layer_count;
++attachment_count;
+
+ if (wined3d_rendertarget_view_get_locations(view) & WINED3D_LOCATION_CLEARED)
+ begin_info.clearValueCount = attachment_count;
}
if (!(context_vk->vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, &state->fb,
@@ -2552,8 +2590,7 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
begin_info.renderArea.offset.y = 0;
begin_info.renderArea.extent.width = fb_width;
begin_info.renderArea.extent.height = fb_height;
- begin_info.clearValueCount = 0;
- begin_info.pClearValues = NULL;
+ begin_info.pClearValues = clear_values;
VK_CALL(vkCmdBeginRenderPass(vk_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE));
LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index 051da2891f3..752563508c8 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -511,6 +511,29 @@ void wined3d_rendertarget_view_invalidate_location(struct wined3d_rendertarget_v
wined3d_view_invalidate_location(view->resource, &view->desc, location);
}
+/* Note: This may return 0 if the selected layers do not have a location in common. */
+DWORD wined3d_rendertarget_view_get_locations(const struct wined3d_rendertarget_view *view)
+{
+ struct wined3d_resource *resource = view->resource;
+ unsigned int i, sub_resource_idx, layer_count;
+ const struct wined3d_texture *texture;
+ DWORD ret = ~0u;
+
+ if (resource->type == WINED3D_RTYPE_BUFFER)
+ return buffer_from_resource(resource)->locations;
+
+ texture = texture_from_resource(resource);
+ sub_resource_idx = view->sub_resource_idx;
+ layer_count = resource->type != WINED3D_RTYPE_TEXTURE_3D ? view->layer_count : 1;
+ for (i = 0; i < layer_count; ++i, sub_resource_idx += texture->level_count)
+ ret &= texture->sub_resources[sub_resource_idx].locations;
+
+ if (!ret)
+ WARN("View %p (texture %p) layers do not have a location in common.\n", view, texture);
+
+ return ret;
+}
+
static void wined3d_render_target_view_gl_cs_init(void *object)
{
struct wined3d_rendertarget_view_gl *view_gl = object;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 0ddad7ee5ec..35925b04cd1 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2456,11 +2456,17 @@ struct wined3d_retired_objects_vk
SIZE_T count;
};
+#define WINED3D_FB_ATTACHMENT_FLAG_DISCARDED 1
+#define WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C 2
+#define WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S 4
+#define WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z 8
+
struct wined3d_render_pass_attachment_vk
{
VkFormat vk_format;
VkSampleCountFlagBits vk_samples;
VkImageLayout vk_layout;
+ uint32_t flags;
};
struct wined3d_render_pass_key_vk
@@ -2468,7 +2474,6 @@ struct wined3d_render_pass_key_vk
struct wined3d_render_pass_attachment_vk rt[WINED3D_MAX_RENDER_TARGETS];
struct wined3d_render_pass_attachment_vk ds;
uint32_t rt_mask;
- uint32_t clear_flags;
};
struct wined3d_render_pass_vk
@@ -5283,6 +5288,8 @@ void wined3d_rendertarget_view_prepare_location(struct wined3d_rendertarget_view
struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
void wined3d_rendertarget_view_validate_location(struct wined3d_rendertarget_view *view,
DWORD location) DECLSPEC_HIDDEN;
+DWORD wined3d_rendertarget_view_get_locations(const struct wined3d_rendertarget_view *view)
+ DECLSPEC_HIDDEN;
HRESULT wined3d_rendertarget_view_no3d_init(struct wined3d_rendertarget_view *view_no3d,
const struct wined3d_view_desc *desc, struct wined3d_resource *resource,
More information about the wine-cvs
mailing list