8 #include <vulkan/vulkan.h>
10 #include "swapchain_base_tizen.hpp"
12 #if VULKAN_WSI_DEBUG > 0
13 #define WSI_PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__)
15 #define WSI_PRINT_ERROR(...) (void)0
21 swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAllocationCallbacks *callbacks)
22 : m_device_data(dev_data)
23 , m_allocator(callbacks, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)
24 , m_swapchain_images(m_allocator)
25 , m_surface(VK_NULL_HANDLE)
26 , m_present_mode(VK_PRESENT_MODE_IMMEDIATE_KHR)
27 , m_descendant(VK_NULL_HANDLE)
28 , m_ancestor(VK_NULL_HANDLE)
29 , m_device(VK_NULL_HANDLE)
30 , m_queue(VK_NULL_HANDLE)
34 VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info)
36 assert(device != VK_NULL_HANDLE);
37 assert(swapchain_create_info != nullptr);
38 assert(swapchain_create_info->surface != VK_NULL_HANDLE);
43 m_surface = swapchain_create_info->surface;
45 /* We have allocated images, we can call the platform init function if something needs to be done. */
46 result = init_platform(device, swapchain_create_info);
47 if (result != VK_SUCCESS)
52 VkImageCreateInfo image_create_info = {};
53 image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
54 image_create_info.pNext = nullptr;
55 image_create_info.imageType = VK_IMAGE_TYPE_2D;
56 image_create_info.format = swapchain_create_info->imageFormat;
57 image_create_info.extent = { swapchain_create_info->imageExtent.width, swapchain_create_info->imageExtent.height, 1 };
58 image_create_info.mipLevels = 1;
59 image_create_info.arrayLayers = swapchain_create_info->imageArrayLayers;
60 image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
61 image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
62 image_create_info.usage = swapchain_create_info->imageUsage;
63 image_create_info.flags = 0;
64 image_create_info.sharingMode = swapchain_create_info->imageSharingMode;
65 image_create_info.queueFamilyIndexCount = swapchain_create_info->queueFamilyIndexCount;
66 image_create_info.pQueueFamilyIndices = swapchain_create_info->pQueueFamilyIndices;
67 image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
69 result = create_image(image_create_info);
70 if (result != VK_SUCCESS)
75 m_device_data.disp.GetDeviceQueue(m_device, 0, 0, &m_queue);
76 result = m_device_data.SetDeviceLoaderData(m_device, m_queue);
77 if (VK_SUCCESS != result)
82 if (swapchain_create_info->oldSwapchain != VK_NULL_HANDLE)
84 /* TO BE DONE - How to reuse the old swapchain */
86 m_ancestor = swapchain_create_info->oldSwapchain;
88 auto *ancestor = reinterpret_cast<swapchain_base *>(m_ancestor);
89 ancestor->deprecate(reinterpret_cast<VkSwapchainKHR>(this));
96 void swapchain_base::teardown()
98 if (m_queue != VK_NULL_HANDLE)
100 /* Make sure the vkFences are done signaling. */
101 m_device_data.disp.QueueWaitIdle(m_queue);
105 VkResult swapchain_base::acquire_next_image(uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *image_index)
109 retval = acquire_image(image_index);
110 if (retval != VK_SUCCESS)
113 if (VK_NULL_HANDLE != semaphore || VK_NULL_HANDLE != fence)
115 VkSubmitInfo submit = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
117 if (VK_NULL_HANDLE != semaphore)
119 submit.signalSemaphoreCount = 1;
120 submit.pSignalSemaphores = &semaphore;
123 submit.commandBufferCount = 0;
124 submit.pCommandBuffers = nullptr;
125 retval = m_device_data.disp.QueueSubmit(m_queue, 1, &submit, fence);
126 assert(retval == VK_SUCCESS);
132 VkResult swapchain_base::get_swapchain_images(uint32_t *swapchain_image_count, VkImage *swapchain_images)
134 if (swapchain_images == nullptr)
136 /* Return the number of swapchain images. */
137 *swapchain_image_count = m_swapchain_images.size();
143 assert(m_swapchain_images.size() > 0);
144 assert(*swapchain_image_count > 0);
146 /* Populate array, write actual number of images returned. */
147 uint32_t current_image = 0;
151 swapchain_images[current_image] = m_swapchain_images[current_image].image;
155 if (current_image == m_swapchain_images.size())
157 *swapchain_image_count = current_image;
162 } while (current_image < *swapchain_image_count);
164 /* If swapchain_image_count is smaller than the number of presentable images
165 * in the swapchain, VK_INCOMPLETE must be returned instead of VK_SUCCESS. */
166 *swapchain_image_count = current_image;
168 return VK_INCOMPLETE;
172 VkResult swapchain_base::queue_present(VkQueue queue, const VkPresentInfoKHR *present_info, const uint32_t image_index)
176 /* When the semaphore that comes in is signalled, we know that all work is done. So, we do not
177 * want to block any future Vulkan queue work on it. So, we pass in BOTTOM_OF_PIPE bit as the
180 VkPipelineStageFlags pipeline_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
182 VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO,
184 present_info->waitSemaphoreCount,
185 present_info->pWaitSemaphores,
186 &pipeline_stage_flags,
192 result = m_device_data.disp.ResetFences(m_device, 1, &m_swapchain_images[image_index].present_fence);
193 if (result != VK_SUCCESS)
198 result = m_device_data.disp.QueueSubmit(queue, 1, &submit_info, m_swapchain_images[image_index].present_fence);
199 if (result != VK_SUCCESS)
204 present_image(image_index);
209 void swapchain_base::deprecate(VkSwapchainKHR descendant)
211 // TO BE DONE - release old swapchain resources
214 void swapchain_base::clear_ancestor()
216 m_ancestor = VK_NULL_HANDLE;
219 void swapchain_base::clear_descendant()
221 m_descendant = VK_NULL_HANDLE;
224 #undef WSI_PRINT_ERROR
226 } /* namespace wsi */