create device & swapchain
This commit is contained in:
parent
d8163fd614
commit
e48d175b76
@ -8,6 +8,7 @@ namespace vulkanapi {
|
||||
mInstance = new Instance(instanceCreator);
|
||||
|
||||
auto deviceCreator = DeviceCreator(*mInstance);
|
||||
deviceCreator.AddWindowExtension();
|
||||
deviceCreator.desiredPhysicalDeviceFeatures.geometryShader = VK_TRUE;
|
||||
deviceCreator.AddQueue("TransferQueue", VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0);
|
||||
deviceCreator.AddQueue("RenderQueue", VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0);
|
||||
@ -15,6 +16,7 @@ namespace vulkanapi {
|
||||
deviceCreator.AddQueue("PresentQueue", VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT, 1.0);
|
||||
mDevice = new Device(deviceCreator);
|
||||
|
||||
|
||||
}
|
||||
Backend::~Backend()
|
||||
{
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include "wrapper/instance.h"
|
||||
#include "wrapper/device.h"
|
||||
#include "wrapper/swapchain.h"
|
||||
#include "wrapper/swapchain_creator.h"
|
||||
#include <vulkan/vulkan_win32.h>
|
||||
namespace vulkanapi {
|
||||
Window::Window(Backend& backend, int frames, uint32_t width, uint32_t height, const char* title)
|
||||
@ -19,7 +20,7 @@ namespace vulkanapi {
|
||||
mPtr // HWND hwnd
|
||||
};
|
||||
vkCreateWin32SurfaceKHR(instance, &surface_create_info, nullptr, &mSurfaceKHR);
|
||||
|
||||
mSwapchain = new Swapchain(backend.GetDevice(), frames, width, height, mSurfaceKHR);
|
||||
SwapchainCreator swapchainCreator(backend.GetDevice(), frames, width, height, mSurfaceKHR);
|
||||
mSwapchain = new Swapchain(swapchainCreator);
|
||||
}
|
||||
}
|
||||
@ -1,20 +1,37 @@
|
||||
#include "device.h"
|
||||
#include "device_creator.h"
|
||||
#include "zlog.h"
|
||||
namespace vulkanapi {
|
||||
Device::Device(DeviceCreator& Creator)
|
||||
{
|
||||
|
||||
}
|
||||
uint32_t Device::GetQueueFamilyIndex(VkQueueFlags flag)
|
||||
{
|
||||
Creator.FindDevice(mPhysical);
|
||||
std::vector<VkQueueFamilyProperties> queue_families;
|
||||
// CheckAvailableQueueFamiliesAndTheirProperties(mPhysical, queue_families);
|
||||
for (uint32_t i = 0, l = queue_families.size(); i < l; i++) {
|
||||
if ((queue_families[i].queueFlags & flag) == flag) {
|
||||
return i;
|
||||
}
|
||||
Creator.CheckAvailableQueueFamilies(mPhysical, queue_families);
|
||||
std::vector<VkDeviceQueueCreateInfo> queue_create_infos;
|
||||
std::vector<std::vector<float>> queue_prioritie;
|
||||
Creator.QueueCreateInfos(queue_create_infos, queue_prioritie, queue_families);
|
||||
auto extensions = Creator.EnabledExtensionNames();
|
||||
VkDeviceCreateInfo device_create_info = {
|
||||
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType
|
||||
nullptr, // const void * pNext
|
||||
0, // VkDeviceCreateFlags flags
|
||||
static_cast<uint32_t>(queue_create_infos.size()), // uint32_t queueCreateInfoCount
|
||||
queue_create_infos.data(), // const VkDeviceQueueCreateInfo * pQueueCreateInfos
|
||||
0, // uint32_t enabledLayerCount
|
||||
nullptr, // const char * const * ppEnabledLayerNames
|
||||
static_cast<uint32_t>(extensions.size()), // uint32_t enabledExtensionCount
|
||||
extensions.data(), // const char * const * ppEnabledExtensionNames
|
||||
&Creator.desiredPhysicalDeviceFeatures // const VkPhysicalDeviceFeatures * pEnabledFeatures
|
||||
};
|
||||
#ifdef _USE_GRAPHIC_DEBUG
|
||||
auto layers = Creator.EnabledLayerNames();
|
||||
device_create_info.enabledLayerCount = layers.size();
|
||||
device_create_info.ppEnabledLayerNames = layers.data();
|
||||
#endif // _USE_GRAPHIC_DEBUG
|
||||
VkResult result = vkCreateDevice(mPhysical, &device_create_info, nullptr, &mPtr);
|
||||
if ((result != VK_SUCCESS) || (mPtr == VK_NULL_HANDLE)) {
|
||||
zlog::error("Could not create logical device.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
VkCommandPool Device::CreateCommandPool(const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator)
|
||||
{
|
||||
|
||||
@ -18,8 +18,6 @@ namespace vulkanapi {
|
||||
}
|
||||
public:
|
||||
Device(DeviceCreator& Creator);
|
||||
|
||||
uint32_t GetQueueFamilyIndex(VkQueueFlags flag);
|
||||
VkCommandPool CreateCommandPool(const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator);
|
||||
VkQueue GetQueue(uint32_t familyIndex, uint32_t queueIndex);
|
||||
VkDescriptorPool CreateDescriptorPool(const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "device.h"
|
||||
#include "device_creator.h"
|
||||
#include "instance.h"
|
||||
#include "zlog.h"
|
||||
namespace vulkanapi {
|
||||
DeviceCreator::DeviceCreator(Instance& instance)
|
||||
@ -23,10 +24,100 @@ namespace vulkanapi {
|
||||
AddLayer("VK_LAYER_RENDERDOC_Capture");
|
||||
#endif
|
||||
}
|
||||
void DeviceCreator::QueueCreateInfos(std::vector<VkDeviceQueueCreateInfo>& queue_create_infos, std::vector<VkQueueFamilyProperties>& queue_families)
|
||||
bool DeviceCreator::CheckProperty(const VkPhysicalDevice device)
|
||||
{
|
||||
std::vector<VkLayerProperties> availableLayers();
|
||||
|
||||
VkPhysicalDeviceProperties deviceProperties;
|
||||
vkGetPhysicalDeviceProperties(device, &deviceProperties);
|
||||
return (deviceProperties.deviceType & desiredPhysicalDeviceType) == desiredPhysicalDeviceType;
|
||||
}
|
||||
bool DeviceCreator::CheckExtension(const VkPhysicalDevice device)
|
||||
{
|
||||
uint32_t extensionCount = 0;
|
||||
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
|
||||
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
|
||||
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
|
||||
for (const auto& desiredExtension : desiredExtensions)
|
||||
{
|
||||
bool find = false;
|
||||
for (const auto& availableExtension : availableExtensions)
|
||||
{
|
||||
if (strcmp(availableExtension.extensionName, desiredExtension.c_str()) == 0)
|
||||
{
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!find)return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool DeviceCreator::FindDevice(VkPhysicalDevice& device)
|
||||
{
|
||||
std::vector<VkPhysicalDevice> available_devices;
|
||||
instance.EnumerateAvailablePhysicalDevices(available_devices);
|
||||
for (int i = 0, size = available_devices.size(); i < size;i++)
|
||||
{
|
||||
device = available_devices[i];
|
||||
if (!CheckProperty(device))continue;
|
||||
if (!CheckExtension(device))continue;
|
||||
#ifdef _USE_GRAPHIC_DEBUG
|
||||
if (!CheckLayer(device))continue;
|
||||
#endif // _USE_GRAPHIC_DEBUG
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
std::vector<char const*> DeviceCreator::EnabledExtensionNames()
|
||||
{
|
||||
std::vector<char const*> _extension;
|
||||
for (int i = 0, l = desiredExtensions.size(); i < l; i++) {
|
||||
_extension.push_back(desiredExtensions[i].c_str());
|
||||
}
|
||||
return _extension;
|
||||
}
|
||||
void DeviceCreator::QueueCreateInfos(std::vector<VkDeviceQueueCreateInfo>& queue_create_infos, std::vector<std::vector<float>>& queue_prioritie,
|
||||
std::vector<VkQueueFamilyProperties>& queue_families)
|
||||
{
|
||||
uint32_t size = queue_families.size();
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
VkDeviceQueueCreateInfo queueCreateInfo{};
|
||||
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queueCreateInfo.queueFamilyIndex = i;
|
||||
queueCreateInfo.queueCount = 0;
|
||||
queue_create_infos.push_back(queueCreateInfo);
|
||||
queue_prioritie.emplace_back(std::vector<float>{});
|
||||
}
|
||||
uint32_t max_value = 1;
|
||||
for (const auto& queue : desiredQueues) {
|
||||
uint32_t index = -1;
|
||||
bool bFind = false;
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
auto family = queue_families[i];
|
||||
if ((family.queueFlags & queue.flag) == queue.flag) {
|
||||
index = i;
|
||||
if (queue_create_infos[i].queueCount < max_value * family.queueCount) {
|
||||
bFind = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (index != -1 && queue_create_infos[index].queueCount < queue_families[index].queueCount) {
|
||||
queue_create_infos[index].queueCount++;
|
||||
queue_prioritie[index].push_back(queue.prioritie);
|
||||
}
|
||||
if (!bFind)
|
||||
max_value++;
|
||||
}
|
||||
auto it = queue_create_infos.begin();
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
if (it->queueCount == 0) {
|
||||
it = queue_create_infos.erase(it);
|
||||
}
|
||||
else {
|
||||
it->pQueuePriorities = queue_prioritie[i].data();
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
void DeviceCreator::AddExtension(std::string extensionName)
|
||||
{
|
||||
@ -37,5 +128,50 @@ namespace vulkanapi {
|
||||
{
|
||||
desiredLayers.push_back(layerName);
|
||||
}
|
||||
bool DeviceCreator::CheckLayer(const VkPhysicalDevice device)
|
||||
{
|
||||
uint32_t layerCount = 0;
|
||||
vkEnumerateDeviceLayerProperties(device, &layerCount, nullptr);
|
||||
std::vector<VkLayerProperties> availableLayers(layerCount);
|
||||
vkEnumerateDeviceLayerProperties(device, &layerCount, availableLayers.data());
|
||||
for (const auto& desiredLayer : desiredLayers)
|
||||
{
|
||||
bool find = false;
|
||||
for (const auto& availableLayer : availableLayers)
|
||||
{
|
||||
if (strcmp(availableLayer.layerName, desiredLayer.c_str()) == 0)
|
||||
{
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!find)return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
std::vector<char const*> DeviceCreator::EnabledLayerNames()
|
||||
{
|
||||
std::vector<char const*> _extension;
|
||||
for (int i = 0, l = desiredLayers.size(); i < l; i++) {
|
||||
_extension.push_back(desiredLayers[i].c_str());
|
||||
}
|
||||
return _extension;
|
||||
}
|
||||
#endif
|
||||
bool DeviceCreator::CheckAvailableQueueFamilies(VkPhysicalDevice physical_device, std::vector<VkQueueFamilyProperties>& queue_families) {
|
||||
uint32_t queue_families_count = 0;
|
||||
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, nullptr);
|
||||
if (queue_families_count == 0) {
|
||||
zlog::error("Could not get the number of queue families.");
|
||||
return false;
|
||||
}
|
||||
queue_families.resize(queue_families_count);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, queue_families.data());
|
||||
if (queue_families_count == 0) {
|
||||
zlog::error("Could not acquire properties of queue families.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -16,7 +16,7 @@ namespace vulkanapi {
|
||||
VkQueueFlags flag;
|
||||
float prioritie;
|
||||
DesiredQueue(std::string name, VkQueueFlags flag, float prioritie)
|
||||
: name(name), flag(flag), prioritie(prioritie){}
|
||||
: name(name), flag(flag), prioritie(prioritie) {}
|
||||
};
|
||||
public:
|
||||
VkPhysicalDeviceFeatures desiredPhysicalDeviceFeatures;
|
||||
@ -31,12 +31,21 @@ namespace vulkanapi {
|
||||
void AddQueue(std::string name, VkQueueFlags flag, float prioritie);
|
||||
void AddExtension(std::string extensionName);
|
||||
void AddWindowExtension();
|
||||
void QueueCreateInfos(std::vector<VkDeviceQueueCreateInfo>& queue_create_infos, std::vector<VkQueueFamilyProperties>& queue_families);
|
||||
bool CheckProperty(const VkPhysicalDevice device);
|
||||
bool CheckExtension(const VkPhysicalDevice device);
|
||||
bool FindDevice(VkPhysicalDevice& device);
|
||||
std::vector<char const*> EnabledExtensionNames();
|
||||
void QueueCreateInfos(std::vector<VkDeviceQueueCreateInfo>& queue_create_infos,
|
||||
std::vector<std::vector<float>>& queue_prioritie,
|
||||
std::vector<VkQueueFamilyProperties>& queue_families);
|
||||
#ifdef _USE_GRAPHIC_DEBUG
|
||||
public:
|
||||
std::vector<std::string> desiredLayers;
|
||||
void AddLayer(std::string layerName);
|
||||
bool CheckLayer(const VkPhysicalDevice device);
|
||||
std::vector<char const*> EnabledLayerNames();
|
||||
#endif
|
||||
private:
|
||||
|
||||
static bool CheckAvailableQueueFamilies(VkPhysicalDevice physical_device, std::vector<VkQueueFamilyProperties>& queue_families);
|
||||
};
|
||||
};
|
||||
@ -1,43 +1,50 @@
|
||||
#include "swapchain.h"
|
||||
#include "swapchain_help.h"
|
||||
#include "swapchain_creator.h"
|
||||
#include "device.h"
|
||||
#include "image.h"
|
||||
#include "zlog.h"
|
||||
namespace vulkanapi {
|
||||
Swapchain::Swapchain(Device& device, int frames, int width, int height, VkSurfaceKHR presentation_surface)
|
||||
Swapchain::Swapchain(SwapchainCreator& Creator)
|
||||
: mPtr(nullptr)
|
||||
{
|
||||
uint32_t queue_family_index;
|
||||
VkPhysicalDevice physical_device = device.GetPhysical();
|
||||
|
||||
//选择交换链图像的格式与颜色空间
|
||||
VkFormat image_format;
|
||||
VkColorSpaceKHR image_color_space;
|
||||
SelectFormatOfSwapchainImages(physical_device, presentation_surface, { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
|
||||
image_format, image_color_space);
|
||||
|
||||
VkSurfaceCapabilitiesKHR surface_capabilities;
|
||||
GetCapabilitiesOfPresentationSurface(physical_device, presentation_surface, surface_capabilities);
|
||||
|
||||
VkExtent2D image_size{ (uint32_t)width ,(uint32_t)height };
|
||||
ChooseSizeOfSwapchainImages(surface_capabilities, image_size);
|
||||
|
||||
//调用设备接口,创建交换链
|
||||
VkSwapchainKHR old_swapchain = VK_NULL_HANDLE;
|
||||
VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
CreateSwapchain(device.Ptr(), presentation_surface, frames, { image_format, image_color_space }, image_size
|
||||
, imageUsage, VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,VK_PRESENT_MODE_FIFO_KHR, old_swapchain, mPtr);
|
||||
|
||||
VkSurfaceCapabilitiesKHR capabilities{};
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(Creator.device.GetPhysical(), Creator.presentation_surface, &capabilities);
|
||||
VkExtent2D image_extent = Creator.EnableImageExtent2D(capabilities);
|
||||
VkSwapchainCreateInfoKHR swapchain_create_info = {
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,// VkStructureType sType
|
||||
nullptr, // const void * pNext
|
||||
0, // VkSwapchainCreateFlagsKHR flags
|
||||
Creator.presentation_surface, // VkSurfaceKHR surface
|
||||
(uint32_t)Creator.frames, // uint32_t minImageCount
|
||||
Creator.imageFormat, // VkFormat imageFormat
|
||||
Creator.imageColorSpace, // VkColorSpaceKHR imageColorSpace
|
||||
image_extent, // VkExtent2D imageExtent
|
||||
1, // uint32_t imageArrayLayers
|
||||
Creator.imageUsage, // VkImageUsageFlags imageUsage
|
||||
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode imageSharingMode
|
||||
0, // uint32_t queueFamilyIndexCount
|
||||
nullptr, // const uint32_t * pQueueFamilyIndices
|
||||
capabilities.currentTransform, // VkSurfaceTransformFlagBitsKHR preTransform
|
||||
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, // VkCompositeAlphaFlagBitsKHR compositeAlpha
|
||||
Creator.presentMode, // VkPresentModeKHR presentMode
|
||||
VK_TRUE, // VkBool32 clipped
|
||||
VK_NULL_HANDLE // VkSwapchainKHR oldSwapchain
|
||||
};
|
||||
VkResult result = vkCreateSwapchainKHR(Creator.device.Ptr(), &swapchain_create_info, nullptr, &mPtr);
|
||||
if (result != VK_SUCCESS) {
|
||||
zlog::error("Failed to create swap chain.");
|
||||
}
|
||||
std::vector<VkImage> swapchain_images;
|
||||
GetHandlesOfSwapchainImages(device.Ptr(), mPtr, swapchain_images);
|
||||
Creator.CreateSwapchainImages(mPtr, swapchain_images);
|
||||
uint32_t image_count = swapchain_images.size();
|
||||
for (auto img : swapchain_images) {
|
||||
mImages.push_back(new Image(device, img, Image::Args{
|
||||
mImages.push_back(new Image(Creator.device, img, Image::Args{
|
||||
1,
|
||||
"",
|
||||
width, height,
|
||||
1, 1, 1,
|
||||
image_format, imageUsage,
|
||||
1, 1, 1, 1}));
|
||||
"",
|
||||
(int)Creator.width, (int)Creator.height,
|
||||
1, 1, 1,
|
||||
Creator.imageFormat, Creator.imageUsage,
|
||||
1, 1, 1, 1}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,13 +4,14 @@
|
||||
#include "../vulkan.h"
|
||||
|
||||
namespace vulkanapi {
|
||||
class Device;
|
||||
class Image;
|
||||
class SwapchainCreator;
|
||||
class Swapchain {
|
||||
friend class SwapchainCreator;
|
||||
protected:
|
||||
VkSwapchainKHR mPtr;
|
||||
std::vector<Image*> mImages;
|
||||
public:
|
||||
Swapchain(Device& device,int frames, int width, int height, VkSurfaceKHR presentation_surface);
|
||||
Swapchain(SwapchainCreator& Creator);
|
||||
};
|
||||
};
|
||||
43
engine/src/engine/vulkanapi/wrapper/swapchain_creator.cpp
Normal file
43
engine/src/engine/vulkanapi/wrapper/swapchain_creator.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "swapchain_creator.h"
|
||||
#include "device.h"
|
||||
#include <algorithm>
|
||||
namespace vulkanapi {
|
||||
SwapchainCreator::SwapchainCreator(Device& device, int frames, uint32_t width, uint32_t height,
|
||||
VkSurfaceKHR presentation_surface)
|
||||
: device(device)
|
||||
, presentation_surface(presentation_surface)
|
||||
, frames(frames)
|
||||
, width(width)
|
||||
, height(height)
|
||||
, imageFormat(VkFormat::VK_FORMAT_B8G8R8A8_SRGB)
|
||||
, imageColorSpace(VkColorSpaceKHR::VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||
, presentMode(VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR)
|
||||
, imageUsage(VkImageUsageFlagBits::VK_IMAGE_USAGE_TRANSFER_DST_BIT)
|
||||
, maxFrameInFlightCount(2)
|
||||
{
|
||||
|
||||
}
|
||||
VkExtent2D SwapchainCreator::EnableImageExtent2D(VkSurfaceCapabilitiesKHR& capabilities)
|
||||
{
|
||||
VkExtent2D image_extent{ width , height };
|
||||
if (capabilities.currentExtent.width != 0xFFFFFFFF)
|
||||
{
|
||||
image_extent = capabilities.currentExtent;
|
||||
}
|
||||
else
|
||||
{
|
||||
image_extent.width = std::clamp(image_extent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
|
||||
image_extent.height = std::clamp(image_extent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
||||
}
|
||||
return image_extent;
|
||||
}
|
||||
bool SwapchainCreator::CreateSwapchainImages(VkSwapchainKHR swapchain, std::vector<VkImage>& swapchain_images)
|
||||
{
|
||||
uint32_t imageCount = 0;
|
||||
vkGetSwapchainImagesKHR(device.Ptr(), swapchain, &imageCount, nullptr);
|
||||
std::vector<VkImage> scImages = std::vector<VkImage>(imageCount);
|
||||
swapchain_images.resize(imageCount);
|
||||
vkGetSwapchainImagesKHR(device.Ptr(), swapchain, &imageCount, swapchain_images.data());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
30
engine/src/engine/vulkanapi/wrapper/swapchain_creator.h
Normal file
30
engine/src/engine/vulkanapi/wrapper/swapchain_creator.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "../vulkan.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace vulkanapi {
|
||||
class Device;
|
||||
class SwapchainCreator {
|
||||
friend class Swapchain;
|
||||
public:
|
||||
int frames;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
std::string title;
|
||||
VkFormat imageFormat;
|
||||
VkColorSpaceKHR imageColorSpace;
|
||||
VkPresentModeKHR presentMode;
|
||||
VkImageUsageFlags imageUsage;
|
||||
uint32_t maxFrameInFlightCount;
|
||||
|
||||
public:
|
||||
VkSurfaceKHR presentation_surface;
|
||||
Device& device;
|
||||
public:
|
||||
SwapchainCreator(Device& device,int frames,uint32_t width, uint32_t height, VkSurfaceKHR presentation_surface);
|
||||
|
||||
VkExtent2D EnableImageExtent2D(VkSurfaceCapabilitiesKHR& capabilities);
|
||||
bool CreateSwapchainImages(VkSwapchainKHR swapchain,std::vector<VkImage>& swapchain_images);
|
||||
};
|
||||
};
|
||||
@ -1,162 +0,0 @@
|
||||
#pragma once
|
||||
#include "instance.h"
|
||||
#include <iostream>
|
||||
#include "zlog.h"
|
||||
namespace vulkanapi {
|
||||
bool GetCapabilitiesOfPresentationSurface(VkPhysicalDevice physical_device,
|
||||
VkSurfaceKHR presentation_surface,
|
||||
VkSurfaceCapabilitiesKHR& surface_capabilities) {
|
||||
VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, presentation_surface, &surface_capabilities);
|
||||
|
||||
if (VK_SUCCESS != result) {
|
||||
zlog::error("Could not get the capabilities of a presentation surface.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool ChooseSizeOfSwapchainImages(VkSurfaceCapabilitiesKHR const& surface_capabilities,
|
||||
VkExtent2D& size_of_images) {
|
||||
if (0xFFFFFFFF == surface_capabilities.currentExtent.width) {
|
||||
if (size_of_images.width < surface_capabilities.minImageExtent.width) {
|
||||
size_of_images.width = surface_capabilities.minImageExtent.width;
|
||||
}
|
||||
else if (size_of_images.width > surface_capabilities.maxImageExtent.width) {
|
||||
size_of_images.width = surface_capabilities.maxImageExtent.width;
|
||||
}
|
||||
|
||||
if (size_of_images.height < surface_capabilities.minImageExtent.height) {
|
||||
size_of_images.height = surface_capabilities.minImageExtent.height;
|
||||
}
|
||||
else if (size_of_images.height > surface_capabilities.maxImageExtent.height) {
|
||||
size_of_images.height = surface_capabilities.maxImageExtent.height;
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_of_images = surface_capabilities.currentExtent;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool SelectFormatOfSwapchainImages(VkPhysicalDevice physical_device,
|
||||
VkSurfaceKHR presentation_surface,
|
||||
VkSurfaceFormatKHR desired_surface_format,
|
||||
VkFormat& image_format,
|
||||
VkColorSpaceKHR& image_color_space) {
|
||||
// Enumerate supported formats
|
||||
uint32_t formats_count = 0;
|
||||
VkResult result = VK_SUCCESS;
|
||||
|
||||
result = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, presentation_surface, &formats_count, nullptr);
|
||||
if ((VK_SUCCESS != result) ||
|
||||
(0 == formats_count)) {
|
||||
zlog::error("Could not get the number of supported surface formats.");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<VkSurfaceFormatKHR> surface_formats(formats_count);
|
||||
result = vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, presentation_surface, &formats_count, surface_formats.data());
|
||||
if ((VK_SUCCESS != result) ||
|
||||
(0 == formats_count)) {
|
||||
zlog::error("Could not enumerate supported surface formats.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Select surface format
|
||||
if ((1 == surface_formats.size()) &&
|
||||
(VK_FORMAT_UNDEFINED == surface_formats[0].format)) {
|
||||
image_format = desired_surface_format.format;
|
||||
image_color_space = desired_surface_format.colorSpace;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto& surface_format : surface_formats) {
|
||||
if ((desired_surface_format.format == surface_format.format) &&
|
||||
(desired_surface_format.colorSpace == surface_format.colorSpace)) {
|
||||
image_format = desired_surface_format.format;
|
||||
image_color_space = desired_surface_format.colorSpace;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& surface_format : surface_formats) {
|
||||
if (desired_surface_format.format == surface_format.format) {
|
||||
image_format = desired_surface_format.format;
|
||||
image_color_space = surface_format.colorSpace;
|
||||
zlog::error("Desired combination of format and colorspace is not supported. Selecting other colorspace.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
image_format = surface_formats[0].format;
|
||||
image_color_space = surface_formats[0].colorSpace;
|
||||
zlog::error("Desired format is not supported. Selecting available format - colorspace combination.");
|
||||
return true;
|
||||
}
|
||||
bool CreateSwapchain(VkDevice logical_device,
|
||||
VkSurfaceKHR presentation_surface,
|
||||
uint32_t image_count,
|
||||
VkSurfaceFormatKHR surface_format,
|
||||
VkExtent2D image_size,
|
||||
VkImageUsageFlags image_usage,
|
||||
VkSurfaceTransformFlagBitsKHR surface_transform,
|
||||
VkPresentModeKHR present_mode,
|
||||
VkSwapchainKHR& old_swapchain,
|
||||
VkSwapchainKHR& swapchain) {
|
||||
VkSwapchainCreateInfoKHR swapchain_create_info = {
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, // VkStructureType sType
|
||||
nullptr, // const void * pNext
|
||||
0, // VkSwapchainCreateFlagsKHR flags
|
||||
presentation_surface, // VkSurfaceKHR surface
|
||||
image_count, // uint32_t minImageCount
|
||||
surface_format.format, // VkFormat imageFormat
|
||||
surface_format.colorSpace, // VkColorSpaceKHR imageColorSpace
|
||||
image_size, // VkExtent2D imageExtent
|
||||
1, // uint32_t imageArrayLayers
|
||||
image_usage, // VkImageUsageFlags imageUsage
|
||||
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode imageSharingMode
|
||||
0, // uint32_t queueFamilyIndexCount
|
||||
nullptr, // const uint32_t * pQueueFamilyIndices
|
||||
surface_transform, // VkSurfaceTransformFlagBitsKHR preTransform
|
||||
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, // VkCompositeAlphaFlagBitsKHR compositeAlpha
|
||||
present_mode, // VkPresentModeKHR presentMode
|
||||
VK_TRUE, // VkBool32 clipped
|
||||
old_swapchain // VkSwapchainKHR oldSwapchain
|
||||
};
|
||||
|
||||
VkResult result = vkCreateSwapchainKHR(logical_device, &swapchain_create_info, nullptr, &swapchain);
|
||||
if ((VK_SUCCESS != result) ||
|
||||
(VK_NULL_HANDLE == swapchain)) {
|
||||
zlog::error("Could not create a swapchain.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (VK_NULL_HANDLE != old_swapchain) {
|
||||
vkDestroySwapchainKHR(logical_device, old_swapchain, nullptr);
|
||||
old_swapchain = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool GetHandlesOfSwapchainImages(VkDevice logical_device,
|
||||
VkSwapchainKHR swapchain,
|
||||
std::vector<VkImage>& swapchain_images) {
|
||||
uint32_t images_count = 0;
|
||||
VkResult result = VK_SUCCESS;
|
||||
|
||||
result = vkGetSwapchainImagesKHR(logical_device, swapchain, &images_count, nullptr);
|
||||
if ((VK_SUCCESS != result) ||
|
||||
(0 == images_count)) {
|
||||
zlog::error("Could not get the number of swapchain images.");
|
||||
return false;
|
||||
}
|
||||
|
||||
swapchain_images.resize(images_count);
|
||||
result = vkGetSwapchainImagesKHR(logical_device, swapchain, &images_count, swapchain_images.data());
|
||||
if ((VK_SUCCESS != result) ||
|
||||
(0 == images_count)) {
|
||||
zlog::error("Could not enumerate swapchain images.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user