assert(create_info.pQueueCreateInfos[0].queueCount == 1);
return std::make_unique<Vulkan_device>(physical_device, enabled_features, extensions);
}
+
+std::unique_ptr<Vulkan_semaphore> Vulkan_semaphore::create(Vulkan_device &device,
+ const VkSemaphoreCreateInfo &create_info)
+{
+ assert(create_info.sType == VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO);
+ assert(create_info.flags == 0);
+ return std::make_unique<Vulkan_semaphore>();
+}
+
+std::unique_ptr<Vulkan_image> Vulkan_image::create(Vulkan_device &device, const VkImageCreateInfo &create_info)
+{
+#warning finish implementing Vulkan_image::create
+ return std::make_unique<Vulkan_image>();
+}
}
}
KHR_surface,
KHR_xcb_surface,
KHR_xlib_surface,
+ KHR_swapchain,
};
kazan_util_generate_enum_traits(Supported_extension,
Supported_extension::Not_supported,
Supported_extension::KHR_surface,
Supported_extension::KHR_xcb_surface,
- Supported_extension::KHR_xlib_surface);
+ Supported_extension::KHR_xlib_surface,
+ Supported_extension::KHR_swapchain);
typedef util::Enum_set<Supported_extension> Supported_extensions;
#else
return Extension_scope::Not_supported;
#endif
+ case Supported_extension::KHR_swapchain:
+ return Extension_scope::Device;
}
assert(!"unknown extension");
return Extension_scope::Not_supported;
#else
return {};
#endif
+ case Supported_extension::KHR_swapchain:
+ return {
+ .extensionName = VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+ .specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION,
+ };
}
assert(!"unknown extension");
return {};
return {Supported_extension::KHR_surface};
case Supported_extension::KHR_xlib_surface:
return {Supported_extension::KHR_surface};
+ case Supported_extension::KHR_swapchain:
+ return {Supported_extension::KHR_surface};
}
assert(!"unknown extension");
return {};
}
};
+template <typename Object_type, typename Vulkan_handle_type>
+struct Vulkan_nondispatchable_object
+{
+ typedef Vulkan_handle_type Vulkan_handle;
+ typedef Object_type Object;
+ static Object_type *from_handle(Vulkan_handle_type v) noexcept
+ {
+ return static_cast<Object_type *>(reinterpret_cast<Vulkan_nondispatchable_object *>(v));
+ }
+ static std::unique_ptr<Object_type> move_from_handle(Vulkan_handle_type v) noexcept
+ {
+ return std::unique_ptr<Object_type>(from_handle(v));
+ }
+};
+
template <typename Object_type>
typename std::
enable_if<std::is_base_of<Vulkan_dispatchable_object<Object_type,
return to_handle(v.release());
}
+template <typename Object_type, typename = void>
+typename std::
+ enable_if<std::is_base_of<Vulkan_nondispatchable_object<Object_type,
+ typename Object_type::Vulkan_handle>,
+ Object_type>::value,
+ typename Object_type::Vulkan_handle>::type
+ to_handle(Object_type *object) noexcept
+{
+ return reinterpret_cast<typename Object_type::Vulkan_handle>(
+ static_cast<Vulkan_nondispatchable_object<Object_type, typename Object_type::Vulkan_handle>
+ *>(object));
+}
+
struct Vulkan_instance;
struct Vulkan_physical_device
struct Vulkan_device : public Vulkan_dispatchable_object<Vulkan_device, VkDevice>
{
- struct Queue
+ struct Queue : public Vulkan_dispatchable_object<Queue, VkQueue>
{
+ Vulkan_instance &instance;
+ Vulkan_physical_device &physical_device;
+ Vulkan_device &device;
+ explicit Queue(Vulkan_device &device) noexcept : instance(device.instance),
+ physical_device(device.physical_device),
+ device(device)
+ {
+ }
};
Vulkan_instance &instance;
Vulkan_physical_device &physical_device;
: instance(physical_device.instance),
physical_device(physical_device),
enabled_features(enabled_features),
+ queues{Queue(*this)},
extensions(extensions)
{
}
static util::variant<std::unique_ptr<Vulkan_device>, VkResult> create(
Vulkan_physical_device &physical_device, const VkDeviceCreateInfo &create_info);
};
+
+struct Vulkan_semaphore : public Vulkan_nondispatchable_object<Vulkan_semaphore, VkSemaphore>
+{
+ static std::unique_ptr<Vulkan_semaphore> create(Vulkan_device &device,
+ const VkSemaphoreCreateInfo &create_info);
+};
+
+struct Vulkan_image : public Vulkan_nondispatchable_object<Vulkan_image, VkImage>
+{
+ virtual ~Vulkan_image() = default;
+#warning finish implementing Vulkan_image
+ static std::unique_ptr<Vulkan_image> create(Vulkan_device &device,
+ const VkImageCreateInfo &create_info);
+};
}
}
}
extern "C" VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(VkDevice device,
- uint32_t queueFamilyIndex,
- uint32_t queueIndex,
- VkQueue *pQueue)
+ uint32_t queue_family_index,
+ uint32_t queue_index,
+ VkQueue *queue)
{
-#warning finish implementing vkGetDeviceQueue
- assert(!"vkGetDeviceQueue is not implemented");
+ assert(device);
+ assert(queue_family_index < vulkan::Vulkan_physical_device::queue_family_property_count);
+ assert(queue_index < vulkan::Vulkan_device::queue_count);
+ assert(queue);
+ auto *device_pointer = vulkan::Vulkan_device::from_handle(device);
+ static_assert(vulkan::Vulkan_device::queue_count == 1, "");
+ *queue = to_handle(&device_pointer->queues[0]);
}
extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit(VkQueue queue,
extern "C" VKAPI_ATTR VkResult VKAPI_CALL
vkCreateSemaphore(VkDevice device,
- const VkSemaphoreCreateInfo *pCreateInfo,
+ const VkSemaphoreCreateInfo *create_info,
const VkAllocationCallbacks *allocator,
- VkSemaphore *pSemaphore)
+ VkSemaphore *semaphore)
{
validate_allocator(allocator);
-#warning finish implementing vkCreateSemaphore
- assert(!"vkCreateSemaphore is not implemented");
+ assert(device);
+ assert(create_info);
+ assert(semaphore);
+ return vulkan_icd::catch_exceptions_and_return_result(
+ [&]()
+ {
+ auto create_result = vulkan::Vulkan_semaphore::create(
+ *vulkan::Vulkan_device::from_handle(device), *create_info);
+ *semaphore = move_to_handle(std::move(create_result));
+ return VK_SUCCESS;
+ });
}
extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore(VkDevice device,
const VkAllocationCallbacks *allocator)
{
validate_allocator(allocator);
-#warning finish implementing vkDestroySemaphore
- assert(!"vkDestroySemaphore is not implemented");
+ assert(device);
+ vulkan::Vulkan_semaphore::move_from_handle(semaphore).reset();
}
extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent(VkDevice device,
}
extern "C" VKAPI_ATTR VkResult VKAPI_CALL
- vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
- uint32_t queueFamilyIndex,
+ vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physical_device,
+ uint32_t queue_family_index,
VkSurfaceKHR surface,
- VkBool32 *pSupported)
+ VkBool32 *supported)
{
-#warning finish implementing vkGetPhysicalDeviceSurfaceSupportKHR
- assert(!"vkGetPhysicalDeviceSurfaceSupportKHR is not implemented");
+ assert(physical_device);
+ assert(queue_family_index < vulkan::Vulkan_physical_device::queue_family_property_count);
+ assert(surface);
+ assert(supported);
+ return vulkan_icd::catch_exceptions_and_return_result(
+ [&]()
+ {
+ auto *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
+ auto *wsi = vulkan_icd::Wsi::find(surface_base->platform);
+ assert(wsi);
+ bool is_supported{};
+ auto result = wsi->get_surface_support(surface_base, is_supported);
+ if(result != VK_SUCCESS)
+ return result;
+ *supported = is_supported;
+ return VK_SUCCESS;
+ });
}
extern "C" VKAPI_ATTR VkResult VKAPI_CALL
}
#endif
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+ vkCreateXlibSurfaceKHR(VkInstance instance,
+ const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface)
+{
+#warning finish implementing vkCreateXlibSurfaceKHR
+ assert(!"vkCreateXlibSurfaceKHR is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(
+ VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display *dpy, VisualID visualID)
+{
+#warning finish implementing vkGetPhysicalDeviceXlibPresentationSupportKHR
+ assert(!"vkGetPhysicalDeviceXlibPresentationSupportKHR is not implemented");
+}
+#endif
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+ vkCreateSwapchainKHR(VkDevice device,
+ const VkSwapchainCreateInfoKHR *create_info,
+ const VkAllocationCallbacks *allocator,
+ VkSwapchainKHR *swapchain)
+{
+ validate_allocator(allocator);
+ assert(device);
+ assert(create_info);
+ assert(swapchain);
+ return vulkan_icd::catch_exceptions_and_return_result(
+ [&]()
+ {
+ assert(create_info->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR);
+ auto *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(create_info->surface);
+ auto *wsi = vulkan_icd::Wsi::find(surface_base->platform);
+ assert(wsi);
+ auto create_result =
+ wsi->create_swapchain(*vulkan::Vulkan_device::from_handle(device), *create_info);
+ if(util::holds_alternative<VkResult>(create_result))
+ return util::get<VkResult>(create_result);
+ *swapchain = move_to_handle(
+ util::get<std::unique_ptr<vulkan_icd::Vulkan_swapchain>>(std::move(create_result)));
+ return VK_SUCCESS;
+ });
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(VkDevice device,
+ VkSwapchainKHR swapchain,
+ const VkAllocationCallbacks *allocator)
+{
+ validate_allocator(allocator);
+ assert(device);
+ assert(swapchain);
+ vulkan_icd::Vulkan_swapchain::move_from_handle(swapchain).reset();
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(VkDevice device,
+ VkSwapchainKHR swapchain,
+ uint32_t *swapchain_image_count,
+ VkImage *swapchain_images)
+{
+ assert(device);
+ assert(swapchain);
+ return vulkan_icd::catch_exceptions_and_return_result(
+ [&]()
+ {
+ auto *swapchain_pointer = vulkan_icd::Vulkan_swapchain::from_handle(swapchain);
+ std::vector<VkImage> images;
+ images.reserve(swapchain_pointer->images.size());
+ for(auto &image : swapchain_pointer->images)
+ images.push_back(to_handle(image.get()));
+ return vulkan_icd::vulkan_enumerate_list_helper(
+ swapchain_image_count, swapchain_images, images.data(), images.size());
+ });
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(VkDevice device,
+ VkSwapchainKHR swapchain,
+ uint64_t timeout,
+ VkSemaphore semaphore,
+ VkFence fence,
+ uint32_t *pImageIndex)
+{
+#warning finish implementing vkAcquireNextImageKHR
+ assert(!"vkAcquireNextImageKHR is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue,
+ const VkPresentInfoKHR *pPresentInfo)
+{
+#warning finish implementing vkQueuePresentKHR
+ assert(!"vkQueuePresentKHR is not implemented");
+}
+
namespace kazan
{
namespace vulkan_icd
INSTANCE_SCOPE_EXTENSION_FUNCTION(vkGetPhysicalDeviceXcbPresentationSupportKHR,
KHR_xcb_surface);
#endif
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ INSTANCE_SCOPE_EXTENSION_FUNCTION(vkCreateXlibSurfaceKHR, KHR_xlib_surface);
+ INSTANCE_SCOPE_EXTENSION_FUNCTION(vkGetPhysicalDeviceXlibPresentationSupportKHR,
+ KHR_xlib_surface);
+#endif
+ INSTANCE_SCOPE_EXTENSION_FUNCTION(vkCreateSwapchainKHR, KHR_swapchain);
+ INSTANCE_SCOPE_EXTENSION_FUNCTION(vkDestroySwapchainKHR, KHR_swapchain);
+ INSTANCE_SCOPE_EXTENSION_FUNCTION(vkGetSwapchainImagesKHR, KHR_swapchain);
+ INSTANCE_SCOPE_EXTENSION_FUNCTION(vkAcquireNextImageKHR, KHR_swapchain);
+ INSTANCE_SCOPE_EXTENSION_FUNCTION(vkQueuePresentKHR, KHR_swapchain);
#undef LIBRARY_SCOPE_FUNCTION
#undef INSTANCE_SCOPE_FUNCTION
#include "vulkan/vulkan.h"
#include "vulkan/vk_icd.h"
#include "vulkan/remove_xlib_macros.h"
+#include "vulkan/api_objects.h"
+#include "util/variant.h"
#include <type_traits>
#include <cstdint>
#include <vector>
{
namespace vulkan_icd
{
+struct Wsi;
+
+class Vulkan_swapchain
+ : public vulkan::Vulkan_nondispatchable_object<Vulkan_swapchain, VkSwapchainKHR>
+{
+public:
+ std::vector<std::unique_ptr<vulkan::Vulkan_image>> images;
+
+public:
+ explicit Vulkan_swapchain(std::vector<std::unique_ptr<vulkan::Vulkan_image>> images) noexcept
+ : images(std::move(images))
+ {
+ }
+ virtual ~Vulkan_swapchain() = default;
+};
+
struct Wsi
{
class Wsi_list
{
}
virtual void destroy_surface(VkIcdSurfaceBase *surface) const noexcept = 0;
- virtual VkResult get_surface_support(VkIcdSurfaceBase *surface, VkBool32 &supported) const = 0;
- virtual VkResult get_surface_formats(VkIcdSurfaceBase *surface, std::vector<VkSurfaceFormatKHR> &surface_formats) const = 0;
- virtual VkResult get_present_modes(VkIcdSurfaceBase *surface, std::vector<VkPresentModeKHR> &present_modes) const = 0;
- virtual VkResult get_surface_capabilities(VkIcdSurfaceBase *surface, VkSurfaceCapabilitiesKHR &capabilities) const = 0;
+ virtual VkResult get_surface_support(VkIcdSurfaceBase *surface, bool &supported) const = 0;
+ virtual VkResult get_surface_formats(
+ VkIcdSurfaceBase *surface, std::vector<VkSurfaceFormatKHR> &surface_formats) const = 0;
+ virtual VkResult get_present_modes(VkIcdSurfaceBase *surface,
+ std::vector<VkPresentModeKHR> &present_modes) const = 0;
+ virtual VkResult get_surface_capabilities(VkIcdSurfaceBase *surface,
+ VkSurfaceCapabilitiesKHR &capabilities) const = 0;
+ virtual util::variant<VkResult, std::unique_ptr<Vulkan_swapchain>> create_swapchain(
+ vulkan::Vulkan_device &device, const VkSwapchainCreateInfoKHR &create_info) const = 0;
};
static_assert(std::is_trivially_destructible<Wsi>::value,
struct Implementation;
VkIcdSurfaceBase *create_surface(const VkXcbSurfaceCreateInfoKHR &create_info) const;
virtual void destroy_surface(VkIcdSurfaceBase *surface) const noexcept override;
- virtual VkResult get_surface_support(VkIcdSurfaceBase *surface, VkBool32 &supported) const override;
- virtual VkResult get_surface_formats(VkIcdSurfaceBase *surface, std::vector<VkSurfaceFormatKHR> &surface_formats) const override;
- virtual VkResult get_present_modes(VkIcdSurfaceBase *surface, std::vector<VkPresentModeKHR> &present_modes) const override;
- virtual VkResult get_surface_capabilities(VkIcdSurfaceBase *surface, VkSurfaceCapabilitiesKHR &capabilities) const override;
+ virtual VkResult get_surface_support(VkIcdSurfaceBase *surface, bool &supported) const override;
+ virtual VkResult get_surface_formats(
+ VkIcdSurfaceBase *surface, std::vector<VkSurfaceFormatKHR> &surface_formats) const override;
+ virtual VkResult get_present_modes(VkIcdSurfaceBase *surface,
+ std::vector<VkPresentModeKHR> &present_modes) const override;
+ virtual VkResult get_surface_capabilities(
+ VkIcdSurfaceBase *surface, VkSurfaceCapabilitiesKHR &capabilities) const override;
+ virtual util::variant<VkResult, std::unique_ptr<Vulkan_swapchain>> create_swapchain(
+ vulkan::Vulkan_device &device, const VkSwapchainCreateInfoKHR &create_info) const override;
static const Xcb_wsi &get() noexcept;
};
#endif
struct Implementation;
VkIcdSurfaceBase *create_surface(const VkXlibSurfaceCreateInfoKHR &create_info) const;
virtual void destroy_surface(VkIcdSurfaceBase *surface) const noexcept override;
- virtual VkResult get_surface_support(VkIcdSurfaceBase *surface, VkBool32 &supported) const override;
- virtual VkResult get_surface_formats(VkIcdSurfaceBase *surface, std::vector<VkSurfaceFormatKHR> &surface_formats) const override;
- virtual VkResult get_present_modes(VkIcdSurfaceBase *surface, std::vector<VkPresentModeKHR> &present_modes) const override;
- virtual VkResult get_surface_capabilities(VkIcdSurfaceBase *surface, VkSurfaceCapabilitiesKHR &capabilities) const override;
+ virtual VkResult get_surface_support(VkIcdSurfaceBase *surface, bool &supported) const override;
+ virtual VkResult get_surface_formats(
+ VkIcdSurfaceBase *surface, std::vector<VkSurfaceFormatKHR> &surface_formats) const override;
+ virtual VkResult get_present_modes(VkIcdSurfaceBase *surface,
+ std::vector<VkPresentModeKHR> &present_modes) const override;
+ virtual VkResult get_surface_capabilities(
+ VkIcdSurfaceBase *surface, VkSurfaceCapabilitiesKHR &capabilities) const override;
+ virtual util::variant<VkResult, std::unique_ptr<Vulkan_swapchain>> create_swapchain(
+ vulkan::Vulkan_device &device, const VkSwapchainCreateInfoKHR &create_info) const override;
static const Xlib_wsi &get() noexcept;
};
#endif
struct Implementation;
VkIcdSurfaceBase *create_surface(const VkWaylandSurfaceCreateInfoKHR &create_info) const;
virtual void destroy_surface(VkIcdSurfaceBase *surface) const noexcept override;
- virtual VkResult get_surface_support(VkIcdSurfaceBase *surface, VkBool32 &supported) const override;
- virtual VkResult get_surface_formats(VkIcdSurfaceBase *surface, std::vector<VkSurfaceFormatKHR> &surface_formats) const override;
- virtual VkResult get_present_modes(VkIcdSurfaceBase *surface, std::vector<VkPresentModeKHR> &present_modes) const override;
- virtual VkResult get_surface_capabilities(VkIcdSurfaceBase *surface, VkSurfaceCapabilitiesKHR &capabilities) const override;
+ virtual VkResult get_surface_support(VkIcdSurfaceBase *surface, bool &supported) const override;
+ virtual VkResult get_surface_formats(
+ VkIcdSurfaceBase *surface, std::vector<VkSurfaceFormatKHR> &surface_formats) const override;
+ virtual VkResult get_present_modes(VkIcdSurfaceBase *surface,
+ std::vector<VkPresentModeKHR> &present_modes) const override;
+ virtual VkResult get_surface_capabilities(
+ VkIcdSurfaceBase *surface, VkSurfaceCapabilitiesKHR &capabilities) const override;
+ virtual util::variant<VkResult, std::unique_ptr<Vulkan_swapchain>> create_swapchain(
+ vulkan::Vulkan_device &device, const VkSwapchainCreateInfoKHR &create_info) const override;
static const Wayland_wsi &get() noexcept;
};
#endif
struct Implementation;
VkIcdSurfaceBase *create_surface(const VkWin32SurfaceCreateInfoKHR &create_info) const;
virtual void destroy_surface(VkIcdSurfaceBase *surface) const noexcept override;
- virtual VkResult get_surface_support(VkIcdSurfaceBase *surface, VkBool32 &supported) const override;
- virtual VkResult get_surface_formats(VkIcdSurfaceBase *surface, std::vector<VkSurfaceFormatKHR> &surface_formats) const override;
- virtual VkResult get_present_modes(VkIcdSurfaceBase *surface, std::vector<VkPresentModeKHR> &present_modes) const override;
- virtual VkResult get_surface_capabilities(VkIcdSurfaceBase *surface, VkSurfaceCapabilitiesKHR &capabilities) const override;
+ virtual VkResult get_surface_support(VkIcdSurfaceBase *surface, bool &supported) const override;
+ virtual VkResult get_surface_formats(
+ VkIcdSurfaceBase *surface, std::vector<VkSurfaceFormatKHR> &surface_formats) const override;
+ virtual VkResult get_present_modes(VkIcdSurfaceBase *surface,
+ std::vector<VkPresentModeKHR> &present_modes) const override;
+ virtual VkResult get_surface_capabilities(
+ VkIcdSurfaceBase *surface, VkSurfaceCapabilitiesKHR &capabilities) const override;
+ virtual util::variant<VkResult, std::unique_ptr<Vulkan_swapchain>> create_swapchain(
+ vulkan::Vulkan_device &device, const VkSwapchainCreateInfoKHR &create_info) const override;
static const Win32_wsi &get() noexcept;
};
#endif
#include <cstdlib>
#include <memory>
#include <cstring>
+#include <iostream>
+#include <list>
+#include <utility>
+#include <algorithm>
#include "util/optional.h"
namespace kazan
std::uint32_t image_width;
std::uint32_t image_height;
Surface_format_group surface_format_group;
- std::vector<VkPresentModeKHR> present_modes;
+ util::optional<std::vector<VkPresentModeKHR>> present_modes;
VkSurfaceCapabilitiesKHR capabilities;
+ std::size_t image_pixel_size;
+ std::size_t scanline_alignment;
+ xcb_shm_query_version_cookie_t shm_query_version_cookie;
Start_setup_results(Gc gc,
bool shm_is_supported,
unsigned window_depth,
std::uint32_t image_height,
Surface_format_group surface_format_group,
std::vector<VkPresentModeKHR> present_modes,
- const VkSurfaceCapabilitiesKHR &capabilities) noexcept
+ const VkSurfaceCapabilitiesKHR &capabilities,
+ std::size_t image_pixel_size,
+ std::size_t scanline_alignment,
+ xcb_shm_query_version_cookie_t shm_query_version_cookie) noexcept
: status(Status::Success),
gc(std::move(gc)),
shm_is_supported(shm_is_supported),
image_height(image_height),
surface_format_group(surface_format_group),
present_modes(std::move(present_modes)),
- capabilities(capabilities)
+ capabilities(capabilities),
+ image_pixel_size(image_pixel_size),
+ scanline_alignment(scanline_alignment),
+ shm_query_version_cookie(shm_query_version_cookie)
{
}
- Start_setup_results(Status status) noexcept : status(status),
- gc(),
- shm_is_supported(),
- window_depth(),
- surface_format_group(),
- present_modes(),
- capabilities{}
+ constexpr Start_setup_results(Status status) noexcept : status(status),
+ gc(),
+ shm_is_supported(),
+ window_depth(),
+ image_width(),
+ image_height(),
+ surface_format_group(),
+ present_modes(),
+ capabilities{},
+ image_pixel_size(),
+ scanline_alignment(),
+ shm_query_version_cookie()
{
assert(status != Status::Success);
}
};
- static Start_setup_results start_setup(xcb_connection_t *connection, xcb_window_t window)
+ static Start_setup_results start_setup(xcb_connection_t *connection,
+ xcb_window_t window,
+ bool is_full_setup)
{
auto mit_shm_cookie = query_extension(connection, "MIT-SHM");
auto get_geometry_cookie = xcb_get_geometry(connection, window);
Query_extension_reply(xcb_query_extension_reply(connection, mit_shm_cookie, nullptr));
bool shm_is_supported = mit_shm_reply && mit_shm_reply->present;
xcb_shm_query_version_cookie_t shm_query_version_cookie{};
- if(shm_is_supported)
+ if(shm_is_supported && is_full_setup)
shm_query_version_cookie = xcb_shm_query_version(connection);
auto get_geometry_reply =
Get_geometry_reply(xcb_get_geometry_reply(connection, get_geometry_cookie, nullptr));
image_height,
surface_format_group,
present_modes,
- capabilities);
+ capabilities,
+ image_pixel_size,
+ scanline_alignment,
+ shm_query_version_cookie);
}
+ struct Swapchain final : public Vulkan_swapchain
+ {
+ struct Swapchain_image final : public vulkan::Vulkan_image
+ {
+ std::shared_ptr<void> pixels;
+ std::size_t row_pitch;
+ std::uint32_t width;
+ std::uint32_t height;
+ std::size_t pixel_size;
+ Shared_memory_segment shared_memory_segment;
+ Server_shm_seg server_shm_seg;
+ Pixmap pixmap;
+ std::list<Swapchain_image *>::iterator iter;
+ Swapchain_image(std::shared_ptr<void> pixels,
+ std::size_t row_pitch,
+ std::uint32_t width,
+ std::uint32_t height,
+ std::size_t pixel_size,
+ Shared_memory_segment shared_memory_segment,
+ Server_shm_seg server_shm_seg,
+ Pixmap pixmap,
+ std::list<Swapchain_image *>::iterator iter) noexcept
+ : pixels(std::move(pixels)),
+ row_pitch(row_pitch),
+ width(width),
+ height(height),
+ pixel_size(pixel_size),
+ shared_memory_segment(std::move(shared_memory_segment)),
+ server_shm_seg(std::move(server_shm_seg)),
+ pixmap(std::move(pixmap)),
+ iter(iter)
+ {
+ }
+ };
+ xcb_connection_t *connection;
+ xcb_window_t window;
+ bool shm_is_supported;
+ std::list<Swapchain_image *> free_list;
+ explicit Swapchain(Start_setup_results start_setup_results,
+ xcb_connection_t *connection,
+ xcb_window_t window,
+ const VkSwapchainCreateInfoKHR &create_info)
+ : Vulkan_swapchain({}),
+ connection(connection),
+ window(window),
+ shm_is_supported(start_setup_results.shm_is_supported)
+ {
+ std::size_t unpadded_scanline_size =
+ start_setup_results.image_pixel_size * start_setup_results.image_width;
+ std::size_t padded_scanline_size =
+ (unpadded_scanline_size + start_setup_results.scanline_alignment - 1U)
+ & ~(start_setup_results.scanline_alignment - 1U);
+ std::size_t image_size = padded_scanline_size * start_setup_results.image_height;
+ if(shm_is_supported)
+ {
+ auto shm_query_version_reply = Shm_query_version_reply(xcb_shm_query_version_reply(
+ connection, start_setup_results.shm_query_version_cookie, nullptr));
+ if(!shm_query_version_reply || !shm_query_version_reply->shared_pixmaps
+ || shm_query_version_reply->pixmap_format != XCB_IMAGE_FORMAT_Z_PIXMAP)
+ {
+ std::cerr
+ << "shared memory pixmaps are not supported, falling back to using core "
+ "X protocol"
+ << std::endl;
+ shm_is_supported = false;
+ }
+ }
+ auto image_count = std::max<std::uint32_t>(create_info.minImageCount, 2);
+ while(true)
+ {
+ bool shm_failed = false;
+ for(std::uint32_t i = 0; i < image_count; i++)
+ {
+ Shared_memory_segment shared_memory_segment;
+ std::shared_ptr<void> pixels;
+ Server_shm_seg server_shm_seg;
+ Pixmap pixmap;
+ if(shm_is_supported)
+ {
+ shared_memory_segment = Shared_memory_segment::create(image_size);
+ pixels = shared_memory_segment.map();
+ auto seg_id = xcb_generate_id(connection);
+ auto shm_attach_cookie = xcb_shm_attach_checked(
+ connection, seg_id, shared_memory_segment.get(), false);
+ auto error =
+ Generic_error(xcb_request_check(connection, shm_attach_cookie));
+ if(error)
+ {
+ shm_failed = true;
+ break;
+ }
+ server_shm_seg = Server_shm_seg(seg_id, connection);
+ auto pixmap_id = xcb_generate_id(connection);
+ error = Generic_error(xcb_request_check(
+ connection,
+ xcb_shm_create_pixmap_checked(connection,
+ pixmap_id,
+ window,
+ start_setup_results.image_width,
+ start_setup_results.image_height,
+ start_setup_results.window_depth,
+ server_shm_seg.get(),
+ 0)));
+ if(error)
+ {
+ shm_failed = true;
+ break;
+ }
+ pixmap = Pixmap(pixmap_id, connection);
+ }
+ else
+ {
+ pixels = std::shared_ptr<unsigned char>(new unsigned char[image_size],
+ [](unsigned char *p) noexcept
+ {
+ delete[] p;
+ });
+ }
+ auto image_iter = free_list.insert(free_list.end(), nullptr);
+ auto image =
+ std::make_unique<Swapchain_image>(std::move(pixels),
+ padded_scanline_size,
+ start_setup_results.image_width,
+ start_setup_results.image_height,
+ start_setup_results.image_pixel_size,
+ std::move(shared_memory_segment),
+ std::move(server_shm_seg),
+ std::move(pixmap),
+ image_iter);
+ *image_iter = image.get();
+ images.push_back(std::move(image));
+ }
+ if(shm_failed)
+ {
+ std::cerr << "using shared memory failed, falling back to using core X protocol"
+ << std::endl;
+ shm_is_supported = false;
+ free_list.clear();
+ images.clear();
+ continue;
+ }
+ break;
+ }
+ }
+ };
};
VkIcdSurfaceBase *Xcb_wsi::create_surface(const VkXcbSurfaceCreateInfoKHR &create_info) const
delete reinterpret_cast<Surface_type *>(surface);
}
-VkResult Xcb_wsi::get_surface_support(VkIcdSurfaceBase *surface_, VkBool32 &supported) const
+VkResult Xcb_wsi::get_surface_support(VkIcdSurfaceBase *surface_, bool &supported) const
{
auto &surface = *reinterpret_cast<Surface_type *>(surface_);
- switch(Implementation::start_setup(surface.connection, surface.window).status)
+ switch(Implementation::start_setup(surface.connection, surface.window, false).status)
{
case Implementation::Start_setup_results::Status::Bad_surface:
return VK_ERROR_SURFACE_LOST_KHR;
std::vector<VkSurfaceFormatKHR> &surface_formats) const
{
auto &surface = *reinterpret_cast<Surface_type *>(surface_);
- auto start_setup_result = Implementation::start_setup(surface.connection, surface.window);
+ auto start_setup_result =
+ Implementation::start_setup(surface.connection, surface.window, false);
switch(start_setup_result.status)
{
case Implementation::Start_setup_results::Status::Bad_surface:
std::vector<VkPresentModeKHR> &present_modes) const
{
auto &surface = *reinterpret_cast<Surface_type *>(surface_);
- auto start_setup_result = Implementation::start_setup(surface.connection, surface.window);
+ auto start_setup_result =
+ Implementation::start_setup(surface.connection, surface.window, false);
switch(start_setup_result.status)
{
case Implementation::Start_setup_results::Status::Bad_surface:
case Implementation::Start_setup_results::Status::No_support:
return VK_ERROR_SURFACE_LOST_KHR;
case Implementation::Start_setup_results::Status::Success:
- present_modes = std::move(start_setup_result.present_modes);
+ present_modes = std::move(start_setup_result.present_modes.value());
return VK_SUCCESS;
}
assert(!"unreachable");
VkSurfaceCapabilitiesKHR &capabilities) const
{
auto &surface = *reinterpret_cast<Surface_type *>(surface_);
- auto start_setup_result = Implementation::start_setup(surface.connection, surface.window);
+ auto start_setup_result =
+ Implementation::start_setup(surface.connection, surface.window, false);
switch(start_setup_result.status)
{
case Implementation::Start_setup_results::Status::Bad_surface:
return {};
}
+util::variant<VkResult, std::unique_ptr<Vulkan_swapchain>> Xcb_wsi::create_swapchain(
+ vulkan::Vulkan_device &device, const VkSwapchainCreateInfoKHR &create_info) const
+{
+#warning finish implementing Xcb_wsi::create_swapchain
+ auto &surface = *reinterpret_cast<Surface_type *>(create_info.surface);
+ return std::make_unique<Implementation::Swapchain>(
+ Implementation::start_setup(surface.connection, surface.window, true),
+ surface.connection,
+ surface.window,
+ create_info);
+}
+
const Xcb_wsi &Xcb_wsi::get() noexcept
{
static const Xcb_wsi retval{};
delete reinterpret_cast<Surface_type *>(surface);
}
-VkResult Xlib_wsi::get_surface_support(VkIcdSurfaceBase *surface_, VkBool32 &supported) const
+VkResult Xlib_wsi::get_surface_support(VkIcdSurfaceBase *surface_, bool &supported) const
{
auto &surface = *reinterpret_cast<Surface_type *>(surface_);
auto xcb_surface = Implementation::get_xcb_surface(surface);
reinterpret_cast<VkIcdSurfaceBase *>(&xcb_surface), capabilities);
}
+util::variant<VkResult, std::unique_ptr<Vulkan_swapchain>> Xlib_wsi::create_swapchain(
+ vulkan::Vulkan_device &device, const VkSwapchainCreateInfoKHR &create_info) const
+{
+ assert(create_info.surface);
+ auto &surface = *reinterpret_cast<Surface_type *>(create_info.surface);
+ auto xcb_surface = Implementation::get_xcb_surface(surface);
+ VkSwapchainCreateInfoKHR xcb_create_info = create_info;
+ xcb_create_info.surface = reinterpret_cast<VkSurfaceKHR>(&xcb_surface);
+ return Xcb_wsi::get().create_swapchain(device, xcb_create_info);
+}
+
const Xlib_wsi &Xlib_wsi::get() noexcept
{
static const Xlib_wsi retval{};