[PATCH v2 3/4] wined3d: Store clear colors in subresources (v3).

Stefan Dösinger wine at gitlab.winehq.org
Tue May 24 05:59:47 CDT 2022


From: Stefan Dösinger <stefan at codeweavers.com>

Signed-off-by: Stefan Dösinger <stefan at codeweavers.com>

---

Version 3: Add an ERR check in the GL path.
Version 2: Take the new wined3d_texture_vk_clear into account.

@Zeb: I can't write a FIXME in wined3d_buffer_load_location for non-zero
colors because buffers don't (yet) store clear colors. The proper place
to write a FIXME would be when delaying a buffer clear, but right now
we'll never enter the clear code for buffers. (wined3d_device_clear
is <= d3d9 only and wined3d_device_context_clear_rendertarget_view has a
FIXME("Not implemented for buffer resources.\n");
---
 dlls/wined3d/context_vk.c      | 41 +++++++++++++--
 dlls/wined3d/texture.c         | 91 ++++++++++++++++++++++------------
 dlls/wined3d/utils.c           | 19 +++++++
 dlls/wined3d/wined3d_private.h | 11 ++++
 4 files changed, 125 insertions(+), 37 deletions(-)

diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index aa3b45d54fd..c257b5f3c86 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -2509,7 +2509,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];
+    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;
@@ -2518,6 +2518,7 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
     struct wined3d_query_vk *query_vk;
     VkRenderPassBeginInfo begin_info;
     unsigned int attachment_count, i;
+    struct wined3d_texture *texture;
     VkFramebufferCreateInfo fb_desc;
     VkResult vr;
 
@@ -2549,10 +2550,25 @@ 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;
         context_vk->rt_count = i + 1;
-        ++attachment_count;
 
         if (wined3d_rendertarget_view_get_locations(view) & WINED3D_LOCATION_CLEARED)
-            begin_info.clearValueCount = attachment_count;
+        {
+            VkClearColorValue *c = &clear_values[attachment_count].color;
+
+            if (view->resource->type == WINED3D_RTYPE_BUFFER)
+            {
+                c->int32[0] = c->int32[1] = c->int32[2] = c->int32[3] = 0;
+            }
+            else
+            {
+                texture = texture_from_resource(view->resource);
+                wined3d_format_colour_to_vk(view->format,
+                        &texture->sub_resources[view->sub_resource_idx].clear_value.colour, c);
+            }
+
+            begin_info.clearValueCount = attachment_count + 1;
+        }
+        ++attachment_count;
     }
 
     if ((view = state->fb.depth_stencil))
@@ -2568,10 +2584,25 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
             fb_height = view->height;
         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;
