2 * Copyright © 2017 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 #include "wsi_common_private.h"
25 #include "util/macros.h"
28 wsi_device_init(struct wsi_device
*wsi
,
29 VkPhysicalDevice pdevice
,
30 WSI_FN_GetPhysicalDeviceProcAddr proc_addr
)
32 memset(wsi
, 0, sizeof(*wsi
));
34 #define WSI_GET_CB(func) \
35 PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
36 WSI_GET_CB(GetPhysicalDeviceMemoryProperties
);
37 WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties
);
40 GetPhysicalDeviceMemoryProperties(pdevice
, &wsi
->memory_props
);
41 GetPhysicalDeviceQueueFamilyProperties(pdevice
, &wsi
->queue_family_count
, NULL
);
43 #define WSI_GET_CB(func) \
44 wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
45 WSI_GET_CB(AllocateMemory
);
46 WSI_GET_CB(AllocateCommandBuffers
);
47 WSI_GET_CB(BindBufferMemory
);
48 WSI_GET_CB(BindImageMemory
);
49 WSI_GET_CB(BeginCommandBuffer
);
50 WSI_GET_CB(CmdCopyImageToBuffer
);
51 WSI_GET_CB(CreateBuffer
);
52 WSI_GET_CB(CreateCommandPool
);
53 WSI_GET_CB(CreateImage
);
54 WSI_GET_CB(DestroyBuffer
);
55 WSI_GET_CB(DestroyCommandPool
);
56 WSI_GET_CB(DestroyImage
);
57 WSI_GET_CB(EndCommandBuffer
);
58 WSI_GET_CB(FreeMemory
);
59 WSI_GET_CB(FreeCommandBuffers
);
60 WSI_GET_CB(GetBufferMemoryRequirements
);
61 WSI_GET_CB(GetImageMemoryRequirements
);
62 WSI_GET_CB(GetMemoryFdKHR
);
63 WSI_GET_CB(QueueSubmit
);
68 wsi_swapchain_init(const struct wsi_device
*wsi
,
69 struct wsi_swapchain
*chain
,
71 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
72 const VkAllocationCallbacks
*pAllocator
)
76 memset(chain
, 0, sizeof(*chain
));
79 chain
->device
= device
;
80 chain
->alloc
= *pAllocator
;
83 vk_zalloc(pAllocator
, sizeof(VkCommandPool
) * wsi
->queue_family_count
, 8,
84 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
85 if (!chain
->cmd_pools
)
86 return VK_ERROR_OUT_OF_HOST_MEMORY
;
88 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
89 const VkCommandPoolCreateInfo cmd_pool_info
= {
90 .sType
= VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
,
93 .queueFamilyIndex
= i
,
95 result
= wsi
->CreateCommandPool(device
, &cmd_pool_info
, &chain
->alloc
,
96 &chain
->cmd_pools
[i
]);
97 if (result
!= VK_SUCCESS
)
104 wsi_swapchain_finish(chain
);
109 wsi_swapchain_finish(struct wsi_swapchain
*chain
)
111 for (uint32_t i
= 0; i
< chain
->wsi
->queue_family_count
; i
++) {
112 chain
->wsi
->DestroyCommandPool(chain
->device
, chain
->cmd_pools
[i
],
118 select_memory_type(const struct wsi_device
*wsi
,
119 VkMemoryPropertyFlags props
,
122 for (uint32_t i
= 0; i
< wsi
->memory_props
.memoryTypeCount
; i
++) {
123 const VkMemoryType type
= wsi
->memory_props
.memoryTypes
[i
];
124 if ((type_bits
& (1 << i
)) && (type
.propertyFlags
& props
) == props
)
128 unreachable("No memory type found");
132 vk_format_size(VkFormat format
)
135 case VK_FORMAT_B8G8R8A8_UNORM
:
136 case VK_FORMAT_B8G8R8A8_SRGB
:
139 unreachable("Unknown WSI Format");
143 static inline uint32_t
144 align_u32(uint32_t v
, uint32_t a
)
146 assert(a
!= 0 && a
== (a
& -a
));
147 return (v
+ a
- 1) & ~(a
- 1);
150 #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
153 wsi_create_prime_image(const struct wsi_swapchain
*chain
,
154 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
155 struct wsi_image
*image
)
157 const struct wsi_device
*wsi
= chain
->wsi
;
160 memset(image
, 0, sizeof(*image
));
162 const uint32_t cpp
= vk_format_size(pCreateInfo
->imageFormat
);
163 const uint32_t linear_stride
= align_u32(pCreateInfo
->imageExtent
.width
* cpp
,
164 WSI_PRIME_LINEAR_STRIDE_ALIGN
);
166 uint32_t linear_size
= linear_stride
* pCreateInfo
->imageExtent
.height
;
167 linear_size
= align_u32(linear_size
, 4096);
169 const VkExternalMemoryBufferCreateInfoKHR prime_buffer_external_info
= {
170 .sType
= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR
,
172 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
174 const VkBufferCreateInfo prime_buffer_info
= {
175 .sType
= VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
,
176 .pNext
= &prime_buffer_external_info
,
178 .usage
= VK_BUFFER_USAGE_TRANSFER_DST_BIT
,
179 .sharingMode
= VK_SHARING_MODE_EXCLUSIVE
,
181 result
= wsi
->CreateBuffer(chain
->device
, &prime_buffer_info
,
182 &chain
->alloc
, &image
->prime
.buffer
);
183 if (result
!= VK_SUCCESS
)
186 VkMemoryRequirements reqs
;
187 wsi
->GetBufferMemoryRequirements(chain
->device
, image
->prime
.buffer
, &reqs
);
188 assert(reqs
.size
<= linear_size
);
190 const struct wsi_memory_allocate_info memory_wsi_info
= {
191 .sType
= VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA
,
193 .implicit_sync
= true,
195 const VkExportMemoryAllocateInfoKHR prime_memory_export_info
= {
196 .sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR
,
197 .pNext
= &memory_wsi_info
,
198 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
200 const VkMemoryDedicatedAllocateInfoKHR prime_memory_dedicated_info
= {
201 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR
,
202 .pNext
= &prime_memory_export_info
,
203 .image
= VK_NULL_HANDLE
,
204 .buffer
= image
->prime
.buffer
,
206 const VkMemoryAllocateInfo prime_memory_info
= {
207 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
208 .pNext
= &prime_memory_dedicated_info
,
209 .allocationSize
= linear_size
,
210 .memoryTypeIndex
= select_memory_type(wsi
, 0, reqs
.memoryTypeBits
),
212 result
= wsi
->AllocateMemory(chain
->device
, &prime_memory_info
,
213 &chain
->alloc
, &image
->prime
.memory
);
214 if (result
!= VK_SUCCESS
)
217 result
= wsi
->BindBufferMemory(chain
->device
, image
->prime
.buffer
,
218 image
->prime
.memory
, 0);
219 if (result
!= VK_SUCCESS
)
222 const VkImageCreateInfo image_info
= {
223 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
226 .imageType
= VK_IMAGE_TYPE_2D
,
227 .format
= pCreateInfo
->imageFormat
,
229 .width
= pCreateInfo
->imageExtent
.width
,
230 .height
= pCreateInfo
->imageExtent
.height
,
235 .samples
= VK_SAMPLE_COUNT_1_BIT
,
236 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
237 .usage
= pCreateInfo
->imageUsage
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
,
238 .sharingMode
= pCreateInfo
->imageSharingMode
,
239 .queueFamilyIndexCount
= pCreateInfo
->queueFamilyIndexCount
,
240 .pQueueFamilyIndices
= pCreateInfo
->pQueueFamilyIndices
,
241 .initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
,
243 result
= wsi
->CreateImage(chain
->device
, &image_info
,
244 &chain
->alloc
, &image
->image
);
245 if (result
!= VK_SUCCESS
)
248 wsi
->GetImageMemoryRequirements(chain
->device
, image
->image
, &reqs
);
250 const VkMemoryDedicatedAllocateInfoKHR memory_dedicated_info
= {
251 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR
,
253 .image
= image
->image
,
254 .buffer
= VK_NULL_HANDLE
,
256 const VkMemoryAllocateInfo memory_info
= {
257 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
258 .pNext
= &memory_dedicated_info
,
259 .allocationSize
= reqs
.size
,
260 .memoryTypeIndex
= select_memory_type(wsi
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
,
261 reqs
.memoryTypeBits
),
263 result
= wsi
->AllocateMemory(chain
->device
, &memory_info
,
264 &chain
->alloc
, &image
->memory
);
265 if (result
!= VK_SUCCESS
)
268 result
= wsi
->BindImageMemory(chain
->device
, image
->image
,
270 if (result
!= VK_SUCCESS
)
273 image
->prime
.blit_cmd_buffers
=
274 vk_zalloc(&chain
->alloc
,
275 sizeof(VkCommandBuffer
) * wsi
->queue_family_count
, 8,
276 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
277 if (!image
->prime
.blit_cmd_buffers
)
280 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
281 const VkCommandBufferAllocateInfo cmd_buffer_info
= {
282 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
,
284 .commandPool
= chain
->cmd_pools
[i
],
285 .level
= VK_COMMAND_BUFFER_LEVEL_PRIMARY
,
286 .commandBufferCount
= 1,
288 result
= wsi
->AllocateCommandBuffers(chain
->device
, &cmd_buffer_info
,
289 &image
->prime
.blit_cmd_buffers
[i
]);
290 if (result
!= VK_SUCCESS
)
293 const VkCommandBufferBeginInfo begin_info
= {
294 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
,
296 wsi
->BeginCommandBuffer(image
->prime
.blit_cmd_buffers
[i
], &begin_info
);
298 struct VkBufferImageCopy buffer_image_copy
= {
300 .bufferRowLength
= linear_stride
/ cpp
,
301 .bufferImageHeight
= 0,
302 .imageSubresource
= {
303 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
308 .imageOffset
= { .x
= 0, .y
= 0, .z
= 0 },
310 .width
= pCreateInfo
->imageExtent
.width
,
311 .height
= pCreateInfo
->imageExtent
.height
,
315 wsi
->CmdCopyImageToBuffer(image
->prime
.blit_cmd_buffers
[i
],
317 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
,
319 1, &buffer_image_copy
);
321 result
= wsi
->EndCommandBuffer(image
->prime
.blit_cmd_buffers
[i
]);
322 if (result
!= VK_SUCCESS
)
326 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info
= {
327 .sType
= VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR
,
329 .memory
= image
->prime
.memory
,
330 .handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
333 result
= wsi
->GetMemoryFdKHR(chain
->device
, &linear_memory_get_fd_info
, &fd
);
334 if (result
!= VK_SUCCESS
)
337 image
->size
= linear_size
;
338 image
->row_pitch
= linear_stride
;
345 wsi_destroy_prime_image(chain
, image
);
351 wsi_destroy_prime_image(const struct wsi_swapchain
*chain
,
352 struct wsi_image
*image
)
354 const struct wsi_device
*wsi
= chain
->wsi
;
356 if (image
->prime
.blit_cmd_buffers
) {
357 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
358 wsi
->FreeCommandBuffers(chain
->device
, chain
->cmd_pools
[i
],
359 1, &image
->prime
.blit_cmd_buffers
[i
]);
361 vk_free(&chain
->alloc
, image
->prime
.blit_cmd_buffers
);
364 wsi
->FreeMemory(chain
->device
, image
->memory
, &chain
->alloc
);
365 wsi
->DestroyImage(chain
->device
, image
->image
, &chain
->alloc
);
366 wsi
->FreeMemory(chain
->device
, image
->prime
.memory
, &chain
->alloc
);
367 wsi
->DestroyBuffer(chain
->device
, image
->prime
.buffer
, &chain
->alloc
);
371 wsi_prime_image_blit_to_linear(const struct wsi_swapchain
*chain
,
372 struct wsi_image
*image
,
374 uint32_t waitSemaphoreCount
,
375 const VkSemaphore
*pWaitSemaphores
)
377 uint32_t queue_family
= chain
->wsi
->queue_get_family_index(queue
);
379 VkPipelineStageFlags stage_flags
= VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
;
380 const VkSubmitInfo submit_info
= {
381 .sType
= VK_STRUCTURE_TYPE_SUBMIT_INFO
,
383 .waitSemaphoreCount
= waitSemaphoreCount
,
384 .pWaitSemaphores
= pWaitSemaphores
,
385 .pWaitDstStageMask
= &stage_flags
,
386 .commandBufferCount
= 1,
387 .pCommandBuffers
= &image
->prime
.blit_cmd_buffers
[queue_family
],
388 .signalSemaphoreCount
= 0,
389 .pSignalSemaphores
= NULL
,
391 return chain
->wsi
->QueueSubmit(queue
, 1, &submit_info
, VK_NULL_HANDLE
);