Add createSwapChain for GEVulkanDriver
This commit is contained in:
parent
3f99d279a7
commit
f0f498d53f
@ -199,7 +199,7 @@ namespace GE
|
|||||||
|
|
||||||
//! Only used by the internal engine. Used to notify the driver that
|
//! Only used by the internal engine. Used to notify the driver that
|
||||||
//! the window was resized.
|
//! the window was resized.
|
||||||
virtual void OnResize(const core::dimension2d<u32>& size) {}
|
virtual void OnResize(const core::dimension2d<u32>& size);
|
||||||
|
|
||||||
//! Returns type of video driver
|
//! Returns type of video driver
|
||||||
virtual E_DRIVER_TYPE getDriverType() const { return video::EDT_VULKAN; }
|
virtual E_DRIVER_TYPE getDriverType() const { return video::EDT_VULKAN; }
|
||||||
@ -263,6 +263,13 @@ namespace GE
|
|||||||
virtual void disableScissorTest() {}
|
virtual void disableScissorTest() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct SwapChainSupportDetails
|
||||||
|
{
|
||||||
|
VkSurfaceCapabilitiesKHR capabilities;
|
||||||
|
std::vector<VkSurfaceFormatKHR> formats;
|
||||||
|
std::vector<VkPresentModeKHR> presentModes;
|
||||||
|
};
|
||||||
|
|
||||||
//! returns a device dependent texture from a software surface (IImage)
|
//! returns a device dependent texture from a software surface (IImage)
|
||||||
//! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES
|
//! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES
|
||||||
virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0) { return NULL; }
|
virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0) { return NULL; }
|
||||||
@ -294,29 +301,42 @@ namespace GE
|
|||||||
s32 userData = 0,
|
s32 userData = 0,
|
||||||
E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) { return 0; }
|
E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) { return 0; }
|
||||||
|
|
||||||
|
SIrrlichtCreationParameters m_params;
|
||||||
// RAII to auto cleanup
|
// RAII to auto cleanup
|
||||||
struct VK
|
struct VK
|
||||||
{
|
{
|
||||||
VkInstance instance;
|
VkInstance instance;
|
||||||
VkSurfaceKHR surface;
|
VkSurfaceKHR surface;
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
|
VkSwapchainKHR swap_chain;
|
||||||
|
std::vector<VkImage> swap_chain_images;
|
||||||
|
std::vector<VkImageView> swap_chain_image_views;
|
||||||
VK()
|
VK()
|
||||||
{
|
{
|
||||||
instance = VK_NULL_HANDLE;
|
instance = VK_NULL_HANDLE;
|
||||||
surface = VK_NULL_HANDLE;
|
surface = VK_NULL_HANDLE;
|
||||||
device = VK_NULL_HANDLE;
|
device = VK_NULL_HANDLE;
|
||||||
|
swap_chain = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
~VK()
|
~VK()
|
||||||
{
|
{
|
||||||
|
for (VkImageView& image_view : swap_chain_image_views)
|
||||||
|
vkDestroyImageView(device, image_view, NULL);
|
||||||
|
if (swap_chain != VK_NULL_HANDLE)
|
||||||
|
vkDestroySwapchainKHR(device, swap_chain, NULL);
|
||||||
if (device != VK_NULL_HANDLE)
|
if (device != VK_NULL_HANDLE)
|
||||||
vkDestroyDevice(device, NULL);
|
vkDestroyDevice(device, NULL);
|
||||||
if (surface != VK_NULL_HANDLE)
|
if (surface != VK_NULL_HANDLE)
|
||||||
vkDestroySurfaceKHR(instance, surface, NULL);
|
vkDestroySurfaceKHR(instance, surface, NULL);
|
||||||
if (instance != VK_NULL_HANDLE)
|
if (instance != VK_NULL_HANDLE)
|
||||||
vkDestroyInstance(instance, NULL);
|
vkDestroyInstance(instance, NULL);
|
||||||
|
if (instance != VK_NULL_HANDLE)
|
||||||
|
vkDestroyInstance(instance, NULL);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
VK m_vk;
|
VK m_vk;
|
||||||
|
VkFormat m_swap_chain_image_format;
|
||||||
|
VkExtent2D m_swap_chain_extent;
|
||||||
VkPhysicalDevice m_physical_device;
|
VkPhysicalDevice m_physical_device;
|
||||||
std::vector<const char*> m_device_extensions;
|
std::vector<const char*> m_device_extensions;
|
||||||
VkSurfaceCapabilitiesKHR m_surface_capabilities;
|
VkSurfaceCapabilitiesKHR m_surface_capabilities;
|
||||||
@ -339,6 +359,7 @@ namespace GE
|
|||||||
std::vector<VkSurfaceFormatKHR>* surface_formats,
|
std::vector<VkSurfaceFormatKHR>* surface_formats,
|
||||||
std::vector<VkPresentModeKHR>* present_modes);
|
std::vector<VkPresentModeKHR>* present_modes);
|
||||||
void createDevice();
|
void createDevice();
|
||||||
|
void createSwapChain();
|
||||||
std::string getVulkanVersionString() const;
|
std::string getVulkanVersionString() const;
|
||||||
std::string getDriverVersionString() const;
|
std::string getDriverVersionString() const;
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#ifdef _IRR_COMPILE_WITH_VULKAN_
|
#ifdef _IRR_COMPILE_WITH_VULKAN_
|
||||||
#include "SDL_vulkan.h"
|
#include "SDL_vulkan.h"
|
||||||
|
#include <limits>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -437,7 +438,8 @@ namespace GE
|
|||||||
{
|
{
|
||||||
GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params,
|
GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params,
|
||||||
io::IFileSystem* io, SDL_Window* window)
|
io::IFileSystem* io, SDL_Window* window)
|
||||||
: CNullDriver(io, core::dimension2d<u32>(0, 0))
|
: CNullDriver(io, core::dimension2d<u32>(0, 0)),
|
||||||
|
m_params(params)
|
||||||
{
|
{
|
||||||
m_physical_device = VK_NULL_HANDLE;
|
m_physical_device = VK_NULL_HANDLE;
|
||||||
m_graphics_queue = VK_NULL_HANDLE;
|
m_graphics_queue = VK_NULL_HANDLE;
|
||||||
@ -461,6 +463,11 @@ GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params,
|
|||||||
|
|
||||||
if (SDL_Vulkan_CreateSurface(window, m_vk.instance, &m_vk.surface) == SDL_FALSE)
|
if (SDL_Vulkan_CreateSurface(window, m_vk.instance, &m_vk.surface) == SDL_FALSE)
|
||||||
throw std::runtime_error("SDL_Vulkan_CreateSurface failed");
|
throw std::runtime_error("SDL_Vulkan_CreateSurface failed");
|
||||||
|
int w, h = 0;
|
||||||
|
SDL_Vulkan_GetDrawableSize(window, &w, &h);
|
||||||
|
ScreenSize.Width = w;
|
||||||
|
ScreenSize.Height = h;
|
||||||
|
|
||||||
m_device_extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
m_device_extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||||
findPhysicalDevice();
|
findPhysicalDevice();
|
||||||
createDevice();
|
createDevice();
|
||||||
@ -476,6 +483,7 @@ GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
vkGetPhysicalDeviceProperties(m_physical_device, &m_properties);
|
vkGetPhysicalDeviceProperties(m_physical_device, &m_properties);
|
||||||
|
createSwapChain();
|
||||||
os::Printer::log("Vulkan version", getVulkanVersionString().c_str());
|
os::Printer::log("Vulkan version", getVulkanVersionString().c_str());
|
||||||
os::Printer::log("Vulkan vendor", getVendorInfo().c_str());
|
os::Printer::log("Vulkan vendor", getVendorInfo().c_str());
|
||||||
os::Printer::log("Vulkan renderer", m_properties.deviceName);
|
os::Printer::log("Vulkan renderer", m_properties.deviceName);
|
||||||
@ -742,6 +750,157 @@ std::string GEVulkanDriver::getDriverVersionString() const
|
|||||||
return driver_version.str();
|
return driver_version.str();
|
||||||
} // getDriverVersionString
|
} // getDriverVersionString
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void GEVulkanDriver::createSwapChain()
|
||||||
|
{
|
||||||
|
VkSurfaceFormatKHR surface_format = m_surface_formats[0];
|
||||||
|
|
||||||
|
if (m_surface_formats.size() == 1 &&
|
||||||
|
m_surface_formats[0].format == VK_FORMAT_UNDEFINED)
|
||||||
|
{
|
||||||
|
surface_format =
|
||||||
|
{
|
||||||
|
VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (VkSurfaceFormatKHR& available_format : m_surface_formats)
|
||||||
|
{
|
||||||
|
if (available_format.format == VK_FORMAT_B8G8R8A8_UNORM &&
|
||||||
|
available_format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||||
|
{
|
||||||
|
surface_format = available_format;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
if (m_params.SwapInterval == 0)
|
||||||
|
{
|
||||||
|
for (VkPresentModeKHR& available_mode : m_present_modes)
|
||||||
|
{
|
||||||
|
if (available_mode == VK_PRESENT_MODE_IMMEDIATE_KHR)
|
||||||
|
{
|
||||||
|
present_mode = available_mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (VkPresentModeKHR& available_mode : m_present_modes)
|
||||||
|
{
|
||||||
|
if (available_mode == VK_PRESENT_MODE_MAILBOX_KHR)
|
||||||
|
{
|
||||||
|
present_mode = available_mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkExtent2D image_extent = m_surface_capabilities.currentExtent;
|
||||||
|
if (m_surface_capabilities.currentExtent.width == std::numeric_limits<uint32_t>::max())
|
||||||
|
{
|
||||||
|
VkExtent2D max_extent = m_surface_capabilities.maxImageExtent;
|
||||||
|
VkExtent2D min_extent = m_surface_capabilities.minImageExtent;
|
||||||
|
|
||||||
|
VkExtent2D actual_extent =
|
||||||
|
{
|
||||||
|
std::max(
|
||||||
|
std::min(ScreenSize.Width, max_extent.width), min_extent.width),
|
||||||
|
std::max(
|
||||||
|
std::min(ScreenSize.Height, max_extent.height), min_extent.height)
|
||||||
|
};
|
||||||
|
image_extent = actual_extent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to get triple buffering by default
|
||||||
|
// https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Swap_chain
|
||||||
|
uint32_t swap_chain_images_count = m_surface_capabilities.minImageCount + 1;
|
||||||
|
if (m_surface_capabilities.maxImageCount > 0 &&
|
||||||
|
swap_chain_images_count > m_surface_capabilities.maxImageCount)
|
||||||
|
{
|
||||||
|
swap_chain_images_count = m_surface_capabilities.maxImageCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSwapchainCreateInfoKHR create_info = {};
|
||||||
|
create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
|
create_info.surface = m_vk.surface;
|
||||||
|
create_info.minImageCount = swap_chain_images_count;
|
||||||
|
create_info.imageFormat = surface_format.format;
|
||||||
|
create_info.imageColorSpace = surface_format.colorSpace;
|
||||||
|
create_info.imageExtent = image_extent;
|
||||||
|
create_info.imageArrayLayers = 1;
|
||||||
|
create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
|
||||||
|
if (m_graphics_family != m_present_family)
|
||||||
|
{
|
||||||
|
uint32_t queueFamilyIndices[] =
|
||||||
|
{ m_graphics_family, m_present_family };
|
||||||
|
create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||||
|
create_info.queueFamilyIndexCount = 2;
|
||||||
|
create_info.pQueueFamilyIndices = queueFamilyIndices;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
create_info.preTransform = m_surface_capabilities.currentTransform;
|
||||||
|
create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||||
|
create_info.presentMode = present_mode;
|
||||||
|
create_info.clipped = VK_TRUE;
|
||||||
|
create_info.oldSwapchain = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
VkResult result = vkCreateSwapchainKHR(m_vk.device, &create_info, NULL,
|
||||||
|
&m_vk.swap_chain);
|
||||||
|
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
throw std::runtime_error("vkCreateSwapchainKHR failed");
|
||||||
|
|
||||||
|
vkGetSwapchainImagesKHR(m_vk.device, m_vk.swap_chain, &swap_chain_images_count, NULL);
|
||||||
|
m_vk.swap_chain_images.resize(swap_chain_images_count);
|
||||||
|
vkGetSwapchainImagesKHR(m_vk.device, m_vk.swap_chain, &swap_chain_images_count,
|
||||||
|
&m_vk.swap_chain_images[0]);
|
||||||
|
|
||||||
|
m_swap_chain_image_format = surface_format.format;
|
||||||
|
m_swap_chain_extent = image_extent;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < m_vk.swap_chain_images.size(); i++)
|
||||||
|
{
|
||||||
|
VkImageViewCreateInfo create_info = {};
|
||||||
|
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
create_info.image = m_vk.swap_chain_images[i];
|
||||||
|
create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
create_info.format = m_swap_chain_image_format;
|
||||||
|
create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
create_info.subresourceRange.baseMipLevel = 0;
|
||||||
|
create_info.subresourceRange.levelCount = 1;
|
||||||
|
create_info.subresourceRange.baseArrayLayer = 0;
|
||||||
|
create_info.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
VkImageView swap_chain_image_view = VK_NULL_HANDLE;
|
||||||
|
VkResult result = vkCreateImageView(m_vk.device, &create_info, NULL,
|
||||||
|
&swap_chain_image_view);
|
||||||
|
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
throw std::runtime_error("vkCreateImageView failed");
|
||||||
|
m_vk.swap_chain_image_views.push_back(swap_chain_image_view);
|
||||||
|
}
|
||||||
|
} // createSwapChain
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void GEVulkanDriver::OnResize(const core::dimension2d<u32>& size)
|
||||||
|
{
|
||||||
|
CNullDriver::OnResize(size);
|
||||||
|
} // OnResize
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
|
Loading…
x
Reference in New Issue
Block a user