[PATCH 2/4] wined3d: Tell Vulkan about discarded and cleared framebuffer attachments.

Stefan Dösinger stefan at codeweavers.com
Sun Apr 24 11:24:47 CDT 2022


Signed-off-by: Stefan Dösinger <stefan at codeweavers.com>
---
 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,
-- 
2.35.1




More information about the wine-devel mailing list