This patches allow us to use VK_ATTACHMENT_LOAD_OP_CLEAR and VK_ATTACHMENT_LOAD_OP_DONT_CARE for cleared and discarded textures in some conditions. I wrote them in an attempt to improve improve Rocket League performance, but in their current state they don't produce a measurable gain yet. They still seem like the right thing to do.
To matter in Rocket League, support for non-zero clear values needs to be added. This needs a bit more work on the fallback path (something along the lines of calling surface_cpu_blt_colour_fill and extending it to support floats). Rocket League also clears the depth component of a Depth-Stencil surface without clearing the Stencil part. Vulkan supports that, but it is not easy to integrate it with our location management.
Stefan Dösinger (4): wined3d: Invalidate framebuffer locations after setting up the renderpass. wined3d: Tell Vulkan about discarded and cleared framebuffer attachments. wined3d: Don't explicitly clear the draw location before starting a renderpass. wined3d: Set WINED3D_LOCATION_CLEARED for full-subresource clears to black.
dlls/wined3d/context_vk.c | 94 ++++++++++++++++++++++++++++------ dlls/wined3d/texture.c | 86 ++++++++++++++++++++++++------- dlls/wined3d/view.c | 23 +++++++++ dlls/wined3d/wined3d_private.h | 9 +++- 4 files changed, 177 insertions(+), 35 deletions(-)
Signed-off-by: Stefan Dösinger stefan@codeweavers.com
---
So we can communicate discarded or cleared attachments to Vulkan. --- dlls/wined3d/context_vk.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 9891bf0b541..c3108811e2c 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -3309,12 +3309,14 @@ 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_rendertarget_view *rtv; struct wined3d_buffer_vk *buffer_vk; VkSampleCountFlagBits sample_count; VkCommandBuffer vk_command_buffer; + unsigned int i, invalidate_rt = 0; struct wined3d_buffer *buffer; uint32_t null_buffer_binding; - unsigned int i; + bool invalidate_ds = false;
if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)) || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER)) @@ -3331,15 +3333,13 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c context_vk->sample_count = 0; for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i) { - struct wined3d_rendertarget_view *rtv; - if (!(rtv = state->fb.render_targets[i]) || rtv->format->id == WINED3DFMT_NULL) continue;
if (wined3d_blend_state_get_writemask(state->blend_state, i)) { wined3d_rendertarget_view_load_location(rtv, &context_vk->c, rtv->resource->draw_binding); - wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding); + invalidate_rt |= (1 << i); } else { @@ -3360,7 +3360,7 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c else wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding); if (!state->depth_stencil_state || state->depth_stencil_state->desc.depth_write) - wined3d_rendertarget_view_invalidate_location(dsv, ~dsv->resource->draw_binding); + invalidate_ds = true;
sample_count = max(1, wined3d_resource_get_sample_count(dsv->resource)); if (!context_vk->sample_count) @@ -3443,6 +3443,16 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c return VK_NULL_HANDLE; }
+ while (invalidate_rt) + { + i = wined3d_bit_scan(&invalidate_rt); + rtv = state->fb.render_targets[i]; + wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding); + } + + if (invalidate_ds) + wined3d_rendertarget_view_invalidate_location(dsv, ~dsv->resource->draw_binding); + if (wined3d_context_vk_update_graphics_pipeline_key(context_vk, state, context_vk->graphics.vk_pipeline_layout, &null_buffer_binding) || !context_vk->graphics.vk_pipeline) {
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Stefan Dösinger stefan@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,
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Stefan Dösinger stefan@codeweavers.com --- dlls/wined3d/context_vk.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 059c44fee9a..b19220c2e34 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -3375,7 +3375,12 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c
if (wined3d_blend_state_get_writemask(state->blend_state, i)) { - wined3d_rendertarget_view_load_location(rtv, &context_vk->c, rtv->resource->draw_binding); + /* We handle clears at the beginning of the render pass, no need for an explicit clear + * first. */ + if (wined3d_rendertarget_view_get_locations(rtv) & WINED3D_LOCATION_CLEARED) + wined3d_rendertarget_view_prepare_location(rtv, &context_vk->c, rtv->resource->draw_binding); + else + wined3d_rendertarget_view_load_location(rtv, &context_vk->c, rtv->resource->draw_binding); invalidate_rt |= (1 << i); } else @@ -3393,9 +3398,17 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c if ((dsv = state->fb.depth_stencil)) { if (wined3d_state_uses_depth_buffer(state)) - wined3d_rendertarget_view_load_location(dsv, &context_vk->c, dsv->resource->draw_binding); + { + if (wined3d_rendertarget_view_get_locations(dsv) & WINED3D_LOCATION_CLEARED) + wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding); + else + wined3d_rendertarget_view_load_location(dsv, &context_vk->c, dsv->resource->draw_binding); + } else + { wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding); + } + if (!state->depth_stencil_state || state->depth_stencil_state->desc.depth_write) invalidate_ds = true;
@@ -3484,11 +3497,15 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c { i = wined3d_bit_scan(&invalidate_rt); rtv = state->fb.render_targets[i]; + wined3d_rendertarget_view_validate_location(rtv, rtv->resource->draw_binding); wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding); }
if (invalidate_ds) + { + wined3d_rendertarget_view_validate_location(dsv, dsv->resource->draw_binding); wined3d_rendertarget_view_invalidate_location(dsv, ~dsv->resource->draw_binding); + }
if (wined3d_context_vk_update_graphics_pipeline_key(context_vk, state, context_vk->graphics.vk_pipeline_layout, &null_buffer_binding) || !context_vk->graphics.vk_pipeline)
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Stefan Dösinger stefan@codeweavers.com
---
This is in the Vulkan codepath because GL lacks the renderpass clear functionality and delaying from an explicit d3d clear call to the next time the resource is used for something else isn't necessarily a performance win. Most likely we'd just break up a TARGET|DEPTH|STENCIL clear into 3 separate glClear invocations... --- dlls/wined3d/texture.c | 86 ++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 19 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index eaa7cdf3ea5..0fffb8fc4f2 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -805,6 +805,9 @@ BOOL wined3d_texture_load_location(struct wined3d_texture *texture,
/* FIXME: Clear textures on the GPU if possible. */
+ if (location != WINED3D_LOCATION_SYSMEM) + WARN_(d3d_perf)("Clearing texture %p in CPU.\n", texture); + if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM)) return FALSE; wined3d_texture_get_bo_address(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM); @@ -6407,13 +6410,13 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk { VkClearValue clear_values[WINED3D_MAX_RENDER_TARGETS + 1]; VkImageView views[WINED3D_MAX_RENDER_TARGETS + 1]; + unsigned int i, attachment_count, delay_count = 0; struct wined3d_rendertarget_view_vk *rtv_vk; struct wined3d_rendertarget_view *view; const struct wined3d_vk_info *vk_info; struct wined3d_device_vk *device_vk; VkCommandBuffer vk_command_buffer; VkRenderPassBeginInfo begin_desc; - unsigned int i, attachment_count; VkFramebufferCreateInfo fb_desc; VkFramebuffer vk_framebuffer; VkRenderPass vk_render_pass; @@ -6439,10 +6442,25 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk if (!(view = fb->render_targets[i])) continue;
- if (!is_full_clear(view, draw_rect, clear_rects)) - wined3d_rendertarget_view_load_location(view, &context_vk->c, view->resource->draw_binding); + 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 + { + FIXME("non-zero clear\n"); + wined3d_rendertarget_view_prepare_location(view, &context_vk->c, view->resource->draw_binding); + } + } else - wined3d_rendertarget_view_prepare_location(view, &context_vk->c, view->resource->draw_binding); + { + wined3d_rendertarget_view_load_location(view, &context_vk->c, view->resource->draw_binding); + } wined3d_rendertarget_view_validate_location(view, view->resource->draw_binding); wined3d_rendertarget_view_invalidate_location(view, ~view->resource->draw_binding);
@@ -6472,31 +6490,60 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk ++attachment_count; }
+ if (!attachment_count) + flags &= ~WINED3DCLEAR_TARGET; + if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && (view = fb->depth_stencil)) { - if (!is_full_clear(view, draw_rect, clear_rects)) + DWORD full_flags = 0; + + /* Vulkan can clear only depth or stencil, but at the moment we can't put the depth and + * stencil parts in separate locations. It isn't easy to do either, as such a half-cleared + * texture would need to be handled not just as a DS target but also when used as a shader + * resource or accessed on sysmem. */ + if (view->format->depth_size) + full_flags = WINED3DCLEAR_ZBUFFER; + 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) + { wined3d_rendertarget_view_load_location(view, &context_vk->c, view->resource->draw_binding); - else - wined3d_rendertarget_view_prepare_location(view, &context_vk->c, view->resource->draw_binding); - wined3d_rendertarget_view_validate_location(view, view->resource->draw_binding); - wined3d_rendertarget_view_invalidate_location(view, ~view->resource->draw_binding); + wined3d_rendertarget_view_validate_location(view, view->resource->draw_binding); + wined3d_rendertarget_view_invalidate_location(view, ~view->resource->draw_binding);
- 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); + 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; + clear_values[attachment_count].depthStencil.depth = depth; + clear_values[attachment_count].depthStencil.stencil = stencil;
- if (view->layer_count > layer_count) - layer_count = view->layer_count; + if (view->layer_count > layer_count) + layer_count = view->layer_count;
- depth_stencil = true; - ++attachment_count; + depth_stencil = true; + ++attachment_count; + } + else + { + wined3d_rendertarget_view_validate_location(view, WINED3D_LOCATION_CLEARED); + wined3d_rendertarget_view_invalidate_location(view, ~WINED3D_LOCATION_CLEARED); + flags &= ~(WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL); + delay_count++; + } }
if (!attachment_count) + { + TRACE("The clear has been delayed until draw time.\n"); return; + } + + TRACE("Doing an immediate clear of %u attachments.\n", attachment_count); + if (delay_count) + WARN_(d3d_perf)("Partial clear: %u immediate, %u delayed.\n", attachment_count, delay_count);
if (!(vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, fb, rt_count, flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL), flags))) @@ -6650,6 +6697,7 @@ static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_dev } else { + ERR("subrect clear\n"); for (i = 0; i < rt_count; ++i) { if (!(view = fb->render_targets[i])) @@ -6681,7 +6729,7 @@ static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_dev return; }
- TRACE("Forwarding to blitter %p.\n", next); + ERR("Forwarding to blitter %p.\n", next); next->ops->blitter_clear(next, device, next_rt_count, fb, rect_count, clear_rects, draw_rect, next_flags, colour, depth, stencil); }
On Sun, 24 Apr 2022 at 18:25, Stefan Dösinger stefan@codeweavers.com wrote:
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index eaa7cdf3ea5..0fffb8fc4f2 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -805,6 +805,9 @@ BOOL wined3d_texture_load_location(struct wined3d_texture *texture,
/* FIXME: Clear textures on the GPU if possible. */
if (location != WINED3D_LOCATION_SYSMEM)
WARN_(d3d_perf)("Clearing texture %p in CPU.\n", texture);
if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM)) return FALSE; wined3d_texture_get_bo_address(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM);
That conflicts with the series by Zeb.
@@ -6472,31 +6490,60 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
[...]
- TRACE("Doing an immediate clear of %u attachments.\n", attachment_count);
- if (delay_count)
WARN_(d3d_perf)("Partial clear: %u immediate, %u delayed.\n", attachment_count, delay_count);
I suppose using +d3d_perf for this is fine, but this seems more like a TRACE than a WARN.
@@ -6650,6 +6697,7 @@ static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_dev } else {
ERR("subrect clear\n"); for (i = 0; i < rt_count; ++i) { if (!(view = fb->render_targets[i]))
@@ -6681,7 +6729,7 @@ static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_dev return; }
- TRACE("Forwarding to blitter %p.\n", next);
- ERR("Forwarding to blitter %p.\n", next);
Is that leftover debug code?
Am Montag, 25. April 2022, 19:22:47 EAT schrieb Henri Verbeet:
wined3d_texture_get_bo_address(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM);
That conflicts with the series by Zeb.
Yes, and having Zeb's code in before this patch is a good idea anyway, just to avoid handling the delayed clear in CPU by accident. I'll resend this later.
- TRACE("Forwarding to blitter %p.\n", next);
- ERR("Forwarding to blitter %p.\n", next);
Is that leftover debug code?
Yes it is. I even removed it before sending, but then I sent the old format- patched version :-/