wined3d: Create Vulkan images for texture resources.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2020-04-20 23:30:23 +04:30 committed by Alexandre Julliard
parent d16de1e06c
commit 07981fa64f
3 changed files with 205 additions and 6 deletions

View File

@ -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;

View File

@ -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 =

View File

@ -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)