Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
9aeef376
Commit
9aeef376
authored
May 29, 2020
by
Henri Verbeet
Committed by
Alexandre Julliard
May 29, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wined3d: Implement swapchains for the Vulkan adapter.
Signed-off-by:
Henri Verbeet
<
hverbeet@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
a8141ef0
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
658 additions
and
10 deletions
+658
-10
adapter_vk.c
dlls/wined3d/adapter_vk.c
+9
-4
swapchain.c
dlls/wined3d/swapchain.c
+610
-3
wined3d_private.h
dlls/wined3d/wined3d_private.h
+23
-1
wined3d_vk.h
dlls/wined3d/wined3d_vk.h
+16
-2
No files found.
dlls/wined3d/adapter_vk.c
View file @
9aeef376
...
...
@@ -421,6 +421,7 @@ vulkan_device_extensions[] =
{
VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME
,
~
0u
},
{
VK_KHR_MAINTENANCE1_EXTENSION_NAME
,
VK_API_VERSION_1_1
},
{
VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME
,
VK_API_VERSION_1_1
},
{
VK_KHR_SWAPCHAIN_EXTENSION_NAME
,
~
0u
},
};
static
bool
enable_vulkan_device_extensions
(
VkPhysicalDevice
physical_device
,
uint32_t
*
extension_count
,
...
...
@@ -1180,7 +1181,7 @@ static void adapter_vk_copy_bo_address(struct wined3d_context *context,
static
HRESULT
adapter_vk_create_swapchain
(
struct
wined3d_device
*
device
,
struct
wined3d_swapchain_desc
*
desc
,
void
*
parent
,
const
struct
wined3d_parent_ops
*
parent_ops
,
struct
wined3d_swapchain
**
swapchain
)
{
struct
wined3d_swapchain
*
swapchain_vk
;
struct
wined3d_swapchain
_vk
*
swapchain_vk
;
HRESULT
hr
;
TRACE
(
"device %p, desc %p, parent %p, parent_ops %p, swapchain %p.
\n
"
,
...
...
@@ -1197,15 +1198,17 @@ static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device, struct
}
TRACE
(
"Created swapchain %p.
\n
"
,
swapchain_vk
);
*
swapchain
=
swapchain_vk
;
*
swapchain
=
&
swapchain_vk
->
s
;
return
hr
;
}
static
void
adapter_vk_destroy_swapchain
(
struct
wined3d_swapchain
*
swapchain
)
{
wined3d_swapchain_cleanup
(
swapchain
);
heap_free
(
swapchain
);
struct
wined3d_swapchain_vk
*
swapchain_vk
=
wined3d_swapchain_vk
(
swapchain
);
wined3d_swapchain_vk_cleanup
(
swapchain_vk
);
heap_free
(
swapchain_vk
);
}
unsigned
int
wined3d_adapter_vk_get_memory_type_index
(
const
struct
wined3d_adapter_vk
*
adapter_vk
,
...
...
@@ -1827,6 +1830,8 @@ static const struct
vulkan_instance_extensions
[]
=
{
{
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
,
VK_API_VERSION_1_1
,
FALSE
},
{
VK_KHR_SURFACE_EXTENSION_NAME
,
~
0u
,
TRUE
},
{
VK_KHR_WIN32_SURFACE_EXTENSION_NAME
,
~
0u
,
TRUE
},
};
static
BOOL
enable_vulkan_instance_extensions
(
uint32_t
*
extension_count
,
...
...
dlls/wined3d/swapchain.c
View file @
9aeef376
...
...
@@ -113,6 +113,45 @@ void wined3d_swapchain_gl_cleanup(struct wined3d_swapchain_gl *swapchain_gl)
}
}
static
void
wined3d_swapchain_vk_destroy_vulkan_swapchain
(
struct
wined3d_swapchain_vk
*
swapchain_vk
)
{
struct
wined3d_device_vk
*
device_vk
=
wined3d_device_vk
(
swapchain_vk
->
s
.
device
);
const
struct
wined3d_vk_info
*
vk_info
;
unsigned
int
i
;
VkResult
vr
;
TRACE
(
"swapchain_vk %p.
\n
"
,
swapchain_vk
);
vk_info
=
&
wined3d_adapter_vk
(
device_vk
->
d
.
adapter
)
->
vk_info
;
if
((
vr
=
VK_CALL
(
vkQueueWaitIdle
(
device_vk
->
vk_queue
)))
<
0
)
ERR
(
"Failed to wait on queue, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
heap_free
(
swapchain_vk
->
vk_images
);
for
(
i
=
0
;
i
<
swapchain_vk
->
image_count
;
++
i
)
{
VK_CALL
(
vkDestroySemaphore
(
device_vk
->
vk_device
,
swapchain_vk
->
vk_semaphores
[
i
].
available
,
NULL
));
VK_CALL
(
vkDestroySemaphore
(
device_vk
->
vk_device
,
swapchain_vk
->
vk_semaphores
[
i
].
presentable
,
NULL
));
}
heap_free
(
swapchain_vk
->
vk_semaphores
);
VK_CALL
(
vkDestroySwapchainKHR
(
device_vk
->
vk_device
,
swapchain_vk
->
vk_swapchain
,
NULL
));
VK_CALL
(
vkDestroySurfaceKHR
(
vk_info
->
instance
,
swapchain_vk
->
vk_surface
,
NULL
));
}
static
void
wined3d_swapchain_vk_destroy_object
(
void
*
object
)
{
wined3d_swapchain_vk_destroy_vulkan_swapchain
(
object
);
}
void
wined3d_swapchain_vk_cleanup
(
struct
wined3d_swapchain_vk
*
swapchain_vk
)
{
struct
wined3d_cs
*
cs
=
swapchain_vk
->
s
.
device
->
cs
;
wined3d_cs_destroy_object
(
cs
,
wined3d_swapchain_vk_destroy_object
,
swapchain_vk
);
wined3d_cs_finish
(
cs
,
WINED3D_CS_QUEUE_DEFAULT
);
wined3d_swapchain_cleanup
(
&
swapchain_vk
->
s
);
}
ULONG
CDECL
wined3d_swapchain_incref
(
struct
wined3d_swapchain
*
swapchain
)
{
ULONG
refcount
=
InterlockedIncrement
(
&
swapchain
->
ref
);
...
...
@@ -551,10 +590,561 @@ static const struct wined3d_swapchain_ops swapchain_gl_ops =
swapchain_frontbuffer_updated
,
};
static
bool
wined3d_swapchain_vk_present_mode_supported
(
struct
wined3d_swapchain_vk
*
swapchain_vk
,
VkPresentModeKHR
vk_present_mode
)
{
struct
wined3d_device_vk
*
device_vk
=
wined3d_device_vk
(
swapchain_vk
->
s
.
device
);
const
struct
wined3d_vk_info
*
vk_info
;
struct
wined3d_adapter_vk
*
adapter_vk
;
VkPhysicalDevice
vk_physical_device
;
VkPresentModeKHR
*
vk_modes
;
bool
supported
=
false
;
uint32_t
count
,
i
;
VkResult
vr
;
adapter_vk
=
wined3d_adapter_vk
(
device_vk
->
d
.
adapter
);
vk_physical_device
=
adapter_vk
->
physical_device
;
vk_info
=
&
adapter_vk
->
vk_info
;
if
((
vr
=
VK_CALL
(
vkGetPhysicalDeviceSurfacePresentModesKHR
(
vk_physical_device
,
swapchain_vk
->
vk_surface
,
&
count
,
NULL
)))
<
0
)
{
ERR
(
"Failed to get supported present mode count, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
return
false
;
}
if
(
!
(
vk_modes
=
heap_calloc
(
count
,
sizeof
(
*
vk_modes
))))
return
false
;
if
((
vr
=
VK_CALL
(
vkGetPhysicalDeviceSurfacePresentModesKHR
(
vk_physical_device
,
swapchain_vk
->
vk_surface
,
&
count
,
vk_modes
)))
<
0
)
{
ERR
(
"Failed to get supported present modes, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
goto
done
;
}
for
(
i
=
0
;
i
<
count
;
++
i
)
{
if
(
vk_modes
[
i
]
==
vk_present_mode
)
{
supported
=
true
;
goto
done
;
}
}
done:
heap_free
(
vk_modes
);
return
supported
;
}
static
VkFormat
wined3d_swapchain_vk_select_vk_format
(
struct
wined3d_swapchain_vk
*
swapchain_vk
,
VkSurfaceKHR
vk_surface
)
{
struct
wined3d_device_vk
*
device_vk
=
wined3d_device_vk
(
swapchain_vk
->
s
.
device
);
const
struct
wined3d_swapchain_desc
*
desc
=
&
swapchain_vk
->
s
.
state
.
desc
;
const
struct
wined3d_vk_info
*
vk_info
;
struct
wined3d_adapter_vk
*
adapter_vk
;
const
struct
wined3d_format
*
format
;
VkPhysicalDevice
vk_physical_device
;
VkSurfaceFormatKHR
*
vk_formats
;
uint32_t
format_count
,
i
;
VkFormat
vk_format
;
VkResult
vr
;
adapter_vk
=
wined3d_adapter_vk
(
device_vk
->
d
.
adapter
);
vk_physical_device
=
adapter_vk
->
physical_device
;
vk_info
=
&
adapter_vk
->
vk_info
;
if
((
format
=
wined3d_get_format
(
&
adapter_vk
->
a
,
desc
->
backbuffer_format
,
WINED3D_BIND_RENDER_TARGET
)))
vk_format
=
wined3d_format_vk
(
format
)
->
vk_format
;
else
vk_format
=
VK_FORMAT_B8G8R8A8_UNORM
;
vr
=
VK_CALL
(
vkGetPhysicalDeviceSurfaceFormatsKHR
(
vk_physical_device
,
vk_surface
,
&
format_count
,
NULL
));
if
(
vr
<
0
||
!
format_count
)
{
WARN
(
"Failed to get supported surface format count, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
return
VK_FORMAT_UNDEFINED
;
}
if
(
!
(
vk_formats
=
heap_calloc
(
format_count
,
sizeof
(
*
vk_formats
))))
return
VK_FORMAT_UNDEFINED
;
if
((
vr
=
VK_CALL
(
vkGetPhysicalDeviceSurfaceFormatsKHR
(
vk_physical_device
,
vk_surface
,
&
format_count
,
vk_formats
)))
<
0
)
{
WARN
(
"Failed to get supported surface formats, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
heap_free
(
vk_formats
);
return
VK_FORMAT_UNDEFINED
;
}
for
(
i
=
0
;
i
<
format_count
;
++
i
)
{
if
(
vk_formats
[
i
].
format
==
vk_format
&&
vk_formats
[
i
].
colorSpace
==
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
)
break
;
}
if
(
i
==
format_count
)
{
/* Try to create a swapchain with format conversion. */
vk_format
=
VK_FORMAT_B8G8R8A8_UNORM
;
WARN
(
"Failed to find Vulkan swapchain format for %s.
\n
"
,
debug_d3dformat
(
desc
->
backbuffer_format
));
for
(
i
=
0
;
i
<
format_count
;
++
i
)
{
if
(
vk_formats
[
i
].
format
==
vk_format
&&
vk_formats
[
i
].
colorSpace
==
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
)
break
;
}
}
heap_free
(
vk_formats
);
if
(
i
==
format_count
)
{
FIXME
(
"Failed to find Vulkan swapchain format for %s.
\n
"
,
debug_d3dformat
(
desc
->
backbuffer_format
));
return
VK_FORMAT_UNDEFINED
;
}
TRACE
(
"Using Vulkan swapchain format %#x.
\n
"
,
vk_format
);
return
vk_format
;
}
static
bool
wined3d_swapchain_vk_create_vulkan_swapchain_images
(
struct
wined3d_swapchain_vk
*
swapchain_vk
,
VkSwapchainKHR
vk_swapchain
)
{
struct
wined3d_device_vk
*
device_vk
=
wined3d_device_vk
(
swapchain_vk
->
s
.
device
);
const
struct
wined3d_vk_info
*
vk_info
;
VkSemaphoreCreateInfo
semaphore_info
;
uint32_t
image_count
,
i
;
VkResult
vr
;
vk_info
=
&
wined3d_adapter_vk
(
device_vk
->
d
.
adapter
)
->
vk_info
;
if
((
vr
=
VK_CALL
(
vkGetSwapchainImagesKHR
(
device_vk
->
vk_device
,
vk_swapchain
,
&
image_count
,
NULL
)))
<
0
)
{
ERR
(
"Failed to get image count, vr %s
\n
"
,
wined3d_debug_vkresult
(
vr
));
return
false
;
}
if
(
!
(
swapchain_vk
->
vk_images
=
heap_calloc
(
image_count
,
sizeof
(
*
swapchain_vk
->
vk_images
))))
{
ERR
(
"Failed to allocate images array.
\n
"
);
return
false
;
}
if
((
vr
=
VK_CALL
(
vkGetSwapchainImagesKHR
(
device_vk
->
vk_device
,
vk_swapchain
,
&
image_count
,
swapchain_vk
->
vk_images
)))
<
0
)
{
ERR
(
"Failed to get swapchain images, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
heap_free
(
swapchain_vk
->
vk_images
);
return
false
;
}
if
(
!
(
swapchain_vk
->
vk_semaphores
=
heap_calloc
(
image_count
,
sizeof
(
*
swapchain_vk
->
vk_semaphores
))))
{
ERR
(
"Failed to allocate semaphores array.
\n
"
);
heap_free
(
swapchain_vk
->
vk_images
);
return
false
;
}
semaphore_info
.
sType
=
VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
;
semaphore_info
.
pNext
=
NULL
;
semaphore_info
.
flags
=
0
;
for
(
i
=
0
;
i
<
image_count
;
++
i
)
{
if
((
vr
=
VK_CALL
(
vkCreateSemaphore
(
device_vk
->
vk_device
,
&
semaphore_info
,
NULL
,
&
swapchain_vk
->
vk_semaphores
[
i
].
available
)))
<
0
)
{
ERR
(
"Failed to create semaphore, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
goto
fail
;
}
if
((
vr
=
VK_CALL
(
vkCreateSemaphore
(
device_vk
->
vk_device
,
&
semaphore_info
,
NULL
,
&
swapchain_vk
->
vk_semaphores
[
i
].
presentable
)))
<
0
)
{
ERR
(
"Failed to create semaphore, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
goto
fail
;
}
}
swapchain_vk
->
image_count
=
image_count
;
return
true
;
fail:
for
(
i
=
0
;
i
<
image_count
;
++
i
)
{
if
(
swapchain_vk
->
vk_semaphores
[
i
].
available
)
VK_CALL
(
vkDestroySemaphore
(
device_vk
->
vk_device
,
swapchain_vk
->
vk_semaphores
[
i
].
available
,
NULL
));
if
(
swapchain_vk
->
vk_semaphores
[
i
].
presentable
)
VK_CALL
(
vkDestroySemaphore
(
device_vk
->
vk_device
,
swapchain_vk
->
vk_semaphores
[
i
].
presentable
,
NULL
));
}
heap_free
(
swapchain_vk
->
vk_semaphores
);
heap_free
(
swapchain_vk
->
vk_images
);
return
false
;
}
static
HRESULT
wined3d_swapchain_vk_create_vulkan_swapchain
(
struct
wined3d_swapchain_vk
*
swapchain_vk
)
{
struct
wined3d_device_vk
*
device_vk
=
wined3d_device_vk
(
swapchain_vk
->
s
.
device
);
const
struct
wined3d_swapchain_desc
*
desc
=
&
swapchain_vk
->
s
.
state
.
desc
;
VkSwapchainCreateInfoKHR
vk_swapchain_desc
;
VkWin32SurfaceCreateInfoKHR
surface_desc
;
unsigned
int
width
,
height
,
image_count
;
const
struct
wined3d_vk_info
*
vk_info
;
VkSurfaceCapabilitiesKHR
surface_caps
;
struct
wined3d_adapter_vk
*
adapter_vk
;
VkPresentModeKHR
vk_present_mode
;
VkSwapchainKHR
vk_swapchain
;
VkImageUsageFlags
usage
;
VkSurfaceKHR
vk_surface
;
VkBool32
supported
;
VkFormat
vk_format
;
VkResult
vr
;
adapter_vk
=
wined3d_adapter_vk
(
device_vk
->
d
.
adapter
);
vk_info
=
&
adapter_vk
->
vk_info
;
surface_desc
.
sType
=
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR
;
surface_desc
.
pNext
=
NULL
;
surface_desc
.
flags
=
0
;
surface_desc
.
hinstance
=
(
HINSTANCE
)
GetWindowLongPtrW
(
swapchain_vk
->
s
.
win_handle
,
GWLP_HINSTANCE
);
surface_desc
.
hwnd
=
swapchain_vk
->
s
.
win_handle
;
if
((
vr
=
VK_CALL
(
vkCreateWin32SurfaceKHR
(
vk_info
->
instance
,
&
surface_desc
,
NULL
,
&
vk_surface
)))
<
0
)
{
ERR
(
"Failed to create Vulkan surface, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
return
E_FAIL
;
}
swapchain_vk
->
vk_surface
=
vk_surface
;
if
((
vr
=
VK_CALL
(
vkGetPhysicalDeviceSurfaceSupportKHR
(
adapter_vk
->
physical_device
,
device_vk
->
vk_queue_family_index
,
vk_surface
,
&
supported
)))
<
0
||
!
supported
)
{
ERR
(
"Queue family does not support presentation on this surface, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
goto
fail
;
}
if
((
vk_format
=
wined3d_swapchain_vk_select_vk_format
(
swapchain_vk
,
vk_surface
))
==
VK_FORMAT_UNDEFINED
)
{
ERR
(
"Failed to select swapchain format.
\n
"
);
goto
fail
;
}
if
((
vr
=
VK_CALL
(
vkGetPhysicalDeviceSurfaceCapabilitiesKHR
(
adapter_vk
->
physical_device
,
swapchain_vk
->
vk_surface
,
&
surface_caps
)))
<
0
)
{
ERR
(
"Failed to get surface capabilities, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
goto
fail
;
}
image_count
=
desc
->
backbuffer_count
;
if
(
image_count
<
surface_caps
.
minImageCount
)
image_count
=
surface_caps
.
minImageCount
;
else
if
(
surface_caps
.
maxImageCount
&&
image_count
>
surface_caps
.
maxImageCount
)
image_count
=
surface_caps
.
maxImageCount
;
if
(
image_count
!=
desc
->
backbuffer_count
)
WARN
(
"Image count %u is not supported (%u-%u).
\n
"
,
desc
->
backbuffer_count
,
surface_caps
.
minImageCount
,
surface_caps
.
maxImageCount
);
width
=
desc
->
backbuffer_width
;
if
(
width
<
surface_caps
.
minImageExtent
.
width
)
width
=
surface_caps
.
minImageExtent
.
width
;
else
if
(
width
>
surface_caps
.
maxImageExtent
.
width
)
width
=
surface_caps
.
maxImageExtent
.
width
;
height
=
desc
->
backbuffer_height
;
if
(
height
<
surface_caps
.
minImageExtent
.
height
)
height
=
surface_caps
.
minImageExtent
.
height
;
else
if
(
height
>
surface_caps
.
maxImageExtent
.
height
)
height
=
surface_caps
.
maxImageExtent
.
height
;
if
(
width
!=
desc
->
backbuffer_width
||
height
!=
desc
->
backbuffer_height
)
WARN
(
"Swapchain dimensions %ux%u are not supported (%u-%u x %u-%u).
\n
"
,
desc
->
backbuffer_width
,
desc
->
backbuffer_height
,
surface_caps
.
minImageExtent
.
width
,
surface_caps
.
maxImageExtent
.
width
,
surface_caps
.
minImageExtent
.
height
,
surface_caps
.
maxImageExtent
.
height
);
usage
=
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
;
usage
|=
surface_caps
.
supportedUsageFlags
&
VK_IMAGE_USAGE_TRANSFER_SRC_BIT
;
usage
|=
surface_caps
.
supportedUsageFlags
&
VK_IMAGE_USAGE_TRANSFER_DST_BIT
;
if
(
!
(
usage
&
VK_IMAGE_USAGE_TRANSFER_SRC_BIT
)
||
!
(
usage
&
VK_IMAGE_USAGE_TRANSFER_DST_BIT
))
WARN
(
"Transfer not supported for swapchain images.
\n
"
);
if
(
!
(
surface_caps
.
supportedCompositeAlpha
&
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
))
{
FIXME
(
"Unsupported alpha mode, %#x.
\n
"
,
surface_caps
.
supportedCompositeAlpha
);
goto
fail
;
}
vk_present_mode
=
VK_PRESENT_MODE_FIFO_KHR
;
if
(
!
swapchain_vk
->
s
.
swap_interval
)
{
if
(
wined3d_swapchain_vk_present_mode_supported
(
swapchain_vk
,
VK_PRESENT_MODE_IMMEDIATE_KHR
))
vk_present_mode
=
VK_PRESENT_MODE_IMMEDIATE_KHR
;
else
FIXME
(
"Unsupported swap interval %u.
\n
"
,
swapchain_vk
->
s
.
swap_interval
);
}
vk_swapchain_desc
.
sType
=
VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR
;
vk_swapchain_desc
.
pNext
=
NULL
;
vk_swapchain_desc
.
flags
=
0
;
vk_swapchain_desc
.
surface
=
vk_surface
;
vk_swapchain_desc
.
minImageCount
=
image_count
;
vk_swapchain_desc
.
imageFormat
=
vk_format
;
vk_swapchain_desc
.
imageColorSpace
=
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
;
vk_swapchain_desc
.
imageExtent
.
width
=
width
;
vk_swapchain_desc
.
imageExtent
.
height
=
height
;
vk_swapchain_desc
.
imageArrayLayers
=
1
;
vk_swapchain_desc
.
imageUsage
=
usage
;
vk_swapchain_desc
.
imageSharingMode
=
VK_SHARING_MODE_EXCLUSIVE
;
vk_swapchain_desc
.
queueFamilyIndexCount
=
0
;
vk_swapchain_desc
.
pQueueFamilyIndices
=
NULL
;
vk_swapchain_desc
.
preTransform
=
surface_caps
.
currentTransform
;
vk_swapchain_desc
.
compositeAlpha
=
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
;
vk_swapchain_desc
.
presentMode
=
vk_present_mode
;
vk_swapchain_desc
.
clipped
=
VK_TRUE
;
vk_swapchain_desc
.
oldSwapchain
=
VK_NULL_HANDLE
;
if
((
vr
=
VK_CALL
(
vkCreateSwapchainKHR
(
device_vk
->
vk_device
,
&
vk_swapchain_desc
,
NULL
,
&
vk_swapchain
)))
<
0
)
{
ERR
(
"Failed to create Vulkan swapchain, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
goto
fail
;
}
swapchain_vk
->
vk_swapchain
=
vk_swapchain
;
if
(
!
wined3d_swapchain_vk_create_vulkan_swapchain_images
(
swapchain_vk
,
vk_swapchain
))
{
VK_CALL
(
vkDestroySwapchainKHR
(
device_vk
->
vk_device
,
vk_swapchain
,
NULL
));
goto
fail
;
}
return
WINED3D_OK
;
fail:
VK_CALL
(
vkDestroySurfaceKHR
(
vk_info
->
instance
,
vk_surface
,
NULL
));
return
E_FAIL
;
}
static
HRESULT
wined3d_swapchain_vk_recreate
(
struct
wined3d_swapchain_vk
*
swapchain_vk
)
{
TRACE
(
"swapchain_vk %p.
\n
"
,
swapchain_vk
);
wined3d_swapchain_vk_destroy_vulkan_swapchain
(
swapchain_vk
);
return
wined3d_swapchain_vk_create_vulkan_swapchain
(
swapchain_vk
);
}
static
void
wined3d_swapchain_vk_set_swap_interval
(
struct
wined3d_swapchain_vk
*
swapchain_vk
,
unsigned
int
swap_interval
)
{
if
(
swap_interval
>
1
)
{
if
(
swap_interval
<=
4
)
FIXME
(
"Unsupported swap interval %u.
\n
"
,
swap_interval
);
swap_interval
=
1
;
}
if
(
swapchain_vk
->
s
.
swap_interval
==
swap_interval
)
return
;
swapchain_vk
->
s
.
swap_interval
=
swap_interval
;
wined3d_swapchain_vk_recreate
(
swapchain_vk
);
}
static
void
wined3d_swapchain_vk_blit
(
struct
wined3d_swapchain_vk
*
swapchain_vk
,
struct
wined3d_context_vk
*
context_vk
,
const
RECT
*
src_rect
,
const
RECT
*
dst_rect
,
unsigned
int
swap_interval
)
{
struct
wined3d_texture_vk
*
back_buffer_vk
=
wined3d_texture_vk
(
swapchain_vk
->
s
.
back_buffers
[
0
]);
struct
wined3d_device_vk
*
device_vk
=
wined3d_device_vk
(
swapchain_vk
->
s
.
device
);
const
struct
wined3d_swapchain_desc
*
desc
=
&
swapchain_vk
->
s
.
state
.
desc
;
const
struct
wined3d_vk_info
*
vk_info
=
context_vk
->
vk_info
;
VkCommandBuffer
vk_command_buffer
;
VkPresentInfoKHR
present_desc
;
unsigned
int
present_idx
;
VkImageLayout
vk_layout
;
uint32_t
image_idx
;
VkImageBlit
blit
;
VkResult
vr
;
HRESULT
hr
;
static
const
VkPipelineStageFlags
wait_stage
=
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
;
wined3d_swapchain_vk_set_swap_interval
(
swapchain_vk
,
swap_interval
);
present_idx
=
swapchain_vk
->
current
++
%
swapchain_vk
->
image_count
;
wined3d_context_vk_wait_command_buffer
(
context_vk
,
swapchain_vk
->
vk_semaphores
[
present_idx
].
command_buffer_id
);
vr
=
VK_CALL
(
vkAcquireNextImageKHR
(
device_vk
->
vk_device
,
swapchain_vk
->
vk_swapchain
,
UINT64_MAX
,
swapchain_vk
->
vk_semaphores
[
present_idx
].
available
,
VK_NULL_HANDLE
,
&
image_idx
));
if
(
vr
==
VK_ERROR_OUT_OF_DATE_KHR
)
{
if
(
FAILED
(
hr
=
wined3d_swapchain_vk_recreate
(
swapchain_vk
)))
{
ERR
(
"Failed to recreate swapchain, hr %#x.
\n
"
,
hr
);
return
;
}
vr
=
VK_CALL
(
vkAcquireNextImageKHR
(
device_vk
->
vk_device
,
swapchain_vk
->
vk_swapchain
,
UINT64_MAX
,
swapchain_vk
->
vk_semaphores
[
present_idx
].
available
,
VK_NULL_HANDLE
,
&
image_idx
));
}
if
(
vr
<
0
)
{
ERR
(
"Failed to acquire next Vulkan image, vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
return
;
}
vk_command_buffer
=
wined3d_context_vk_get_command_buffer
(
context_vk
);
wined3d_context_vk_end_current_render_pass
(
context_vk
);
wined3d_context_vk_image_barrier
(
context_vk
,
vk_command_buffer
,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
VK_PIPELINE_STAGE_TRANSFER_BIT
,
vk_access_mask_from_bind_flags
(
back_buffer_vk
->
t
.
resource
.
bind_flags
),
VK_ACCESS_TRANSFER_READ_BIT
,
back_buffer_vk
->
layout
,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
back_buffer_vk
->
vk_image
,
VK_IMAGE_ASPECT_COLOR_BIT
);
wined3d_context_vk_image_barrier
(
context_vk
,
vk_command_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
,
swapchain_vk
->
vk_images
[
image_idx
],
VK_IMAGE_ASPECT_COLOR_BIT
);
blit
.
srcSubresource
.
aspectMask
=
VK_IMAGE_ASPECT_COLOR_BIT
;
blit
.
srcSubresource
.
mipLevel
=
0
;
blit
.
srcSubresource
.
baseArrayLayer
=
0
;
blit
.
srcSubresource
.
layerCount
=
1
;
blit
.
srcOffsets
[
0
].
x
=
src_rect
->
left
;
blit
.
srcOffsets
[
0
].
y
=
src_rect
->
top
;
blit
.
srcOffsets
[
0
].
z
=
0
;
blit
.
srcOffsets
[
1
].
x
=
src_rect
->
right
;
blit
.
srcOffsets
[
1
].
y
=
src_rect
->
bottom
;
blit
.
srcOffsets
[
1
].
z
=
1
;
blit
.
dstSubresource
=
blit
.
srcSubresource
;
blit
.
dstOffsets
[
0
].
x
=
dst_rect
->
left
;
blit
.
dstOffsets
[
0
].
y
=
dst_rect
->
top
;
blit
.
dstOffsets
[
0
].
z
=
0
;
blit
.
dstOffsets
[
1
].
x
=
dst_rect
->
right
;
blit
.
dstOffsets
[
1
].
y
=
dst_rect
->
bottom
;
blit
.
dstOffsets
[
1
].
z
=
1
;
VK_CALL
(
vkCmdBlitImage
(
vk_command_buffer
,
back_buffer_vk
->
vk_image
,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
swapchain_vk
->
vk_images
[
image_idx
],
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
,
1
,
&
blit
,
VK_FILTER_NEAREST
));
wined3d_context_vk_image_barrier
(
context_vk
,
vk_command_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
,
swapchain_vk
->
vk_images
[
image_idx
],
VK_IMAGE_ASPECT_COLOR_BIT
);
if
(
desc
->
swap_effect
==
WINED3D_SWAP_EFFECT_DISCARD
||
desc
->
swap_effect
==
WINED3D_SWAP_EFFECT_FLIP_DISCARD
)
vk_layout
=
VK_IMAGE_LAYOUT_UNDEFINED
;
else
vk_layout
=
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
;
wined3d_context_vk_image_barrier
(
context_vk
,
vk_command_buffer
,
VK_PIPELINE_STAGE_TRANSFER_BIT
,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
VK_ACCESS_TRANSFER_READ_BIT
,
vk_access_mask_from_bind_flags
(
back_buffer_vk
->
t
.
resource
.
bind_flags
),
vk_layout
,
back_buffer_vk
->
layout
,
back_buffer_vk
->
vk_image
,
VK_IMAGE_ASPECT_COLOR_BIT
);
swapchain_vk
->
vk_semaphores
[
present_idx
].
command_buffer_id
=
context_vk
->
current_command_buffer
.
id
;
wined3d_context_vk_submit_command_buffer
(
context_vk
,
1
,
&
swapchain_vk
->
vk_semaphores
[
present_idx
].
available
,
&
wait_stage
,
1
,
&
swapchain_vk
->
vk_semaphores
[
present_idx
].
presentable
);
present_desc
.
sType
=
VK_STRUCTURE_TYPE_PRESENT_INFO_KHR
;
present_desc
.
pNext
=
NULL
;
present_desc
.
waitSemaphoreCount
=
1
;
present_desc
.
pWaitSemaphores
=
&
swapchain_vk
->
vk_semaphores
[
present_idx
].
presentable
;
present_desc
.
swapchainCount
=
1
;
present_desc
.
pSwapchains
=
&
swapchain_vk
->
vk_swapchain
;
present_desc
.
pImageIndices
=
&
image_idx
;
present_desc
.
pResults
=
NULL
;
if
((
vr
=
VK_CALL
(
vkQueuePresentKHR
(
device_vk
->
vk_queue
,
&
present_desc
))))
ERR
(
"Present returned vr %s.
\n
"
,
wined3d_debug_vkresult
(
vr
));
}
static
void
wined3d_swapchain_vk_rotate
(
struct
wined3d_swapchain
*
swapchain
,
struct
wined3d_context_vk
*
context_vk
)
{
struct
wined3d_texture_sub_resource
*
sub_resource
;
struct
wined3d_texture_vk
*
texture
,
*
texture_prev
;
struct
wined3d_allocator_block
*
memory0
;
VkDescriptorImageInfo
vk_info0
;
VkDeviceMemory
vk_memory0
;
VkImageLayout
vk_layout0
;
VkImage
vk_image0
;
DWORD
locations0
;
unsigned
int
i
;
uint64_t
id0
;
static
const
DWORD
supported_locations
=
WINED3D_LOCATION_TEXTURE_RGB
|
WINED3D_LOCATION_RB_MULTISAMPLE
;
if
(
swapchain
->
state
.
desc
.
backbuffer_count
<
2
)
return
;
texture_prev
=
wined3d_texture_vk
(
swapchain
->
back_buffers
[
0
]);
/* Back buffer 0 is already in the draw binding. */
vk_image0
=
texture_prev
->
vk_image
;
memory0
=
texture_prev
->
memory
;
vk_memory0
=
texture_prev
->
vk_memory
;
vk_layout0
=
texture_prev
->
layout
;
id0
=
texture_prev
->
command_buffer_id
;
vk_info0
=
texture_prev
->
default_image_info
;
locations0
=
texture_prev
->
t
.
sub_resources
[
0
].
locations
;
for
(
i
=
1
;
i
<
swapchain
->
state
.
desc
.
backbuffer_count
;
++
i
)
{
texture
=
wined3d_texture_vk
(
swapchain
->
back_buffers
[
i
]);
sub_resource
=
&
texture
->
t
.
sub_resources
[
0
];
if
(
!
(
sub_resource
->
locations
&
supported_locations
))
wined3d_texture_load_location
(
&
texture
->
t
,
0
,
&
context_vk
->
c
,
texture
->
t
.
resource
.
draw_binding
);
texture_prev
->
vk_image
=
texture
->
vk_image
;
texture_prev
->
memory
=
texture
->
memory
;
texture_prev
->
vk_memory
=
texture
->
vk_memory
;
texture_prev
->
layout
=
texture
->
layout
;
texture_prev
->
command_buffer_id
=
texture
->
command_buffer_id
;
texture_prev
->
default_image_info
=
texture
->
default_image_info
;
wined3d_texture_validate_location
(
&
texture_prev
->
t
,
0
,
sub_resource
->
locations
&
supported_locations
);
wined3d_texture_invalidate_location
(
&
texture_prev
->
t
,
0
,
~
(
sub_resource
->
locations
&
supported_locations
));
texture_prev
=
texture
;
}
texture_prev
->
vk_image
=
vk_image0
;
texture_prev
->
memory
=
memory0
;
texture_prev
->
vk_memory
=
vk_memory0
;
texture_prev
->
layout
=
vk_layout0
;
texture_prev
->
command_buffer_id
=
id0
;
texture_prev
->
default_image_info
=
vk_info0
;
wined3d_texture_validate_location
(
&
texture_prev
->
t
,
0
,
locations0
&
supported_locations
);
wined3d_texture_invalidate_location
(
&
texture_prev
->
t
,
0
,
~
(
locations0
&
supported_locations
));
device_invalidate_state
(
swapchain
->
device
,
STATE_FRAMEBUFFER
);
}
static
void
swapchain_vk_present
(
struct
wined3d_swapchain
*
swapchain
,
const
RECT
*
src_rect
,
const
RECT
*
dst_rect
,
unsigned
int
swap_interval
,
uint32_t
flags
)
{
FIXME
(
"Not implemented.
\n
"
);
struct
wined3d_swapchain_vk
*
swapchain_vk
=
wined3d_swapchain_vk
(
swapchain
);
struct
wined3d_texture
*
back_buffer
=
swapchain
->
back_buffers
[
0
];
struct
wined3d_context_vk
*
context_vk
;
context_vk
=
wined3d_context_vk
(
context_acquire
(
swapchain
->
device
,
back_buffer
,
0
));
wined3d_texture_load_location
(
back_buffer
,
0
,
&
context_vk
->
c
,
back_buffer
->
resource
.
draw_binding
);
if
(
swapchain_vk
->
vk_swapchain
)
wined3d_swapchain_vk_blit
(
swapchain_vk
,
context_vk
,
src_rect
,
dst_rect
,
swap_interval
);
wined3d_swapchain_vk_rotate
(
swapchain
,
context_vk
);
wined3d_texture_validate_location
(
swapchain
->
front_buffer
,
0
,
WINED3D_LOCATION_DRAWABLE
);
wined3d_texture_invalidate_location
(
swapchain
->
front_buffer
,
0
,
~
WINED3D_LOCATION_DRAWABLE
);
TRACE
(
"Starting new frame.
\n
"
);
context_release
(
&
context_vk
->
c
);
}
static
const
struct
wined3d_swapchain_ops
swapchain_vk_ops
=
...
...
@@ -994,13 +1584,30 @@ HRESULT wined3d_swapchain_gl_init(struct wined3d_swapchain_gl *swapchain_gl, str
return
hr
;
}
HRESULT
wined3d_swapchain_vk_init
(
struct
wined3d_swapchain
*
swapchain_vk
,
struct
wined3d_device
*
device
,
HRESULT
wined3d_swapchain_vk_init
(
struct
wined3d_swapchain
_vk
*
swapchain_vk
,
struct
wined3d_device
*
device
,
struct
wined3d_swapchain_desc
*
desc
,
void
*
parent
,
const
struct
wined3d_parent_ops
*
parent_ops
)
{
HRESULT
hr
;
TRACE
(
"swapchain_vk %p, device %p, desc %p, parent %p, parent_ops %p.
\n
"
,
swapchain_vk
,
device
,
desc
,
parent
,
parent_ops
);
return
wined3d_swapchain_init
(
swapchain_vk
,
device
,
desc
,
parent
,
parent_ops
,
&
swapchain_vk_ops
);
if
(
FAILED
(
hr
=
wined3d_swapchain_init
(
&
swapchain_vk
->
s
,
device
,
desc
,
parent
,
parent_ops
,
&
swapchain_vk_ops
)))
return
hr
;
if
(
swapchain_vk
->
s
.
win_handle
==
GetDesktopWindow
())
{
WARN
(
"Creating a desktop window swapchain.
\n
"
);
return
hr
;
}
if
(
FAILED
(
hr
=
wined3d_swapchain_vk_create_vulkan_swapchain
(
swapchain_vk
)))
{
wined3d_swapchain_cleanup
(
&
swapchain_vk
->
s
);
return
hr
;
}
return
hr
;
}
HRESULT
CDECL
wined3d_swapchain_create
(
struct
wined3d_device
*
device
,
struct
wined3d_swapchain_desc
*
desc
,
...
...
dlls/wined3d/wined3d_private.h
View file @
9aeef376
...
...
@@ -5084,7 +5084,29 @@ HRESULT wined3d_swapchain_gl_init(struct wined3d_swapchain_gl *swapchain_gl,
struct
wined3d_device
*
device
,
struct
wined3d_swapchain_desc
*
desc
,
void
*
parent
,
const
struct
wined3d_parent_ops
*
parent_ops
)
DECLSPEC_HIDDEN
;
HRESULT
wined3d_swapchain_vk_init
(
struct
wined3d_swapchain
*
swapchain_vk
,
struct
wined3d_swapchain_vk
{
struct
wined3d_swapchain
s
;
VkSwapchainKHR
vk_swapchain
;
VkSurfaceKHR
vk_surface
;
VkImage
*
vk_images
;
struct
{
VkSemaphore
available
;
VkSemaphore
presentable
;
uint64_t
command_buffer_id
;
}
*
vk_semaphores
;
unsigned
int
current
,
image_count
;
};
static
inline
struct
wined3d_swapchain_vk
*
wined3d_swapchain_vk
(
struct
wined3d_swapchain
*
swapchain
)
{
return
CONTAINING_RECORD
(
swapchain
,
struct
wined3d_swapchain_vk
,
s
);
}
void
wined3d_swapchain_vk_cleanup
(
struct
wined3d_swapchain_vk
*
swapchain_vk
)
DECLSPEC_HIDDEN
;
HRESULT
wined3d_swapchain_vk_init
(
struct
wined3d_swapchain_vk
*
swapchain_vk
,
struct
wined3d_device
*
device
,
struct
wined3d_swapchain_desc
*
desc
,
void
*
parent
,
const
struct
wined3d_parent_ops
*
parent_ops
)
DECLSPEC_HIDDEN
;
...
...
dlls/wined3d/wined3d_vk.h
View file @
9aeef376
...
...
@@ -41,7 +41,15 @@
VK_INSTANCE_PFN(vkGetPhysicalDeviceSparseImageFormatProperties) \
/* Vulkan 1.1 */
\
VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceFeatures2) \
VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceProperties2)
VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceProperties2) \
/* VK_KHR_surface */
\
VK_INSTANCE_PFN(vkDestroySurfaceKHR) \
VK_INSTANCE_PFN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \
VK_INSTANCE_PFN(vkGetPhysicalDeviceSurfaceFormatsKHR) \
VK_INSTANCE_PFN(vkGetPhysicalDeviceSurfacePresentModesKHR) \
VK_INSTANCE_PFN(vkGetPhysicalDeviceSurfaceSupportKHR) \
/* VK_KHR_win32_surface */
\
VK_INSTANCE_PFN(vkCreateWin32SurfaceKHR)
#define VK_DEVICE_FUNCS() \
VK_DEVICE_PFN(vkAllocateCommandBuffers) \
...
...
@@ -163,7 +171,13 @@
VK_DEVICE_PFN(vkSetEvent) \
VK_DEVICE_PFN(vkUnmapMemory) \
VK_DEVICE_PFN(vkUpdateDescriptorSets) \
VK_DEVICE_PFN(vkWaitForFences)
VK_DEVICE_PFN(vkWaitForFences) \
/* VK_KHR_swapchain */
\
VK_DEVICE_PFN(vkAcquireNextImageKHR) \
VK_DEVICE_PFN(vkCreateSwapchainKHR) \
VK_DEVICE_PFN(vkDestroySwapchainKHR) \
VK_DEVICE_PFN(vkGetSwapchainImagesKHR) \
VK_DEVICE_PFN(vkQueuePresentKHR)
#define DECLARE_VK_PFN(name) PFN_##name name;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment