Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- dlls/wined3d/context_vk.c | 36 +++++++- dlls/wined3d/texture.c | 160 ++++++++++++++++++++++++++++++++- dlls/wined3d/wined3d_private.h | 15 ++++ 3 files changed, 205 insertions(+), 6 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index b3239a4f9ee..35a0c655ef3 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -86,7 +86,7 @@ VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_cont return vk_memory; }
-static struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk, +struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk, unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory) { struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); @@ -198,7 +198,7 @@ static struct wined3d_retired_object_vk *wined3d_context_vk_get_retired_object_v return &retired->objects[retired->count++]; }
-static void wined3d_context_vk_destroy_memory(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) { struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); @@ -223,7 +223,7 @@ static void wined3d_context_vk_destroy_memory(struct wined3d_context_vk *context o->command_buffer_id = command_buffer_id; }
-static void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *context_vk, +void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *context_vk, struct wined3d_allocator_block *block, uint64_t command_buffer_id) { struct wined3d_retired_object_vk *o; @@ -271,6 +271,31 @@ static void wined3d_context_vk_destroy_buffer(struct wined3d_context_vk *context o->command_buffer_id = command_buffer_id; }
+void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk, + VkImage vk_image, 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(vkDestroyImage(device_vk->vk_device, vk_image, NULL)); + TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(vk_image)); + return; + } + + if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk))) + { + ERR("Leaking image 0x%s.\n", wine_dbgstr_longlong(vk_image)); + return; + } + + o->type = WINED3D_RETIRED_IMAGE_VK; + o->u.vk_image = vk_image; + o->command_buffer_id = command_buffer_id; +} + void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo) { TRACE("context_vk %p, bo %p.\n", context_vk, bo); @@ -345,6 +370,11 @@ static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *cont TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer)); break;
+ case WINED3D_RETIRED_IMAGE_VK: + VK_CALL(vkDestroyImage(device_vk->vk_device, o->u.vk_image, NULL)); + TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image)); + break; + default: ERR("Unhandled object type %#x.\n", o->type); break; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 85f09ee3489..66cee442ff9 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -4230,6 +4230,129 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, FIXME("Not implemented.\n"); }
+static BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *texture_vk, + struct wined3d_context_vk *context_vk) +{ + const struct wined3d_format_vk *format_vk; + VkMemoryRequirements memory_requirements; + const struct wined3d_vk_info *vk_info; + struct wined3d_adapter_vk *adapter_vk; + struct wined3d_device_vk *device_vk; + struct wined3d_resource *resource; + VkImageCreateInfo create_info; + unsigned int memory_type_idx; + VkResult vr; + + if (texture_vk->t.flags & WINED3D_TEXTURE_RGB_ALLOCATED) + return TRUE; + + resource = &texture_vk->t.resource; + device_vk = wined3d_device_vk(resource->device); + adapter_vk = wined3d_adapter_vk(device_vk->d.adapter); + format_vk = wined3d_format_vk(resource->format); + vk_info = context_vk->vk_info; + + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + create_info.pNext = NULL; + + create_info.flags = 0; + if (wined3d_format_is_typeless(&format_vk->f)) + create_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + + switch (resource->type) + { + case WINED3D_RTYPE_TEXTURE_1D: + create_info.imageType = VK_IMAGE_TYPE_1D; + break; + case WINED3D_RTYPE_TEXTURE_2D: + create_info.imageType = VK_IMAGE_TYPE_2D; + if (texture_vk->t.layer_count >= 6 && resource->width == resource->height) + create_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + break; + case WINED3D_RTYPE_TEXTURE_3D: + create_info.imageType = VK_IMAGE_TYPE_3D; + if (resource->bind_flags & (WINED3D_BIND_RENDER_TARGET | WINED3D_BIND_UNORDERED_ACCESS)) + create_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; + break; + default: + ERR("Invalid resource type %s.\n", debug_d3dresourcetype(resource->type)); + create_info.imageType = VK_IMAGE_TYPE_2D; + break; + } + + create_info.format = format_vk->vk_format; + create_info.extent.width = resource->width; + create_info.extent.height = resource->height; + create_info.extent.depth = resource->depth; + create_info.mipLevels = texture_vk->t.level_count; + create_info.arrayLayers = texture_vk->t.layer_count; + create_info.samples = max(1, wined3d_resource_get_sample_count(resource)); + create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + + create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + if (resource->bind_flags & WINED3D_BIND_SHADER_RESOURCE) + create_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT; + if (resource->bind_flags & WINED3D_BIND_RENDER_TARGET) + create_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + if (resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL) + create_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + if (resource->bind_flags & WINED3D_BIND_UNORDERED_ACCESS) + create_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT; + + create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + create_info.queueFamilyIndexCount = 0; + create_info.pQueueFamilyIndices = NULL; + create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + if ((vr = VK_CALL(vkCreateImage(device_vk->vk_device, &create_info, NULL, &texture_vk->vk_image))) < 0) + { + ERR("Failed to create Vulkan image, vr %s.\n", wined3d_debug_vkresult(vr)); + return FALSE; + } + + VK_CALL(vkGetImageMemoryRequirements(device_vk->vk_device, texture_vk->vk_image, &memory_requirements)); + + memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk, + memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + if (memory_type_idx == ~0u) + { + ERR("Failed to find suitable memory type.\n"); + VK_CALL(vkDestroyImage(device_vk->vk_device, texture_vk->vk_image, NULL)); + texture_vk->vk_image = VK_NULL_HANDLE; + return FALSE; + } + + texture_vk->memory = wined3d_context_vk_allocate_memory(context_vk, + memory_type_idx, memory_requirements.size, &texture_vk->vk_memory); + if (!texture_vk->vk_memory) + { + ERR("Failed to allocate image memory.\n"); + VK_CALL(vkDestroyImage(device_vk->vk_device, texture_vk->vk_image, NULL)); + texture_vk->vk_image = VK_NULL_HANDLE; + return FALSE; + } + + if ((vr = VK_CALL(vkBindImageMemory(device_vk->vk_device, texture_vk->vk_image, + texture_vk->vk_memory, texture_vk->memory ? texture_vk->memory->offset : 0))) < 0) + { + WARN("Failed to bind memory, vr %s.\n", wined3d_debug_vkresult(vr)); + if (texture_vk->memory) + wined3d_allocator_block_free(texture_vk->memory); + else + VK_CALL(vkFreeMemory(device_vk->vk_device, texture_vk->vk_memory, NULL)); + texture_vk->vk_memory = VK_NULL_HANDLE; + VK_CALL(vkDestroyImage(device_vk->vk_device, texture_vk->vk_image, NULL)); + texture_vk->vk_image = VK_NULL_HANDLE; + return FALSE; + } + + texture_vk->t.flags |= WINED3D_TEXTURE_RGB_ALLOCATED; + + TRACE("Created image 0x%s, memory 0x%s for texture %p.\n", + wine_dbgstr_longlong(texture_vk->vk_image), wine_dbgstr_longlong(texture_vk->vk_memory), texture_vk); + + return TRUE; +} + static BOOL wined3d_texture_vk_prepare_location(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context *context, unsigned int location) { @@ -4244,8 +4367,7 @@ static BOOL wined3d_texture_vk_prepare_location(struct wined3d_texture *texture, return TRUE;
case WINED3D_LOCATION_TEXTURE_RGB: - /* The Vulkan image is created during resource creation. */ - return TRUE; + return wined3d_texture_vk_prepare_texture(wined3d_texture_vk(texture), wined3d_context_vk(context));
default: FIXME("Unhandled location %s.\n", wined3d_debug_location(location)); @@ -4264,7 +4386,39 @@ static BOOL wined3d_texture_vk_load_location(struct wined3d_texture *texture, static void wined3d_texture_vk_unload_location(struct wined3d_texture *texture, struct wined3d_context *context, unsigned int location) { - FIXME("texture %p, context %p, location %s.\n", texture, context, wined3d_debug_location(location)); + struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture); + struct wined3d_context_vk *context_vk = wined3d_context_vk(context); + + TRACE("texture %p, context %p, location %s.\n", texture, context, wined3d_debug_location(location)); + + switch (location) + { + case WINED3D_LOCATION_TEXTURE_RGB: + if (texture_vk->vk_image) + { + wined3d_context_vk_destroy_image(context_vk, texture_vk->vk_image, texture_vk->command_buffer_id); + texture_vk->vk_image = VK_NULL_HANDLE; + if (texture_vk->memory) + wined3d_context_vk_destroy_allocator_block(context_vk, + texture_vk->memory, texture_vk->command_buffer_id); + else + wined3d_context_vk_destroy_memory(context_vk, + texture_vk->vk_memory, texture_vk->command_buffer_id); + texture_vk->vk_memory = VK_NULL_HANDLE; + texture_vk->memory = NULL; + } + break; + + case WINED3D_LOCATION_BUFFER: + case WINED3D_LOCATION_TEXTURE_SRGB: + case WINED3D_LOCATION_RB_MULTISAMPLE: + case WINED3D_LOCATION_RB_RESOLVED: + break; + + default: + ERR("Unhandled location %s.\n", wined3d_debug_location(location)); + break; + } }
static const struct wined3d_texture_ops wined3d_texture_vk_ops = diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 7e78cb60df5..de07c5909aa 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2195,6 +2195,7 @@ enum wined3d_retired_object_type_vk WINED3D_RETIRED_MEMORY_VK, WINED3D_RETIRED_ALLOCATOR_BLOCK_VK, WINED3D_RETIRED_BUFFER_VK, + WINED3D_RETIRED_IMAGE_VK, };
struct wined3d_retired_object_vk @@ -2206,6 +2207,7 @@ struct wined3d_retired_object_vk VkDeviceMemory vk_memory; struct wined3d_allocator_block *block; VkBuffer vk_buffer; + VkImage vk_image; } u; uint64_t command_buffer_id; }; @@ -2243,13 +2245,21 @@ static inline struct wined3d_context_vk *wined3d_context_vk(struct wined3d_conte return CONTAINING_RECORD(context, struct wined3d_context_vk, c); }
+struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk, + unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory) DECLSPEC_HIDDEN; VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk, unsigned int pool, size_t size) DECLSPEC_HIDDEN; void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo) DECLSPEC_HIDDEN; +void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *context_vk, + 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_image(struct wined3d_context_vk *context_vk, + VkImage vk_image, uint64_t command_buffer_id) DECLSPEC_HIDDEN; +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; HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; @@ -3944,6 +3954,11 @@ void wined3d_texture_gl_set_compatible_renderbuffer(struct wined3d_texture_gl *t struct wined3d_texture_vk { struct wined3d_texture t; + + VkImage vk_image; + struct wined3d_allocator_block *memory; + VkDeviceMemory vk_memory; + uint64_t command_buffer_id; };
static inline struct wined3d_texture_vk *wined3d_texture_vk(struct wined3d_texture *texture)