Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- dlls/wined3d/context_vk.c | 194 ++++++++++++++++++++++ dlls/wined3d/texture.c | 294 ++++++++++++++++++++++++++++++++- dlls/wined3d/view.c | 2 +- dlls/wined3d/wined3d_private.h | 49 +++++- 4 files changed, 531 insertions(+), 8 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index f5a321b076c..f4a52fb9c2f 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -296,6 +296,31 @@ static struct wined3d_retired_object_vk *wined3d_context_vk_get_retired_object_v return &retired->objects[retired->count++]; }
+void wined3d_context_vk_destroy_framebuffer(struct wined3d_context_vk *context_vk, + VkFramebuffer vk_framebuffer, uint64_t command_buffer_id) +{ + 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_retired_object_vk *o; + + if (context_vk->completed_command_buffer_id > command_buffer_id) + { + VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, vk_framebuffer, NULL)); + TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer)); + return; + } + + if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk))) + { + ERR("Leaking framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer)); + return; + } + + o->type = WINED3D_RETIRED_FRAMEBUFFER_VK; + o->u.vk_framebuffer = vk_framebuffer; + o->command_buffer_id = command_buffer_id; +} + void wined3d_context_vk_destroy_memory(struct wined3d_context_vk *context_vk, VkDeviceMemory vk_memory, uint64_t command_buffer_id) { @@ -538,6 +563,11 @@ static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *cont /* Nothing to do. */ break;
+ case WINED3D_RETIRED_FRAMEBUFFER_VK: + VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, o->u.vk_framebuffer, NULL)); + TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_framebuffer)); + break; + case WINED3D_RETIRED_MEMORY_VK: VK_CALL(vkFreeMemory(device_vk->vk_device, o->u.vk_memory, NULL)); TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(o->u.vk_memory)); @@ -599,6 +629,158 @@ static void wined3d_context_vk_destroy_bo_slab(struct wine_rb_entry *entry, void } }
+static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *key, + const struct wined3d_fb_state *fb, unsigned int rt_count) +{ + struct wined3d_render_pass_attachment_vk *a; + struct wined3d_rendertarget_view *view; + unsigned int i; + + memset(key, 0, sizeof(*key)); + + for (i = 0; i < rt_count; ++i) + { + if (!(view = fb->render_targets[i]) || view->format->id == WINED3DFMT_NULL) + continue; + + a = &key->rt[i]; + 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; + key->rt_mask |= 1u << i; + } +} + +static void wined3d_render_pass_vk_cleanup(struct wined3d_render_pass_vk *pass, + struct wined3d_context_vk *context_vk) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + + VK_CALL(vkDestroyRenderPass(device_vk->vk_device, pass->vk_render_pass, NULL)); +} + +static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass, + struct wined3d_context_vk *context_vk, const struct wined3d_render_pass_key_vk *key) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + VkAttachmentReference attachment_references[WINED3D_MAX_RENDER_TARGETS]; + VkAttachmentDescription attachments[WINED3D_MAX_RENDER_TARGETS + 1]; + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + const struct wined3d_render_pass_attachment_vk *a; + unsigned int attachment_count, rt_count, i; + VkAttachmentDescription *attachment; + VkSubpassDescription sub_pass_desc; + VkRenderPassCreateInfo pass_desc; + uint32_t mask; + VkResult vr; + + rt_count = 0; + attachment_count = 0; + mask = key->rt_mask & ((1u << WINED3D_MAX_RENDER_TARGETS) - 1); + while (mask) + { + i = wined3d_bit_scan(&mask); + a = &key->rt[i]; + + attachment = &attachments[attachment_count]; + attachment->flags = 0; + attachment->format = a->vk_format; + attachment->samples = a->vk_samples; + attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachment->initialLayout = a->vk_layout; + attachment->finalLayout = a->vk_layout; + + attachment_references[i].attachment = attachment_count; + attachment_references[i].layout = a->vk_layout; + + ++attachment_count; + rt_count = i + 1; + } + + mask = ~key->rt_mask & ((1u << rt_count) - 1); + while (mask) + { + i = wined3d_bit_scan(&mask); + attachment_references[i].attachment = VK_ATTACHMENT_UNUSED; + attachment_references[i].layout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + sub_pass_desc.flags = 0; + sub_pass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + sub_pass_desc.inputAttachmentCount = 0; + sub_pass_desc.pInputAttachments = NULL; + sub_pass_desc.colorAttachmentCount = rt_count; + sub_pass_desc.pColorAttachments = attachment_references; + sub_pass_desc.pResolveAttachments = NULL; + sub_pass_desc.pDepthStencilAttachment = NULL; + sub_pass_desc.preserveAttachmentCount = 0; + sub_pass_desc.pPreserveAttachments = NULL; + + pass_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + pass_desc.pNext = NULL; + pass_desc.flags = 0; + pass_desc.attachmentCount = attachment_count; + pass_desc.pAttachments = attachments; + pass_desc.subpassCount = 1; + pass_desc.pSubpasses = &sub_pass_desc; + pass_desc.dependencyCount = 0; + pass_desc.pDependencies = NULL; + + pass->key = *key; + if ((vr = VK_CALL(vkCreateRenderPass(device_vk->vk_device, + &pass_desc, NULL, &pass->vk_render_pass))) < 0) + { + WARN("Failed to create Vulkan render pass, vr %d.\n", vr); + return false; + } + + return true; +} + +VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *context_vk, + const struct wined3d_fb_state *fb, unsigned int rt_count) +{ + struct wined3d_render_pass_key_vk key; + struct wined3d_render_pass_vk *pass; + struct wine_rb_entry *entry; + + wined3d_render_pass_key_vk_init(&key, fb, rt_count); + if ((entry = wine_rb_get(&context_vk->render_passes, &key))) + return WINE_RB_ENTRY_VALUE(entry, struct wined3d_render_pass_vk, entry)->vk_render_pass; + + if (!(pass = heap_alloc(sizeof(*pass)))) + return VK_NULL_HANDLE; + + if (!wined3d_render_pass_vk_init(pass, context_vk, &key)) + { + heap_free(pass); + return VK_NULL_HANDLE; + } + + if (wine_rb_put(&context_vk->render_passes, &pass->key, &pass->entry) == -1) + { + ERR("Failed to insert render pass.\n"); + wined3d_render_pass_vk_cleanup(pass, context_vk); + heap_free(pass); + return VK_NULL_HANDLE; + } + + return pass->vk_render_pass; +} + +static void wined3d_context_vk_destroy_render_pass(struct wine_rb_entry *entry, void *ctx) +{ + struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry, + struct wined3d_render_pass_vk, entry); + + wined3d_render_pass_vk_cleanup(pass, ctx); + heap_free(pass); +} + void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk) { struct wined3d_command_buffer_vk *buffer = &context_vk->current_command_buffer; @@ -620,6 +802,8 @@ void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk) heap_free(context_vk->submitted.buffers); heap_free(context_vk->retired.objects);
+ wine_rb_destroy(&context_vk->render_passes, wined3d_context_vk_destroy_render_pass, context_vk); + wined3d_context_cleanup(&context_vk->c); }
@@ -784,6 +968,15 @@ void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk, VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, src_stage_mask, dst_stage_mask, 0, 0, NULL, 0, NULL, 1, &barrier)); }
+static int wined3d_render_pass_vk_compare(const void *key, const struct wine_rb_entry *entry) +{ + const struct wined3d_render_pass_key_vk *k = key; + const struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry, + const struct wined3d_render_pass_vk, entry); + + return memcmp(k, &pass->key, sizeof(*k)); +} + static int wined3d_bo_slab_vk_compare(const void *key, const struct wine_rb_entry *entry) { const struct wined3d_bo_slab_vk *slab = WINE_RB_ENTRY_VALUE(entry, const struct wined3d_bo_slab_vk, entry); @@ -824,6 +1017,7 @@ HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wi } context_vk->current_command_buffer.id = 1;
+ wine_rb_init(&context_vk->render_passes, wined3d_render_pass_vk_compare); wine_rb_init(&context_vk->bo_slab_available, wined3d_bo_slab_vk_compare);
return WINED3D_OK; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 0e39ad55a8c..ef5f3cd48e5 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -4484,6 +4484,57 @@ HRESULT wined3d_texture_no3d_init(struct wined3d_texture *texture_no3d, struct w flags, device, parent, parent_ops, &texture_no3d[1], &wined3d_texture_no3d_ops); }
+const VkDescriptorImageInfo *wined3d_texture_vk_get_default_image_info(struct wined3d_texture_vk *texture_vk, + struct wined3d_context_vk *context_vk) +{ + const struct wined3d_format_vk *format_vk; + const struct wined3d_vk_info *vk_info; + struct wined3d_device_vk *device_vk; + VkImageViewCreateInfo create_info; + uint32_t flags = 0; + VkResult vr; + + if (texture_vk->default_image_info.imageView) + return &texture_vk->default_image_info; + + format_vk = wined3d_format_vk(texture_vk->t.resource.format); + device_vk = wined3d_device_vk(texture_vk->t.resource.device); + vk_info = context_vk->vk_info; + + if (texture_vk->t.layer_count > 1) + flags |= WINED3D_VIEW_TEXTURE_ARRAY; + + wined3d_texture_vk_prepare_texture(texture_vk, context_vk); + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + create_info.pNext = NULL; + create_info.flags = 0; + create_info.image = texture_vk->vk_image; + create_info.viewType = vk_image_view_type_from_wined3d(texture_vk->t.resource.type, flags); + create_info.format = format_vk->vk_format; + create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.subresourceRange.aspectMask = vk_aspect_mask_from_format(&format_vk->f); + create_info.subresourceRange.baseMipLevel = 0; + create_info.subresourceRange.levelCount = texture_vk->t.level_count; + create_info.subresourceRange.baseArrayLayer = 0; + create_info.subresourceRange.layerCount = texture_vk->t.layer_count; + if ((vr = VK_CALL(vkCreateImageView(device_vk->vk_device, &create_info, + NULL, &texture_vk->default_image_info.imageView))) < 0) + { + ERR("Failed to create Vulkan image view, vr %s.\n", wined3d_debug_vkresult(vr)); + return NULL; + } + + TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(texture_vk->default_image_info.imageView)); + + texture_vk->default_image_info.sampler = VK_NULL_HANDLE; + texture_vk->default_image_info.imageLayout = texture_vk->layout; + + return &texture_vk->default_image_info; +} + static void wined3d_texture_vk_upload_data(struct wined3d_context *context, const struct wined3d_const_bo_address *src_bo_addr, const struct wined3d_format *src_format, const struct wined3d_box *src_box, unsigned int src_row_pitch, unsigned int src_slice_pitch, @@ -5042,6 +5093,13 @@ static void wined3d_texture_vk_unload_location(struct wined3d_texture *texture, switch (location) { case WINED3D_LOCATION_TEXTURE_RGB: + if (texture_vk->default_image_info.imageView) + { + wined3d_context_vk_destroy_image_view(context_vk, + texture_vk->default_image_info.imageView, texture_vk->command_buffer_id); + texture_vk->default_image_info.imageView = VK_NULL_HANDLE; + } + if (texture_vk->vk_image) { wined3d_context_vk_destroy_image(context_vk, texture_vk->vk_image, texture_vk->command_buffer_id); @@ -5419,7 +5477,7 @@ static void ffp_blitter_clear_rendertargets(struct wined3d_device *device, unsig context_release(context); }
-static bool ffp_blitter_use_cpu_clear(struct wined3d_rendertarget_view *view) +static bool blitter_use_cpu_clear(struct wined3d_rendertarget_view *view) { struct wined3d_resource *resource; struct wined3d_texture *texture; @@ -5458,7 +5516,7 @@ static void ffp_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de if (!(view = fb->render_targets[i])) continue;
- if (ffp_blitter_use_cpu_clear(view) + if (blitter_use_cpu_clear(view) || (!(view->resource->bind_flags & WINED3D_BIND_RENDER_TARGET) && (wined3d_settings.offscreen_rendering_mode != ORM_FBO || !(view->format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE)))) @@ -5478,7 +5536,7 @@ static void ffp_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de if ((flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) && (view = fb->depth_stencil) && (!view->format->depth_size || (flags & WINED3DCLEAR_ZBUFFER)) && (!view->format->stencil_size || (flags & WINED3DCLEAR_STENCIL)) - && ffp_blitter_use_cpu_clear(view)) + && blitter_use_cpu_clear(view)) { next_flags |= flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL); flags &= ~(WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL); @@ -5978,17 +6036,243 @@ static void vk_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_c heap_free(blitter); }
+static inline VkImageView wined3d_rendertarget_view_vk_get_image_view(struct wined3d_rendertarget_view_vk *rtv_vk, + struct wined3d_context_vk *context_vk) +{ + struct wined3d_texture_vk *texture_vk; + + if (rtv_vk->vk_image_view) + return rtv_vk->vk_image_view; + + texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(rtv_vk->v.resource)); + return wined3d_texture_vk_get_default_image_info(texture_vk, context_vk)->imageView; +} + +static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk, unsigned int rt_count, + const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects, const RECT *draw_rect, + uint32_t flags, const struct wined3d_color *colour, float depth, unsigned int stencil) +{ + VkClearValue clear_values[WINED3D_MAX_RENDER_TARGETS]; + VkImageView views[WINED3D_MAX_RENDER_TARGETS]; + struct wined3d_rendertarget_view_vk *rtv_vk; + struct wined3d_rendertarget_view *view; + const struct wined3d_vk_info *vk_info; + struct wined3d_texture_vk *texture_vk; + 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; + unsigned int layer_count; + VkClearColorValue *c; + VkResult vr; + RECT r; + + TRACE("context_vk %p, rt_count %u, fb %p, rect_count %u, clear_rects %p, " + "draw_rect %s, flags %#x, colour %s, depth %.8e, stencil %#x.\n", + context_vk, rt_count, fb, rect_count, clear_rects, + wine_dbgstr_rect(draw_rect), flags, debug_color(colour), depth, stencil); + + device_vk = wined3d_device_vk(context_vk->c.device); + vk_info = context_vk->vk_info; + + for (i = 0, attachment_count = 0, layer_count = 1; i < rt_count; ++i) + { + 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); + 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); + + rtv_vk = wined3d_rendertarget_view_vk(view); + views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk); + + 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; + } + + if (view->layer_count > layer_count) + layer_count = view->layer_count; + + ++attachment_count; + } + + if (!(vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, fb, rt_count))) + { + ERR("Failed to get render pass.\n"); + return; + } + + if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk))) + { + ERR("Failed to get command buffer.\n"); + return; + } + + fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fb_desc.pNext = NULL; + fb_desc.flags = 0; + fb_desc.renderPass = vk_render_pass; + fb_desc.attachmentCount = attachment_count; + fb_desc.pAttachments = views; + fb_desc.width = draw_rect->right - draw_rect->left; + fb_desc.height = draw_rect->bottom - draw_rect->top; + fb_desc.layers = layer_count; + if ((vr = VK_CALL(vkCreateFramebuffer(device_vk->vk_device, &fb_desc, NULL, &vk_framebuffer))) < 0) + { + ERR("Failed to create Vulkan framebuffer, vr %s.\n", wined3d_debug_vkresult(vr)); + return; + } + + begin_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + begin_desc.pNext = NULL; + begin_desc.renderPass = vk_render_pass; + begin_desc.framebuffer = vk_framebuffer; + begin_desc.clearValueCount = attachment_count; + begin_desc.pClearValues = clear_values; + + for (i = 0; i < rect_count; ++i) + { + r.left = max(clear_rects[i].left, draw_rect->left); + r.top = max(clear_rects[i].top, draw_rect->top); + r.right = min(clear_rects[i].right, draw_rect->right); + r.bottom = min(clear_rects[i].bottom, draw_rect->bottom); + + if (r.left >= r.right || r.top >= r.bottom) + continue; + + begin_desc.renderArea.offset.x = r.left; + begin_desc.renderArea.offset.y = r.top; + begin_desc.renderArea.extent.width = r.right - r.left; + begin_desc.renderArea.extent.height = r.bottom - r.top; + VK_CALL(vkCmdBeginRenderPass(vk_command_buffer, &begin_desc, VK_SUBPASS_CONTENTS_INLINE)); + VK_CALL(vkCmdEndRenderPass(vk_command_buffer)); + } + + wined3d_context_vk_destroy_framebuffer(context_vk, vk_framebuffer, context_vk->current_command_buffer.id); + + for (i = 0; i < rt_count; ++i) + { + if (!(view = fb->render_targets[i])) + continue; + + wined3d_context_vk_reference_rendertarget_view(context_vk, wined3d_rendertarget_view_vk(view)); + texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(view->resource)); + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags), + texture_vk->layout, texture_vk->layout, + texture_vk->vk_image, VK_IMAGE_ASPECT_COLOR_BIT); + } +} + static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_device *device, unsigned int rt_count, const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects, const RECT *draw_rect, DWORD flags, const struct wined3d_color *colour, float depth, DWORD stencil) { + struct wined3d_device_vk *device_vk = wined3d_device_vk(device); + struct wined3d_rendertarget_view *view, *previous = NULL; + struct wined3d_context_vk *context_vk; + bool have_identical_size = true; + struct wined3d_fb_state tmp_fb; + unsigned int next_rt_count = 0; struct wined3d_blitter *next; + uint32_t next_flags = 0; + unsigned int i;
TRACE("blitter %p, device %p, rt_count %u, fb %p, rect_count %u, clear_rects %p, " "draw_rect %s, flags %#x, colour %s, depth %.8e, stencil %#x.\n", blitter, device, rt_count, fb, rect_count, clear_rects, wine_dbgstr_rect(draw_rect), flags, debug_color(colour), depth, stencil);
+ if (!rect_count) + { + rect_count = 1; + clear_rects = draw_rect; + } + + if (flags & WINED3DCLEAR_TARGET) + { + for (i = 0; i < rt_count; ++i) + { + if (!(view = fb->render_targets[i])) + continue; + + if (blitter_use_cpu_clear(view)) + { + next_flags |= WINED3DCLEAR_TARGET; + flags &= ~WINED3DCLEAR_TARGET; + next_rt_count = rt_count; + rt_count = 0; + break; + } + } + } + + if ((flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) && fb->depth_stencil) + { + next_flags |= flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL); + flags &= ~(WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL); + } + + if (flags) + { + context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0)); + + for (i = 0; i < rt_count; ++i) + { + if (!(view = fb->render_targets[i])) + continue; + + if (previous && (previous->width != view->width || previous->height != view->height)) + have_identical_size = false; + previous = view; + } + + if (have_identical_size) + { + vk_blitter_clear_rendertargets(context_vk, rt_count, fb, rect_count, + clear_rects, draw_rect, flags, colour, depth, stencil); + } + else + { + for (i = 0; i < rt_count; ++i) + { + if (!(view = fb->render_targets[i])) + continue; + + tmp_fb.render_targets[0] = view; + tmp_fb.depth_stencil = NULL; + vk_blitter_clear_rendertargets(context_vk, 1, &tmp_fb, rect_count, + clear_rects, draw_rect, WINED3DCLEAR_TARGET, colour, depth, stencil); + } + } + + context_release(&context_vk->c); + } + + if (!next_flags) + return; + if (!(next = blitter->next)) { ERR("No blitter to handle clear.\n"); @@ -5996,8 +6280,8 @@ static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_dev }
TRACE("Forwarding to blitter %p.\n", next); - next->ops->blitter_clear(next, device, rt_count, fb, rect_count, - clear_rects, draw_rect, flags, colour, depth, stencil); + next->ops->blitter_clear(next, device, next_rt_count, fb, rect_count, + clear_rects, draw_rect, next_flags, colour, depth, stencil); }
static bool vk_blitter_blit_supported(enum wined3d_blit_op op, const struct wined3d_context *context, diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 438d9a8b18f..fee64bd47d2 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -621,7 +621,7 @@ HRESULT wined3d_rendertarget_view_gl_init(struct wined3d_rendertarget_view_gl *v return hr; }
-static VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type, uint32_t flags) +VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type, uint32_t flags) { switch (type) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 43bdb26c936..dd8e03d35d9 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -300,6 +300,7 @@ extern const GLenum magLookup[WINED3D_TEXF_LINEAR + 1] DECLSPEC_HIDDEN;
GLenum wined3d_gl_compare_func(enum wined3d_cmp_func f) DECLSPEC_HIDDEN; VkAccessFlags vk_access_mask_from_bind_flags(uint32_t bind_flags) DECLSPEC_HIDDEN; +VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type, uint32_t flags) DECLSPEC_HIDDEN;
static inline enum wined3d_cmp_func wined3d_sanitize_cmp_func(enum wined3d_cmp_func func) { @@ -2223,6 +2224,7 @@ struct wined3d_command_buffer_vk enum wined3d_retired_object_type_vk { WINED3D_RETIRED_FREE_VK, + WINED3D_RETIRED_FRAMEBUFFER_VK, WINED3D_RETIRED_MEMORY_VK, WINED3D_RETIRED_ALLOCATOR_BLOCK_VK, WINED3D_RETIRED_BO_SLAB_SLICE_VK, @@ -2237,6 +2239,7 @@ struct wined3d_retired_object_vk union { struct wined3d_retired_object_vk *next; + VkFramebuffer vk_framebuffer; VkDeviceMemory vk_memory; struct wined3d_allocator_block *block; struct @@ -2259,6 +2262,26 @@ struct wined3d_retired_objects_vk SIZE_T count; };
+struct wined3d_render_pass_attachment_vk +{ + VkFormat vk_format; + VkSampleCountFlagBits vk_samples; + VkImageLayout vk_layout; +}; + +struct wined3d_render_pass_key_vk +{ + struct wined3d_render_pass_attachment_vk rt[WINED3D_MAX_RENDER_TARGETS]; + uint32_t rt_mask; +}; + +struct wined3d_render_pass_vk +{ + struct wine_rb_entry entry; + struct wined3d_render_pass_key_vk key; + VkRenderPass vk_render_pass; +}; + struct wined3d_context_vk { struct wined3d_context c; @@ -2277,6 +2300,7 @@ struct wined3d_context_vk } submitted;
struct wined3d_retired_objects_vk retired; + struct wine_rb_tree render_passes; struct wine_rb_tree bo_slab_available; };
@@ -2296,6 +2320,8 @@ void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *conte struct wined3d_allocator_block *block, uint64_t command_buffer_id) DECLSPEC_HIDDEN; void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo) DECLSPEC_HIDDEN; +void wined3d_context_vk_destroy_framebuffer(struct wined3d_context_vk *context_vk, + VkFramebuffer vk_framebuffer, uint64_t command_buffer_id) DECLSPEC_HIDDEN; void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk, VkImage vk_image, uint64_t command_buffer_id) DECLSPEC_HIDDEN; void wined3d_context_vk_destroy_image_view(struct wined3d_context_vk *context_vk, @@ -2303,6 +2329,8 @@ void wined3d_context_vk_destroy_image_view(struct wined3d_context_vk *context_vk void wined3d_context_vk_destroy_memory(struct wined3d_context_vk *context_vk, VkDeviceMemory vk_memory, uint64_t command_buffer_id) DECLSPEC_HIDDEN; VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; +VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *context_vk, + const struct wined3d_fb_state *fb, unsigned int rt_count) DECLSPEC_HIDDEN; void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk, VkCommandBuffer vk_command_buffer, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, VkImageLayout old_layout, @@ -3996,6 +4024,8 @@ struct wined3d_texture_vk VkDeviceMemory vk_memory; enum VkImageLayout layout; uint64_t command_buffer_id; + + VkDescriptorImageInfo default_image_info; };
static inline struct wined3d_texture_vk *wined3d_texture_vk(struct wined3d_texture *texture) @@ -4003,6 +4033,8 @@ static inline struct wined3d_texture_vk *wined3d_texture_vk(struct wined3d_textu return CONTAINING_RECORD(texture, struct wined3d_texture_vk, t); }
+const VkDescriptorImageInfo *wined3d_texture_vk_get_default_image_info(struct wined3d_texture_vk *texture_vk, + struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; HRESULT wined3d_texture_vk_init(struct wined3d_texture_vk *texture_vk, struct wined3d_device *device, const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count, uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; @@ -5490,17 +5522,30 @@ static inline void wined3d_context_copy_bo_address(struct wined3d_context *conte context->device->adapter->adapter_ops->adapter_copy_bo_address(context, dst, src, size); }
-static inline void wined3d_context_vk_reference_bo(struct wined3d_context_vk *context_vk, struct wined3d_bo_vk *bo) +static inline void wined3d_context_vk_reference_bo(const struct wined3d_context_vk *context_vk, + struct wined3d_bo_vk *bo) { bo->command_buffer_id = context_vk->current_command_buffer.id; }
-static inline void wined3d_context_vk_reference_texture(struct wined3d_context_vk *context_vk, +static inline void wined3d_context_vk_reference_texture(const struct wined3d_context_vk *context_vk, struct wined3d_texture_vk *texture_vk) { texture_vk->command_buffer_id = context_vk->current_command_buffer.id; }
+static inline void wined3d_context_vk_reference_rendertarget_view(const struct wined3d_context_vk *context_vk, + struct wined3d_rendertarget_view_vk *rtv_vk) +{ + struct wined3d_resource *resource = rtv_vk->v.resource; + + if (resource->type == WINED3D_RTYPE_BUFFER) + wined3d_context_vk_reference_bo(context_vk, &wined3d_buffer_vk(buffer_from_resource(resource))->bo); + else + wined3d_context_vk_reference_texture(context_vk, wined3d_texture_vk(texture_from_resource(resource))); + rtv_vk->command_buffer_id = context_vk->current_command_buffer.id; +} + static inline BOOL wined3d_dsv_srv_conflict(const struct wined3d_rendertarget_view *dsv, const struct wined3d_format *srv_format) {