[PATCH 1/6] dxgi: Move D3D12 helper functions closer to the top of the file.

Józef Kucia jkucia at codeweavers.com
Wed Aug 29 05:53:34 CDT 2018


We need to re-create a Vulkan swapchain in ResizeBuffers().

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
 dlls/dxgi/swapchain.c | 872 +++++++++++++++++++++++++-------------------------
 1 file changed, 436 insertions(+), 436 deletions(-)

diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
index 101f2d185e17..a2fc37d7efb9 100644
--- a/dlls/dxgi/swapchain.c
+++ b/dlls/dxgi/swapchain.c
@@ -909,6 +909,442 @@ struct d3d12_swapchain
     DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc;
 };
 
+static DXGI_FORMAT dxgi_format_from_vk_format(VkFormat vk_format)
+{
+    switch (vk_format)
+    {
+        case VK_FORMAT_B8G8R8A8_SRGB:  return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
+        case VK_FORMAT_B8G8R8A8_UNORM: return DXGI_FORMAT_B8G8R8A8_UNORM;
+        case VK_FORMAT_R8G8B8A8_SRGB:  return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+        case VK_FORMAT_R8G8B8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM;
+        default:
+            WARN("Unhandled format %#x.\n", vk_format);
+            return DXGI_FORMAT_UNKNOWN;
+    }
+}
+
+static VkFormat get_swapchain_fallback_format(VkFormat vk_format)
+{
+    switch (vk_format)
+    {
+        case VK_FORMAT_R8G8B8A8_SRGB:  return VK_FORMAT_B8G8R8A8_SRGB;
+        case VK_FORMAT_R8G8B8A8_UNORM: return VK_FORMAT_B8G8R8A8_UNORM;
+        default:
+            WARN("Unhandled format %#x.\n", vk_format);
+            return VK_FORMAT_UNDEFINED;
+    }
+}
+
+static HRESULT select_vk_format(const struct dxgi_vk_funcs *vk_funcs,
+        VkPhysicalDevice vk_physical_device, VkSurfaceKHR vk_surface,
+        const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, VkFormat *vk_format)
+{
+    VkSurfaceFormatKHR *formats;
+    uint32_t format_count;
+    VkFormat format;
+    unsigned int i;
+    VkResult vr;
+
+    *vk_format = VK_FORMAT_UNDEFINED;
+
+    format = vkd3d_get_vk_format(swapchain_desc->Format);
+
+    vr = vk_funcs->p_vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, vk_surface, &format_count, NULL);
+    if (vr < 0 || !format_count)
+    {
+        WARN("Failed to get supported surface formats, vr %d.\n", vr);
+        return DXGI_ERROR_INVALID_CALL;
+    }
+
+    if (!(formats = heap_calloc(format_count, sizeof(*formats))))
+        return E_OUTOFMEMORY;
+
+    if ((vr = vk_funcs->p_vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device,
+            vk_surface, &format_count, formats)) < 0)
+    {
+        WARN("Failed to enumerate supported surface formats, vr %d.\n", vr);
+        heap_free(formats);
+        return hresult_from_vk_result(vr);
+    }
+
+    for (i = 0; i < format_count; ++i)
+    {
+        if (formats[i].format == format && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
+            break;
+    }
+    if (i == format_count)
+    {
+        /* Try to create a swapchain with format conversion. */
+        format = get_swapchain_fallback_format(format);
+        WARN("Failed to find Vulkan swapchain format for %s.\n", debug_dxgi_format(swapchain_desc->Format));
+        for (i = 0; i < format_count; ++i)
+        {
+            if (formats[i].format == format && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
+            {
+                format = formats[i].format;
+                break;
+            }
+        }
+    }
+    heap_free(formats);
+    if (i == format_count)
+    {
+        FIXME("Failed to find Vulkan swapchain format for %s.\n", debug_dxgi_format(swapchain_desc->Format));
+        return DXGI_ERROR_UNSUPPORTED;
+    }
+
+    TRACE("Using Vulkan swapchain format %#x.\n", format);
+
+    *vk_format = format;
+    return S_OK;
+}
+
+static HRESULT vk_select_memory_type(const struct dxgi_vk_funcs *vk_funcs,
+        VkPhysicalDevice vk_physical_device, uint32_t memory_type_mask,
+        VkMemoryPropertyFlags flags, uint32_t *memory_type_index)
+{
+    VkPhysicalDeviceMemoryProperties memory_properties;
+    unsigned int i;
+
+    vk_funcs->p_vkGetPhysicalDeviceMemoryProperties(vk_physical_device, &memory_properties);
+    for (i = 0; i < memory_properties.memoryTypeCount; ++i)
+    {
+        if (!(memory_type_mask & (1u << i)))
+            continue;
+
+        if ((memory_properties.memoryTypes[i].propertyFlags & flags) == flags)
+        {
+            *memory_type_index = i;
+            return S_OK;
+        }
+    }
+
+    FIXME("Failed to find memory type (allowed types %#x).\n", memory_type_mask);
+    return E_FAIL;
+}
+
+static HRESULT d3d12_swapchain_create_user_buffers(struct d3d12_swapchain *swapchain,
+        const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, VkFormat vk_format)
+{
+    const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
+    VkDeviceSize image_offset[DXGI_MAX_SWAP_CHAIN_BUFFERS];
+    VkDevice vk_device = swapchain->vk_device;
+    VkMemoryAllocateInfo allocate_info;
+    VkMemoryRequirements requirements;
+    VkImageCreateInfo image_info;
+    uint32_t memory_type_mask;
+    VkDeviceSize memory_size;
+    unsigned int i;
+    VkResult vr;
+    HRESULT hr;
+
+    memset(&image_info, 0, sizeof(image_info));
+    image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+    image_info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+    image_info.imageType = VK_IMAGE_TYPE_2D;
+    image_info.format = vk_format;
+    image_info.extent.width = swapchain_desc->Width;
+    image_info.extent.height = swapchain_desc->Height;
+    image_info.extent.depth = 1;
+    image_info.mipLevels = 1;
+    image_info.arrayLayers = 1;
+    image_info.samples = VK_SAMPLE_COUNT_1_BIT;
+    image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
+    image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT
+            | VK_IMAGE_USAGE_TRANSFER_DST_BIT
+            | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+    image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+    image_info.queueFamilyIndexCount = 0;
+    image_info.pQueueFamilyIndices = NULL;
+    image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+    for (i = 0; i < swapchain->buffer_count; ++i)
+    {
+        if ((vr = vk_funcs->p_vkCreateImage(vk_device, &image_info, NULL, &swapchain->vk_images[i])) < 0)
+        {
+            WARN("Failed to create Vulkan image, vr %d.\n", vr);
+            swapchain->vk_images[i] = VK_NULL_HANDLE;
+            return hresult_from_vk_result(vr);
+        }
+    }
+
+    memory_size = 0;
+    memory_type_mask = ~0u;
+    for (i = 0; i < swapchain->buffer_count; ++i)
+    {
+        vk_funcs->p_vkGetImageMemoryRequirements(vk_device, swapchain->vk_images[i], &requirements);
+
+        TRACE("Size %s, alignment %s, memory types %#x.\n",
+                wine_dbgstr_longlong(requirements.size), wine_dbgstr_longlong(requirements.alignment),
+                requirements.memoryTypeBits);
+
+        image_offset[i] = (memory_size + (requirements.alignment - 1)) & ~(requirements.alignment - 1);
+        memory_size = image_offset[i] + requirements.size;
+
+        memory_type_mask &= requirements.memoryTypeBits;
+    }
+
+    TRACE("Allocating %s bytes for user images.\n", wine_dbgstr_longlong(memory_size));
+
+    allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+    allocate_info.pNext = NULL;
+    allocate_info.allocationSize = memory_size;
+
+    if (FAILED(hr = vk_select_memory_type(vk_funcs, swapchain->vk_physical_device,
+            memory_type_mask, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocate_info.memoryTypeIndex)))
+        return hr;
+
+    if ((vr = vk_funcs->p_vkAllocateMemory(vk_device, &allocate_info, NULL, &swapchain->vk_memory)) < 0)
+    {
+        WARN("Failed to allocate device memory, vr %d.\n", vr);
+        swapchain->vk_memory = VK_NULL_HANDLE;
+        return hresult_from_vk_result(vr);
+    }
+
+    for (i = 0; i < swapchain->buffer_count; ++i)
+    {
+        if ((vr = vk_funcs->p_vkBindImageMemory(vk_device, swapchain->vk_images[i],
+                swapchain->vk_memory, image_offset[i])) < 0)
+        {
+            WARN("Failed to bind image memory, vr %d.\n", vr);
+            return hresult_from_vk_result(vr);
+        }
+    }
+
+    return S_OK;
+}
+
+static void vk_cmd_image_barrier(const struct dxgi_vk_funcs *vk_funcs, VkCommandBuffer cmd_buffer,
+        VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
+        VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask,
+        VkImageLayout old_layout, VkImageLayout new_layout, VkImage image)
+{
+    VkImageMemoryBarrier barrier;
+
+    barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+    barrier.pNext = NULL;
+    barrier.srcAccessMask = src_access_mask;
+    barrier.dstAccessMask = dst_access_mask;
+    barrier.oldLayout = old_layout;
+    barrier.newLayout = new_layout;
+    barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+    barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+    barrier.image = image;
+    barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    barrier.subresourceRange.baseMipLevel = 0;
+    barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
+    barrier.subresourceRange.baseArrayLayer = 0;
+    barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+
+    vk_funcs->p_vkCmdPipelineBarrier(cmd_buffer,
+            src_stage_mask, dst_stage_mask, 0, 0, NULL, 0, NULL, 1, &barrier);
+}
+
+static HRESULT d3d12_swapchain_prepare_command_buffers(struct d3d12_swapchain *swapchain,
+        const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, uint32_t queue_family_index,
+        VkImage vk_swapchain_images[DXGI_MAX_SWAP_CHAIN_BUFFERS])
+{
+    const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
+    VkDevice vk_device = swapchain->vk_device;
+    VkCommandBufferAllocateInfo allocate_info;
+    VkSemaphoreCreateInfo semaphore_info;
+    VkCommandBufferBeginInfo begin_info;
+    VkCommandPoolCreateInfo pool_info;
+    VkImageBlit blit;
+    unsigned int i;
+    VkResult vr;
+
+    pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+    pool_info.pNext = NULL;
+    pool_info.flags = 0;
+    pool_info.queueFamilyIndex = queue_family_index;
+
+    if ((vr = vk_funcs->p_vkCreateCommandPool(vk_device, &pool_info,
+            NULL, &swapchain->vk_cmd_pool)) < 0)
+    {
+        WARN("Failed to create command pool, vr %d.\n", vr);
+        swapchain->vk_cmd_pool = VK_NULL_HANDLE;
+        return hresult_from_vk_result(vr);
+    }
+
+    allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+    allocate_info.pNext = NULL;
+    allocate_info.commandPool = swapchain->vk_cmd_pool;
+    allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+    allocate_info.commandBufferCount = swapchain->buffer_count;
+
+    if ((vr = vk_funcs->p_vkAllocateCommandBuffers(vk_device, &allocate_info,
+            swapchain->vk_cmd_buffers)) < 0)
+    {
+        WARN("Failed to allocate command buffers, vr %d.\n", vr);
+        return hresult_from_vk_result(vr);
+    }
+
+    for (i = 0; i < swapchain->buffer_count; ++i)
+    {
+        VkCommandBuffer vk_cmd_buffer = swapchain->vk_cmd_buffers[i];
+
+        begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+        begin_info.pNext = NULL;
+        begin_info.flags = 0;
+        begin_info.pInheritanceInfo = NULL;
+
+        if ((vr = vk_funcs->p_vkBeginCommandBuffer(vk_cmd_buffer, &begin_info)) < 0)
+        {
+            WARN("Failed to begin command buffer, vr %d.\n", vr);
+            return hresult_from_vk_result(vr);
+        }
+
+        vk_cmd_image_barrier(vk_funcs, vk_cmd_buffer,
+                VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+                0, VK_ACCESS_TRANSFER_WRITE_BIT,
+                VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                vk_swapchain_images[i]);
+
+        blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+        blit.srcSubresource.mipLevel = 0;
+        blit.srcSubresource.baseArrayLayer = 0;
+        blit.srcSubresource.layerCount = 1;
+        blit.srcOffsets[0].x = 0;
+        blit.srcOffsets[0].y = 0;
+        blit.srcOffsets[0].z = 0;
+        blit.srcOffsets[1].x = swapchain_desc->Width;
+        blit.srcOffsets[1].y = swapchain_desc->Height;
+        blit.srcOffsets[1].z = 1;
+        blit.dstSubresource = blit.srcSubresource;
+        blit.dstOffsets[0] = blit.srcOffsets[0];
+        blit.dstOffsets[1] = blit.srcOffsets[1];
+
+        vk_funcs->p_vkCmdBlitImage(vk_cmd_buffer,
+                swapchain->vk_images[i], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                vk_swapchain_images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                1, &blit, VK_FILTER_NEAREST);
+
+        vk_cmd_image_barrier(vk_funcs, vk_cmd_buffer,
+                VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+                VK_ACCESS_TRANSFER_WRITE_BIT, 0,
+                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+                vk_swapchain_images[i]);
+
+        if ((vr = vk_funcs->p_vkEndCommandBuffer(vk_cmd_buffer)) < 0)
+        {
+            WARN("Failed to end command buffer, vr %d.\n", vr);
+            return hresult_from_vk_result(vr);
+        }
+    }
+
+    for (i = 0; i < swapchain->buffer_count; ++i)
+    {
+        semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+        semaphore_info.pNext = NULL;
+        semaphore_info.flags = 0;
+
+        if ((vr = vk_funcs->p_vkCreateSemaphore(vk_device, &semaphore_info,
+                NULL, &swapchain->vk_semaphores[i])) < 0)
+        {
+            WARN("Failed to create semaphore, vr %d.\n", vr);
+            swapchain->vk_semaphores[i] = VK_NULL_HANDLE;
+            return hresult_from_vk_result(vr);
+        }
+    }
+
+    return S_OK;
+}
+
+static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain,
+        ID3D12Device *device, ID3D12CommandQueue *queue,
+        const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, VkFormat vk_swapchain_format, VkFormat vk_format)
+{
+    const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
+    VkImage vk_swapchain_images[DXGI_MAX_SWAP_CHAIN_BUFFERS];
+    struct vkd3d_image_resource_create_info resource_info;
+    VkSwapchainKHR vk_swapchain = swapchain->vk_swapchain;
+    VkDevice vk_device = swapchain->vk_device;
+    uint32_t image_count, queue_family_index;
+    D3D12_COMMAND_QUEUE_DESC queue_desc;
+    unsigned int i;
+    VkResult vr;
+    HRESULT hr;
+
+    if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, NULL)) < 0)
+    {
+        WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr);
+        return hresult_from_vk_result(vr);
+    }
+    if (image_count != swapchain_desc->BufferCount)
+        FIXME("Got %u swapchain images, expected %u.\n", image_count, swapchain_desc->BufferCount);
+    if (image_count > ARRAY_SIZE(vk_swapchain_images))
+        return E_FAIL;
+    swapchain->buffer_count = image_count;
+    if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain,
+            &image_count, vk_swapchain_images)) < 0)
+    {
+        WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr);
+        return hresult_from_vk_result(vr);
+    }
+
+    resource_info.type = VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO;
+    resource_info.next = NULL;
+    resource_info.desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+    resource_info.desc.Alignment = 0;
+    resource_info.desc.Width = swapchain_desc->Width;
+    resource_info.desc.Height = swapchain_desc->Height;
+    resource_info.desc.DepthOrArraySize = 1;
+    resource_info.desc.MipLevels = 1;
+    resource_info.desc.Format = dxgi_format_from_vk_format(vk_format);
+    resource_info.desc.SampleDesc.Count = 1;
+    resource_info.desc.SampleDesc.Quality = 0;
+    resource_info.desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+    resource_info.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+    resource_info.flags = VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION;
+
+    if (vk_swapchain_format != vk_format)
+    {
+        queue_desc = ID3D12CommandQueue_GetDesc(queue);
+        if (queue_desc.Type != D3D12_COMMAND_LIST_TYPE_DIRECT)
+        {
+            /* vkCmdBlitImage() is only supported for Graphics queues. */
+            FIXME("Format conversion not implemented for command queue type %#x.\n", queue_desc.Type);
+            return E_NOTIMPL;
+        }
+        queue_family_index = vkd3d_get_vk_queue_family_index(queue);
+
+        TRACE("Creating user swapchain buffers for format conversion.\n");
+
+        if (FAILED(hr = d3d12_swapchain_create_user_buffers(swapchain, swapchain_desc, vk_format)))
+            return hr;
+
+        if (FAILED(hr = d3d12_swapchain_prepare_command_buffers(swapchain, swapchain_desc,
+                queue_family_index, vk_swapchain_images)))
+            return hr;
+    }
+
+    for (i = 0; i < swapchain->buffer_count; ++i)
+    {
+        if (swapchain->vk_images[i])
+        {
+            resource_info.vk_image = swapchain->vk_images[i];
+            resource_info.present_state = D3D12_RESOURCE_STATE_COPY_SOURCE;
+        }
+        else
+        {
+            resource_info.vk_image = vk_swapchain_images[i];
+            resource_info.present_state = D3D12_RESOURCE_STATE_PRESENT;
+        }
+
+        if (FAILED(hr = vkd3d_create_image_resource(device, &resource_info, &swapchain->buffers[i])))
+        {
+            WARN("Failed to create vkd3d resource for Vulkan image %u, hr %#x.\n", i, hr);
+            return hr;
+        }
+
+        vkd3d_resource_incref(swapchain->buffers[i]);
+        ID3D12Resource_Release(swapchain->buffers[i]);
+    }
+
+    return S_OK;
+}
+
 static inline struct d3d12_swapchain *d3d12_swapchain_from_IDXGISwapChain3(IDXGISwapChain3 *iface)
 {
     return CONTAINING_RECORD(iface, struct d3d12_swapchain, IDXGISwapChain3_iface);
@@ -1694,442 +2130,6 @@ static BOOL init_vk_funcs(struct dxgi_vk_funcs *dxgi, VkInstance vk_instance, Vk
     return TRUE;
 }
 
-static DXGI_FORMAT dxgi_format_from_vk_format(VkFormat vk_format)
-{
-    switch (vk_format)
-    {
-        case VK_FORMAT_B8G8R8A8_SRGB:  return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
-        case VK_FORMAT_B8G8R8A8_UNORM: return DXGI_FORMAT_B8G8R8A8_UNORM;
-        case VK_FORMAT_R8G8B8A8_SRGB:  return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
-        case VK_FORMAT_R8G8B8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM;
-        default:
-            WARN("Unhandled format %#x.\n", vk_format);
-            return DXGI_FORMAT_UNKNOWN;
-    }
-}
-
-static VkFormat get_swapchain_fallback_format(VkFormat vk_format)
-{
-    switch (vk_format)
-    {
-        case VK_FORMAT_R8G8B8A8_SRGB:  return VK_FORMAT_B8G8R8A8_SRGB;
-        case VK_FORMAT_R8G8B8A8_UNORM: return VK_FORMAT_B8G8R8A8_UNORM;
-        default:
-            WARN("Unhandled format %#x.\n", vk_format);
-            return VK_FORMAT_UNDEFINED;
-    }
-}
-
-static HRESULT select_vk_format(const struct dxgi_vk_funcs *vk_funcs,
-        VkPhysicalDevice vk_physical_device, VkSurfaceKHR vk_surface,
-        const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, VkFormat *vk_format)
-{
-    VkSurfaceFormatKHR *formats;
-    uint32_t format_count;
-    VkFormat format;
-    unsigned int i;
-    VkResult vr;
-
-    *vk_format = VK_FORMAT_UNDEFINED;
-
-    format = vkd3d_get_vk_format(swapchain_desc->Format);
-
-    vr = vk_funcs->p_vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, vk_surface, &format_count, NULL);
-    if (vr < 0 || !format_count)
-    {
-        WARN("Failed to get supported surface formats, vr %d.\n", vr);
-        return DXGI_ERROR_INVALID_CALL;
-    }
-
-    if (!(formats = heap_calloc(format_count, sizeof(*formats))))
-        return E_OUTOFMEMORY;
-
-    if ((vr = vk_funcs->p_vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device,
-            vk_surface, &format_count, formats)) < 0)
-    {
-        WARN("Failed to enumerate supported surface formats, vr %d.\n", vr);
-        heap_free(formats);
-        return hresult_from_vk_result(vr);
-    }
-
-    for (i = 0; i < format_count; ++i)
-    {
-        if (formats[i].format == format && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
-            break;
-    }
-    if (i == format_count)
-    {
-        /* Try to create a swapchain with format conversion. */
-        format = get_swapchain_fallback_format(format);
-        WARN("Failed to find Vulkan swapchain format for %s.\n", debug_dxgi_format(swapchain_desc->Format));
-        for (i = 0; i < format_count; ++i)
-        {
-            if (formats[i].format == format && formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
-            {
-                format = formats[i].format;
-                break;
-            }
-        }
-    }
-    heap_free(formats);
-    if (i == format_count)
-    {
-        FIXME("Failed to find Vulkan swapchain format for %s.\n", debug_dxgi_format(swapchain_desc->Format));
-        return DXGI_ERROR_UNSUPPORTED;
-    }
-
-    TRACE("Using Vulkan swapchain format %#x.\n", format);
-
-    *vk_format = format;
-    return S_OK;
-}
-
-static HRESULT vk_select_memory_type(const struct dxgi_vk_funcs *vk_funcs,
-        VkPhysicalDevice vk_physical_device, uint32_t memory_type_mask,
-        VkMemoryPropertyFlags flags, uint32_t *memory_type_index)
-{
-    VkPhysicalDeviceMemoryProperties memory_properties;
-    unsigned int i;
-
-    vk_funcs->p_vkGetPhysicalDeviceMemoryProperties(vk_physical_device, &memory_properties);
-    for (i = 0; i < memory_properties.memoryTypeCount; ++i)
-    {
-        if (!(memory_type_mask & (1u << i)))
-            continue;
-
-        if ((memory_properties.memoryTypes[i].propertyFlags & flags) == flags)
-        {
-            *memory_type_index = i;
-            return S_OK;
-        }
-    }
-
-    FIXME("Failed to find memory type (allowed types %#x).\n", memory_type_mask);
-    return E_FAIL;
-}
-
-static HRESULT d3d12_swapchain_create_user_buffers(struct d3d12_swapchain *swapchain,
-        const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, VkFormat vk_format)
-{
-    const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
-    VkDeviceSize image_offset[DXGI_MAX_SWAP_CHAIN_BUFFERS];
-    VkDevice vk_device = swapchain->vk_device;
-    VkMemoryAllocateInfo allocate_info;
-    VkMemoryRequirements requirements;
-    VkImageCreateInfo image_info;
-    uint32_t memory_type_mask;
-    VkDeviceSize memory_size;
-    unsigned int i;
-    VkResult vr;
-    HRESULT hr;
-
-    memset(&image_info, 0, sizeof(image_info));
-    image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
-    image_info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
-    image_info.imageType = VK_IMAGE_TYPE_2D;
-    image_info.format = vk_format;
-    image_info.extent.width = swapchain_desc->Width;
-    image_info.extent.height = swapchain_desc->Height;
-    image_info.extent.depth = 1;
-    image_info.mipLevels = 1;
-    image_info.arrayLayers = 1;
-    image_info.samples = VK_SAMPLE_COUNT_1_BIT;
-    image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
-    image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT
-            | VK_IMAGE_USAGE_TRANSFER_DST_BIT
-            | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
-    image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
-    image_info.queueFamilyIndexCount = 0;
-    image_info.pQueueFamilyIndices = NULL;
-    image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
-
-    for (i = 0; i < swapchain->buffer_count; ++i)
-    {
-        if ((vr = vk_funcs->p_vkCreateImage(vk_device, &image_info, NULL, &swapchain->vk_images[i])) < 0)
-        {
-            WARN("Failed to create Vulkan image, vr %d.\n", vr);
-            swapchain->vk_images[i] = VK_NULL_HANDLE;
-            return hresult_from_vk_result(vr);
-        }
-    }
-
-    memory_size = 0;
-    memory_type_mask = ~0u;
-    for (i = 0; i < swapchain->buffer_count; ++i)
-    {
-        vk_funcs->p_vkGetImageMemoryRequirements(vk_device, swapchain->vk_images[i], &requirements);
-
-        TRACE("Size %s, alignment %s, memory types %#x.\n",
-                wine_dbgstr_longlong(requirements.size), wine_dbgstr_longlong(requirements.alignment),
-                requirements.memoryTypeBits);
-
-        image_offset[i] = (memory_size + (requirements.alignment - 1)) & ~(requirements.alignment - 1);
-        memory_size = image_offset[i] + requirements.size;
-
-        memory_type_mask &= requirements.memoryTypeBits;
-    }
-
-    TRACE("Allocating %s bytes for user images.\n", wine_dbgstr_longlong(memory_size));
-
-    allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
-    allocate_info.pNext = NULL;
-    allocate_info.allocationSize = memory_size;
-
-    if (FAILED(hr = vk_select_memory_type(vk_funcs, swapchain->vk_physical_device,
-            memory_type_mask, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocate_info.memoryTypeIndex)))
-        return hr;
-
-    if ((vr = vk_funcs->p_vkAllocateMemory(vk_device, &allocate_info, NULL, &swapchain->vk_memory)) < 0)
-    {
-        WARN("Failed to allocate device memory, vr %d.\n", vr);
-        swapchain->vk_memory = VK_NULL_HANDLE;
-        return hresult_from_vk_result(vr);
-    }
-
-    for (i = 0; i < swapchain->buffer_count; ++i)
-    {
-        if ((vr = vk_funcs->p_vkBindImageMemory(vk_device, swapchain->vk_images[i],
-                swapchain->vk_memory, image_offset[i])) < 0)
-        {
-            WARN("Failed to bind image memory, vr %d.\n", vr);
-            return hresult_from_vk_result(vr);
-        }
-    }
-
-    return S_OK;
-}
-
-static void vk_cmd_image_barrier(const struct dxgi_vk_funcs *vk_funcs, VkCommandBuffer cmd_buffer,
-        VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
-        VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask,
-        VkImageLayout old_layout, VkImageLayout new_layout, VkImage image)
-{
-    VkImageMemoryBarrier barrier;
-
-    barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
-    barrier.pNext = NULL;
-    barrier.srcAccessMask = src_access_mask;
-    barrier.dstAccessMask = dst_access_mask;
-    barrier.oldLayout = old_layout;
-    barrier.newLayout = new_layout;
-    barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
-    barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
-    barrier.image = image;
-    barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
-    barrier.subresourceRange.baseMipLevel = 0;
-    barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
-    barrier.subresourceRange.baseArrayLayer = 0;
-    barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
-
-    vk_funcs->p_vkCmdPipelineBarrier(cmd_buffer,
-            src_stage_mask, dst_stage_mask, 0, 0, NULL, 0, NULL, 1, &barrier);
-}
-
-static HRESULT d3d12_swapchain_prepare_command_buffers(struct d3d12_swapchain *swapchain,
-        const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, uint32_t queue_family_index,
-        VkImage vk_swapchain_images[DXGI_MAX_SWAP_CHAIN_BUFFERS])
-{
-    const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
-    VkDevice vk_device = swapchain->vk_device;
-    VkCommandBufferAllocateInfo allocate_info;
-    VkSemaphoreCreateInfo semaphore_info;
-    VkCommandBufferBeginInfo begin_info;
-    VkCommandPoolCreateInfo pool_info;
-    VkImageBlit blit;
-    unsigned int i;
-    VkResult vr;
-
-    pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
-    pool_info.pNext = NULL;
-    pool_info.flags = 0;
-    pool_info.queueFamilyIndex = queue_family_index;
-
-    if ((vr = vk_funcs->p_vkCreateCommandPool(vk_device, &pool_info,
-            NULL, &swapchain->vk_cmd_pool)) < 0)
-    {
-        WARN("Failed to create command pool, vr %d.\n", vr);
-        swapchain->vk_cmd_pool = VK_NULL_HANDLE;
-        return hresult_from_vk_result(vr);
-    }
-
-    allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
-    allocate_info.pNext = NULL;
-    allocate_info.commandPool = swapchain->vk_cmd_pool;
-    allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
-    allocate_info.commandBufferCount = swapchain->buffer_count;
-
-    if ((vr = vk_funcs->p_vkAllocateCommandBuffers(vk_device, &allocate_info,
-            swapchain->vk_cmd_buffers)) < 0)
-    {
-        WARN("Failed to allocate command buffers, vr %d.\n", vr);
-        return hresult_from_vk_result(vr);
-    }
-
-    for (i = 0; i < swapchain->buffer_count; ++i)
-    {
-        VkCommandBuffer vk_cmd_buffer = swapchain->vk_cmd_buffers[i];
-
-        begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
-        begin_info.pNext = NULL;
-        begin_info.flags = 0;
-        begin_info.pInheritanceInfo = NULL;
-
-        if ((vr = vk_funcs->p_vkBeginCommandBuffer(vk_cmd_buffer, &begin_info)) < 0)
-        {
-            WARN("Failed to begin command buffer, vr %d.\n", vr);
-            return hresult_from_vk_result(vr);
-        }
-
-        vk_cmd_image_barrier(vk_funcs, vk_cmd_buffer,
-                VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
-                0, VK_ACCESS_TRANSFER_WRITE_BIT,
-                VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                vk_swapchain_images[i]);
-
-        blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
-        blit.srcSubresource.mipLevel = 0;
-        blit.srcSubresource.baseArrayLayer = 0;
-        blit.srcSubresource.layerCount = 1;
-        blit.srcOffsets[0].x = 0;
-        blit.srcOffsets[0].y = 0;
-        blit.srcOffsets[0].z = 0;
-        blit.srcOffsets[1].x = swapchain_desc->Width;
-        blit.srcOffsets[1].y = swapchain_desc->Height;
-        blit.srcOffsets[1].z = 1;
-        blit.dstSubresource = blit.srcSubresource;
-        blit.dstOffsets[0] = blit.srcOffsets[0];
-        blit.dstOffsets[1] = blit.srcOffsets[1];
-
-        vk_funcs->p_vkCmdBlitImage(vk_cmd_buffer,
-                swapchain->vk_images[i], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
-                vk_swapchain_images[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                1, &blit, VK_FILTER_NEAREST);
-
-        vk_cmd_image_barrier(vk_funcs, vk_cmd_buffer,
-                VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
-                VK_ACCESS_TRANSFER_WRITE_BIT, 0,
-                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
-                vk_swapchain_images[i]);
-
-        if ((vr = vk_funcs->p_vkEndCommandBuffer(vk_cmd_buffer)) < 0)
-        {
-            WARN("Failed to end command buffer, vr %d.\n", vr);
-            return hresult_from_vk_result(vr);
-        }
-    }
-
-    for (i = 0; i < swapchain->buffer_count; ++i)
-    {
-        semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
-        semaphore_info.pNext = NULL;
-        semaphore_info.flags = 0;
-
-        if ((vr = vk_funcs->p_vkCreateSemaphore(vk_device, &semaphore_info,
-                NULL, &swapchain->vk_semaphores[i])) < 0)
-        {
-            WARN("Failed to create semaphore, vr %d.\n", vr);
-            swapchain->vk_semaphores[i] = VK_NULL_HANDLE;
-            return hresult_from_vk_result(vr);
-        }
-    }
-
-    return S_OK;
-}
-
-static HRESULT d3d12_swapchain_create_buffers(struct d3d12_swapchain *swapchain,
-        ID3D12Device *device, ID3D12CommandQueue *queue,
-        const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, VkFormat vk_swapchain_format, VkFormat vk_format)
-{
-    const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
-    VkImage vk_swapchain_images[DXGI_MAX_SWAP_CHAIN_BUFFERS];
-    struct vkd3d_image_resource_create_info resource_info;
-    VkSwapchainKHR vk_swapchain = swapchain->vk_swapchain;
-    VkDevice vk_device = swapchain->vk_device;
-    uint32_t image_count, queue_family_index;
-    D3D12_COMMAND_QUEUE_DESC queue_desc;
-    unsigned int i;
-    VkResult vr;
-    HRESULT hr;
-
-    if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, NULL)) < 0)
-    {
-        WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr);
-        return hresult_from_vk_result(vr);
-    }
-    if (image_count != swapchain_desc->BufferCount)
-        FIXME("Got %u swapchain images, expected %u.\n", image_count, swapchain_desc->BufferCount);
-    if (image_count > ARRAY_SIZE(vk_swapchain_images))
-        return E_FAIL;
-    swapchain->buffer_count = image_count;
-    if ((vr = vk_funcs->p_vkGetSwapchainImagesKHR(vk_device, vk_swapchain,
-            &image_count, vk_swapchain_images)) < 0)
-    {
-        WARN("Failed to get Vulkan swapchain images, vr %d.\n", vr);
-        return hresult_from_vk_result(vr);
-    }
-
-    resource_info.type = VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO;
-    resource_info.next = NULL;
-    resource_info.desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
-    resource_info.desc.Alignment = 0;
-    resource_info.desc.Width = swapchain_desc->Width;
-    resource_info.desc.Height = swapchain_desc->Height;
-    resource_info.desc.DepthOrArraySize = 1;
-    resource_info.desc.MipLevels = 1;
-    resource_info.desc.Format = dxgi_format_from_vk_format(vk_format);
-    resource_info.desc.SampleDesc.Count = 1;
-    resource_info.desc.SampleDesc.Quality = 0;
-    resource_info.desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
-    resource_info.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
-    resource_info.flags = VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION;
-
-    if (vk_swapchain_format != vk_format)
-    {
-        queue_desc = ID3D12CommandQueue_GetDesc(queue);
-        if (queue_desc.Type != D3D12_COMMAND_LIST_TYPE_DIRECT)
-        {
-            /* vkCmdBlitImage() is only supported for Graphics queues. */
-            FIXME("Format conversion not implemented for command queue type %#x.\n", queue_desc.Type);
-            return E_NOTIMPL;
-        }
-        queue_family_index = vkd3d_get_vk_queue_family_index(queue);
-
-        TRACE("Creating user swapchain buffers for format conversion.\n");
-
-        if (FAILED(hr = d3d12_swapchain_create_user_buffers(swapchain, swapchain_desc, vk_format)))
-            return hr;
-
-        if (FAILED(hr = d3d12_swapchain_prepare_command_buffers(swapchain, swapchain_desc,
-                queue_family_index, vk_swapchain_images)))
-            return hr;
-    }
-
-    for (i = 0; i < swapchain->buffer_count; ++i)
-    {
-        if (swapchain->vk_images[i])
-        {
-            resource_info.vk_image = swapchain->vk_images[i];
-            resource_info.present_state = D3D12_RESOURCE_STATE_COPY_SOURCE;
-        }
-        else
-        {
-            resource_info.vk_image = vk_swapchain_images[i];
-            resource_info.present_state = D3D12_RESOURCE_STATE_PRESENT;
-        }
-
-        if (FAILED(hr = vkd3d_create_image_resource(device, &resource_info, &swapchain->buffers[i])))
-        {
-            WARN("Failed to create vkd3d resource for Vulkan image %u, hr %#x.\n", i, hr);
-            return hr;
-        }
-
-        vkd3d_resource_incref(swapchain->buffers[i]);
-        ID3D12Resource_Release(swapchain->buffers[i]);
-    }
-
-    return S_OK;
-}
-
 static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGIFactory *factory,
         ID3D12Device *device, ID3D12CommandQueue *queue, HWND window,
         const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc)
-- 
2.16.4




More information about the wine-devel mailing list