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,