+        {
+            VkClearDepthStencilValue *c = &clear_values[attachment_count].depthStencil;
+
+            if (view->resource->type == WINED3D_RTYPE_BUFFER)
+            {
+                c->depth = 0.0f;
+                c->stencil = 0;
+            }
+            else
+            {
+                texture = texture_from_resource(view->resource);
+                c->depth = texture->sub_resources[view->sub_resource_idx].clear_value.depth;
+                c->stencil = texture->sub_resources[view->sub_resource_idx].clear_value.stencil;
+            }
+            begin_info.clearValueCount = attachment_count + 1;
+        }
+        ++attachment_count;
     }
 
     if (!(context_vk->vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, &state->fb,
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 0f45d5c844e..7dfedd65ecc 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -823,10 +823,22 @@ BOOL wined3d_texture_load_location(struct wined3d_texture *texture,
         range.size = texture->sub_resources[sub_resource_idx].size;
         if (current & WINED3D_LOCATION_CLEARED)
         {
-            static const struct wined3d_color black;
             unsigned int level_idx = sub_resource_idx % texture->level_count;
             struct wined3d_map_desc map;
             struct wined3d_box box;
+            struct wined3d_color c;
+
+            if (texture->resource.format->flags[WINED3D_GL_RES_TYPE_TEX_2D]
+                    & WINED3DFMT_FLAG_DEPTH_STENCIL)
+            {
+                c.r = texture->sub_resources[sub_resource_idx].clear_value.depth;
+                c.g = texture->sub_resources[sub_resource_idx].clear_value.stencil;
+                c.b = c.a = 0.0f;
+            }
+            else
+            {
+                c = texture->sub_resources[sub_resource_idx].clear_value.colour;
+            }
 
             wined3d_texture_get_pitch(texture, level_idx, &map.row_pitch, &map.slice_pitch);
             if (destination.buffer_object)
@@ -836,7 +848,7 @@ BOOL wined3d_texture_load_location(struct wined3d_texture *texture,
                 map.data = destination.addr;
 
             wined3d_texture_get_level_box(texture, level_idx, &box);
-            wined3d_resource_memory_colour_fill(&texture->resource, &map, &black, &box, true);
+            wined3d_resource_memory_colour_fill(&texture->resource, &map, &c, &box, true);
 
             if (destination.buffer_object)
                 wined3d_context_unmap_bo_address(context, &destination, 1, &range);
@@ -3370,6 +3382,27 @@ static bool wined3d_texture_gl_clear(struct wined3d_texture *texture,
     const struct wined3d_gl_info *gl_info = context_gl->gl_info;
     struct wined3d_bo_address addr;
 
+    /* The code that delays clears is Vulkan-specific, so here we should only
+     * encounter WINED3D_LOCATION_CLEARED on newly created resources and thus
+     * a zero clear value. */
+    if (!format->depth_size && !format->stencil_size)
+    {
+        if (sub_resource->clear_value.colour.r || sub_resource->clear_value.colour.g
+                || sub_resource->clear_value.colour.b || sub_resource->clear_value.colour.a)
+        {
+            ERR("Unexpected color clear value r=%08e, g=%08e, b=%08e, a=%08e.\n",
+                    sub_resource->clear_value.colour.r, sub_resource->clear_value.colour.g,
+                    sub_resource->clear_value.colour.b, sub_resource->clear_value.colour.a);
+        }
+    }
+    else
+    {
+        if (format->depth_size && sub_resource->clear_value.depth)
+            ERR("Unexpected depth clear value %08e.\n", sub_resource->clear_value.depth);
+        if (format->stencil_size && sub_resource->clear_value.stencil)
+            ERR("Unexpected stencil clear value %x.\n", sub_resource->clear_value.stencil);
+    }
+
     if (use_ffp_clear(texture, location))
     {
         GLbitfield clear_mask = 0;
@@ -5281,16 +5314,20 @@ static bool wined3d_texture_vk_clear(struct wined3d_texture_vk *texture_vk,
     struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
     const struct wined3d_format *format = texture_vk->t.resource.format;
     const struct wined3d_vk_info *vk_info = context_vk->vk_info;
-    static const VkClearDepthStencilValue depth_value;
-    static const VkClearColorValue colour_value;
+    VkClearDepthStencilValue depth_value;
     VkCommandBuffer vk_command_buffer;
     VkImageSubresourceRange vk_range;
+    VkClearColorValue colour_value;
     VkImageAspectFlags aspect_mask;
     VkImage vk_image;
 
     if (texture_vk->t.resource.format_flags & WINED3DFMT_FLAG_COMPRESSED)
     {
         struct wined3d_bo_address addr;
+        struct wined3d_color *c = &sub_resource->clear_value.colour;
+
+        if (c->r || c->g || c-> b || c->a)
+            FIXME("Compressed resource %p is cleared to a non-zero color.\n", &texture_vk->t);
 
         if (!wined3d_texture_prepare_location(&texture_vk->t, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM))
             return false;
@@ -5324,11 +5361,18 @@ static bool wined3d_texture_vk_clear(struct wined3d_texture_vk *texture_vk,
             texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vk_image, &vk_range);
 
     if (format->depth_size || format->stencil_size)
+    {
+        depth_value.depth = sub_resource->clear_value.depth;
+        depth_value.stencil = sub_resource->clear_value.stencil;
         VK_CALL(vkCmdClearDepthStencilImage(vk_command_buffer, vk_image,
                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &depth_value, 1, &vk_range));
+    }
     else
+    {
+        wined3d_format_colour_to_vk(format, &sub_resource->clear_value.colour, &colour_value);
         VK_CALL(vkCmdClearColorImage(vk_command_buffer, vk_image,
                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &colour_value, 1, &vk_range));
+    }
 
     wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
             VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
@@ -6635,18 +6679,12 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
 
         if (is_full_clear(view, draw_rect, clear_rects))
         {
-            if (!colour->r && !colour->g && !colour->b && !colour->a)
-            {
-                wined3d_rendertarget_view_validate_location(view, WINED3D_LOCATION_CLEARED);
-                wined3d_rendertarget_view_invalidate_location(view, ~WINED3D_LOCATION_CLEARED);
-                delay_count++;
-                continue;
-            }
-            else
-            {
-                TRACE_(d3d_perf)("non-zero clear\n");
-                wined3d_rendertarget_view_prepare_location(view, &context_vk->c, view->resource->draw_binding);
-            }
+            struct wined3d_texture *texture = texture_from_resource(view->resource);
+            wined3d_rendertarget_view_validate_location(view, WINED3D_LOCATION_CLEARED);
+            wined3d_rendertarget_view_invalidate_location(view, ~WINED3D_LOCATION_CLEARED);
+            texture->sub_resources[view->sub_resource_idx].clear_value.colour = *colour;
+            delay_count++;
+            continue;
         }
         else
         {
@@ -6660,20 +6698,7 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_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)
-        {
-            c->int32[0] = colour->r;
-            c->int32[1] = colour->g;
-            c->int32[2] = colour->b;
-            c->int32[3] = colour->a;
-        }
-        else
-        {
-            c->float32[0] = colour->r;
-            c->float32[1] = colour->g;
-            c->float32[2] = colour->b;
-            c->float32[3] = colour->a;
-        }
+        wined3d_format_colour_to_vk(view->format, colour, c);
 
         if (view->layer_count > layer_count)
             layer_count = view->layer_count;
@@ -6697,8 +6722,7 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
         if (view->format->stencil_size)
             full_flags |= WINED3DCLEAR_STENCIL;
 
-        if (!is_full_clear(view, draw_rect, clear_rects)
-                || depth || stencil || (flags & full_flags) != full_flags)
+        if (!is_full_clear(view, draw_rect, clear_rects) || (flags & full_flags) != full_flags)
         {
             wined3d_rendertarget_view_load_location(view, &context_vk->c, view->resource->draw_binding);
             wined3d_rendertarget_view_validate_location(view, view->resource->draw_binding);
@@ -6719,6 +6743,9 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
         }
         else
         {
+            struct wined3d_texture *texture = texture_from_resource(view->resource);
+            texture->sub_resources[view->sub_resource_idx].clear_value.depth = depth;
+            texture->sub_resources[view->sub_resource_idx].clear_value.stencil = stencil;
             wined3d_rendertarget_view_validate_location(view, WINED3D_LOCATION_CLEARED);
             wined3d_rendertarget_view_invalidate_location(view, ~WINED3D_LOCATION_CLEARED);
             flags &= ~(WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL);
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 088a904ffeb..3680bcf6425 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -6008,6 +6008,25 @@ uint32_t wined3d_format_pack(const struct wined3d_format *format, const struct w
     return p;
 }
 
+void wined3d_format_colour_to_vk(const struct wined3d_format *format, const struct wined3d_color *c,
+        VkClearColorValue *retval)
+{
+    if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_INTEGER)
+    {
+        retval->int32[0] = c->r;
+        retval->int32[1] = c->g;
+        retval->int32[2] = c->b;
+        retval->int32[3] = c->a;
+    }
+    else
+    {
+        retval->float32[0] = c->r;
+        retval->float32[1] = c->g;
+        retval->float32[2] = c->b;
+        retval->float32[3] = c->a;
+    }
+}
+
 /* Note: It's the caller's responsibility to ensure values can be expressed
  * in the requested format. UNORM formats for example can only express values
  * in the range 0.0f -> 1.0f.
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index cd88e70c9ce..835a1346d03 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4559,6 +4559,15 @@ struct wined3d_texture
         uint32_t map_flags;
         DWORD locations;
         struct wined3d_bo *bo;
+        union
+        {
+            struct wined3d_color colour;
+            struct
+            {
+                float depth;
+                unsigned int stencil;
+            };
+        } clear_value;
 
         void *user_memory;
     } *sub_resources;
@@ -6211,6 +6220,8 @@ void wined3d_format_calculate_pitch(const struct wined3d_format *format, unsigne
         unsigned int width, unsigned int height, unsigned int *row_pitch, unsigned int *slice_pitch) DECLSPEC_HIDDEN;
 UINT wined3d_format_calculate_size(const struct wined3d_format *format,
         UINT alignment, UINT width, UINT height, UINT depth) DECLSPEC_HIDDEN;
+void wined3d_format_colour_to_vk(const struct wined3d_format *format, const struct wined3d_color *c,
+        VkClearColorValue *retval) DECLSPEC_HIDDEN;
 void wined3d_format_convert_from_float(const struct wined3d_format *format,
         const struct wined3d_color *color, void *ret) DECLSPEC_HIDDEN;
 void wined3d_format_copy_data(const struct wined3d_format *format, const uint8_t *src,
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/109



More information about the wine-devel mailing list