[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