Compare commits
9 Commits
feature/pr
...
a94f2da6b2
| Author | SHA1 | Date | |
|---|---|---|---|
| a94f2da6b2 | |||
| 9bcb8385fe | |||
| a0b3325e1d | |||
| e3c4267fc2 | |||
| cedb80cb03 | |||
| 6835359510 | |||
| e6b98362b6 | |||
| 0194699815 | |||
| 302b680a48 |
@@ -34,8 +34,6 @@ add_library(maiden_core STATIC
|
|||||||
src/Window.cpp
|
src/Window.cpp
|
||||||
src/Engine.cpp
|
src/Engine.cpp
|
||||||
src/Device.cpp
|
src/Device.cpp
|
||||||
src/Pipeline.cpp
|
|
||||||
src/Swapchain.cpp
|
|
||||||
# include extra source files here
|
# include extra source files here
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,7 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
Device::Device(vk::raii::Instance* instance, Window* window): instance_(instance), window_(window) {
|
Device::Device(vk::raii::Instance* instance): instance_(instance) {
|
||||||
|
|
||||||
selectPhysicalDevice();
|
|
||||||
createSurface();
|
|
||||||
createLogicalDevice();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +55,7 @@ uint32_t Device::evaluatePhysicalDevice(vk::raii::PhysicalDevice& device) {
|
|||||||
if(deviceProperties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) {
|
if(deviceProperties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) {
|
||||||
score += 2;
|
score += 2;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Warning: physical device " << deviceProperties.deviceName << " is not a discrete device!" << std::endl;
|
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Warning: physical device " << deviceProperties.deviceName << " is not a discrete device!" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prefer devices that support vulkan 1.3
|
// prefer devices that support vulkan 1.3
|
||||||
@@ -108,92 +104,3 @@ uint32_t Device::evaluatePhysicalDevice(vk::raii::PhysicalDevice& device) {
|
|||||||
|
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::createLogicalDevice() {
|
|
||||||
|
|
||||||
if(surface_ == nullptr) {
|
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Error: cannot create logical device without a valid presentation surface." << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(physicalDevice_ == nullptr) {
|
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Error: cannot create logical device without a valid physical device." << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// specify queue family requirements
|
|
||||||
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice_.getQueueFamilyProperties();
|
|
||||||
int32_t queueIndex = -1;
|
|
||||||
for(uint32_t qfpIndex = 0; qfpIndex < queueFamilyProperties.size(); qfpIndex++) {
|
|
||||||
if((queueFamilyProperties[qfpIndex].queueFlags & vk::QueueFlagBits::eGraphics) && physicalDevice_.getSurfaceSupportKHR(qfpIndex, *surface_)) {
|
|
||||||
queueIndex = static_cast<int32_t>(qfpIndex);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(queueIndex <= -1) {
|
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Error: could not locate valid graphics queues." << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
float queuePriority = 0.5f;
|
|
||||||
vk::DeviceQueueCreateInfo deviceQueueCreateInfo {
|
|
||||||
.queueFamilyIndex = static_cast<uint32_t>(queueIndex),
|
|
||||||
.queueCount = 1,
|
|
||||||
.pQueuePriorities = &queuePriority
|
|
||||||
};
|
|
||||||
|
|
||||||
// specify device feature requirements
|
|
||||||
vk::PhysicalDeviceVulkan13Features deviceFeatures = { .dynamicRendering = true };
|
|
||||||
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT deviceStateFeatures = { . extendedDynamicState = true };
|
|
||||||
vk::StructureChain<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan13Features, vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT> featureChain = {
|
|
||||||
{}, // empty for now
|
|
||||||
deviceFeatures,
|
|
||||||
deviceStateFeatures
|
|
||||||
};
|
|
||||||
|
|
||||||
// create logical device
|
|
||||||
vk::DeviceCreateInfo deviceCreateInfo {
|
|
||||||
.pNext = &featureChain.get<vk::PhysicalDeviceFeatures2>(),
|
|
||||||
.queueCreateInfoCount = 1,
|
|
||||||
.pQueueCreateInfos = &deviceQueueCreateInfo,
|
|
||||||
.enabledExtensionCount = static_cast<uint32_t>(requiredDeviceExtensions_.size()),
|
|
||||||
.ppEnabledExtensionNames = requiredDeviceExtensions_.data()
|
|
||||||
};
|
|
||||||
logicalDevice_ = vk::raii::Device(physicalDevice_, deviceCreateInfo);
|
|
||||||
|
|
||||||
// initialize the graphics queue
|
|
||||||
graphicsQueue_ = vk::raii::Queue(logicalDevice_, queueIndex, 0);
|
|
||||||
|
|
||||||
if(logicalDevice_ != nullptr) {
|
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Info: Created logcal device" << std::endl;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Error: could not create a valid logical device." << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::createSurface() {
|
|
||||||
|
|
||||||
(void)window_->createSurface(instance_, &surface_);
|
|
||||||
|
|
||||||
if(surface_ == nullptr) {
|
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Error creating surface!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(physicalDevice_ == nullptr) {
|
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Error: cannot create surface without a physical device!" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto surfaceCapabilities = physicalDevice_.getSurfaceCapabilitiesKHR(*surface_);
|
|
||||||
std::vector<vk::SurfaceFormatKHR> availableFormats = physicalDevice_.getSurfaceFormatsKHR(*surface_);
|
|
||||||
std::vector<vk::PresentModeKHR> availablePresentModes = physicalDevice_.getSurfacePresentModesKHR(*surface_);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Device::getExtent(int32_t* width, int32_t* height) {
|
|
||||||
return window_->getExtent(width, height);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,45 +3,23 @@
|
|||||||
|
|
||||||
#include <vulkan/vulkan_raii.hpp>
|
#include <vulkan/vulkan_raii.hpp>
|
||||||
|
|
||||||
#include "Window.hpp"
|
class Device {
|
||||||
|
|
||||||
class Device {
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Device(vk::raii::Instance* instance, Window* window);
|
Device(vk::raii::Instance* instance);
|
||||||
~Device();
|
~Device();
|
||||||
|
|
||||||
// helper to get the surface extent from the window
|
// assigns a capable gpu vkdevice to physicalDevice
|
||||||
bool getExtent(int32_t* width, int32_t* height);
|
bool selectPhysicalDevice();
|
||||||
vk::raii::SurfaceKHR* getSurface() { return &surface_; }
|
|
||||||
|
|
||||||
vk::raii::PhysicalDevice physicalDevice() { return physicalDevice_; }
|
|
||||||
vk::raii::Device* logicalDevice() { return &logicalDevice_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// gives a device a score to attempt to select the most capable device
|
// gives a device a score to attempt to select the most capable device
|
||||||
uint32_t evaluatePhysicalDevice(vk::raii::PhysicalDevice& device);
|
uint32_t evaluatePhysicalDevice(vk::raii::PhysicalDevice& device);
|
||||||
|
|
||||||
// creates the surface
|
|
||||||
void createSurface();
|
|
||||||
|
|
||||||
// assigns a capable gpu vkdevice to physicalDevice
|
|
||||||
bool selectPhysicalDevice();
|
|
||||||
|
|
||||||
// initializes the logical device
|
|
||||||
bool createLogicalDevice();
|
|
||||||
|
|
||||||
// vulkan objects
|
|
||||||
vk::raii::Instance* instance_ = nullptr;
|
vk::raii::Instance* instance_ = nullptr;
|
||||||
vk::raii::PhysicalDevice physicalDevice_ = nullptr;
|
vk::raii::PhysicalDevice physicalDevice_ = nullptr;
|
||||||
vk::raii::Device logicalDevice_ = nullptr;
|
|
||||||
vk::raii::Queue graphicsQueue_ = nullptr;
|
|
||||||
vk::raii::SurfaceKHR surface_ = nullptr;
|
|
||||||
|
|
||||||
// ptrs to other engine objects
|
|
||||||
Window* window_ = nullptr;
|
|
||||||
|
|
||||||
// required extensions for the physical device
|
// required extensions for the physical device
|
||||||
std::vector<const char*> requiredDeviceExtensions_ = { vk::KHRSwapchainExtensionName };
|
std::vector<const char*> requiredDeviceExtensions_ = { vk::KHRSwapchainExtensionName };
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "Device.hpp"
|
#include "Device.hpp"
|
||||||
#include "Swapchain.hpp"
|
|
||||||
|
|
||||||
Engine::Engine(Window* window): window_(window) {
|
Engine::Engine(Window* window): window_(window) {
|
||||||
|
|
||||||
@@ -23,11 +22,14 @@ void Engine::init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// device selection and setup
|
// device selection and setup
|
||||||
Device device(&instance_, window_);
|
Device device(&instance_);
|
||||||
|
device.selectPhysicalDevice();
|
||||||
// render pipeline
|
|
||||||
Swapchain swapchain(&device);
|
// next steps:
|
||||||
// Pipeline pipeline(&device, &swapchain);
|
// queue creation
|
||||||
|
// vulkan memory allocator
|
||||||
|
// create vulkan surface
|
||||||
|
// attach surface to window
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +131,7 @@ std::vector<const char*> Engine::getRequiredInstanceExtensions() {
|
|||||||
|
|
||||||
// get extensions that our windowing library requires
|
// get extensions that our windowing library requires
|
||||||
uint32_t sdlExtensionsCount = 0;
|
uint32_t sdlExtensionsCount = 0;
|
||||||
const char* const* sdlExtensions{ SDL_Vulkan_GetInstanceExtensions(&sdlExtensionsCount) }; // TODO: get this from window so all sdl3 is encapsulated there
|
const char* const* sdlExtensions{ SDL_Vulkan_GetInstanceExtensions(&sdlExtensionsCount) };
|
||||||
// what in the world is this kind of pointer btw
|
// what in the world is this kind of pointer btw
|
||||||
|
|
||||||
std::vector<const char*> requiredExtensions(sdlExtensions, sdlExtensions + static_cast<size_t>(sdlExtensionsCount));
|
std::vector<const char*> requiredExtensions(sdlExtensions, sdlExtensions + static_cast<size_t>(sdlExtensionsCount));
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
|
|
||||||
#include "Pipeline.hpp"
|
|
||||||
|
|
||||||
Pipeline::Pipeline(Device* device) : device_(device) {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Device.hpp"
|
|
||||||
|
|
||||||
// the Pipeline lays out the rendering steps for the vulkan engine to follow
|
|
||||||
class Pipeline {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Pipeline(Device* device);
|
|
||||||
~Pipeline() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Device* device_ = nullptr;
|
|
||||||
|
|
||||||
// will include shaders eventually
|
|
||||||
};
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
|
|
||||||
#include "Swapchain.hpp"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
Swapchain::Swapchain(Device* device) : device_(device) {
|
|
||||||
|
|
||||||
(void)createSwapchain();
|
|
||||||
(void)createImageViews();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Swapchain::createSwapchain() {
|
|
||||||
|
|
||||||
// get capabilities from the device
|
|
||||||
vk::raii::PhysicalDevice physicalDevice = device_->physicalDevice();
|
|
||||||
vk::raii::Device* logicalDevice = device_->logicalDevice();
|
|
||||||
vk::raii::SurfaceKHR* surface = device_->getSurface();
|
|
||||||
vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(*surface);
|
|
||||||
extent_ = chooseExtent(surfaceCapabilities);
|
|
||||||
uint32_t minImageCount = chooseMinImageCount(surfaceCapabilities);
|
|
||||||
|
|
||||||
std::vector<vk::SurfaceFormatKHR> availableFormats = physicalDevice.getSurfaceFormatsKHR(*surface);
|
|
||||||
surfaceFormat_ = chooseSurfaceFormat(availableFormats);
|
|
||||||
|
|
||||||
std::vector<vk::PresentModeKHR> availablePresentModes = physicalDevice.getSurfacePresentModesKHR(*surface);
|
|
||||||
vk::PresentModeKHR presentMode = choosePresentMode(availablePresentModes);
|
|
||||||
|
|
||||||
// create the swapchain object
|
|
||||||
vk::SwapchainCreateInfoKHR swapchainCreateInfo {
|
|
||||||
.surface = *surface,
|
|
||||||
.minImageCount = minImageCount,
|
|
||||||
.imageFormat = surfaceFormat_.format,
|
|
||||||
.imageColorSpace = surfaceFormat_.colorSpace,
|
|
||||||
.imageExtent = extent_,
|
|
||||||
.imageArrayLayers = 1, // only rendering to a single screen
|
|
||||||
.imageUsage = vk::ImageUsageFlagBits::eColorAttachment, // draw directly to swapchain image (as opposed to an offscreen image)
|
|
||||||
.imageSharingMode = vk::SharingMode::eExclusive, // owned only by a single queue
|
|
||||||
.preTransform = surfaceCapabilities.currentTransform, // dont flip or rotate the image
|
|
||||||
.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque, // use other settings if you want the window to be partly transparent :o
|
|
||||||
.presentMode = presentMode,
|
|
||||||
.clipped = true // discard fragments in the window that aren't visible (obscured by another window or minimized)
|
|
||||||
};
|
|
||||||
// TODO: [after presentation] need to handle swapchain recreation as a result of window changes
|
|
||||||
swapchainCreateInfo.oldSwapchain = nullptr;
|
|
||||||
|
|
||||||
vkSwapchain_ = vk::raii::SwapchainKHR(*logicalDevice, swapchainCreateInfo);
|
|
||||||
images_ = vkSwapchain_.getImages();
|
|
||||||
|
|
||||||
if(vkSwapchain_ == nullptr) {
|
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Error: could not create the Vulkan Swapchain!" << std::endl;
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vk::SurfaceFormatKHR Swapchain::chooseSurfaceFormat(std::vector<vk::SurfaceFormatKHR> const& availableFormats) {
|
|
||||||
|
|
||||||
if(availableFormats.empty()) {
|
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Error: no swap formats available!" << std::endl;
|
|
||||||
return vk::SurfaceFormatKHR { vk::Format::eUndefined, vk::ColorSpaceKHR::eSrgbNonlinear };
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for preferred format vk::Format::eB8G8R8A8Srgb
|
|
||||||
const auto formatIt = std::ranges::find_if(availableFormats, [](const auto& format) {
|
|
||||||
return format.format == vk::Format::eB8G8R8A8Srgb && format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear;
|
|
||||||
});
|
|
||||||
|
|
||||||
// just return whatever if the correct one doesn't exist
|
|
||||||
return formatIt != availableFormats.end() ? *formatIt : availableFormats[0];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
vk::PresentModeKHR Swapchain::choosePresentMode(std::vector<vk::PresentModeKHR> const& availablePresentModes) {
|
|
||||||
|
|
||||||
// vk::PresentModeKHR::eImmediate: present rendered fragments directly to the surface (results in frame tearing)
|
|
||||||
// vk::PresentModeKHR::eFifo: first in first out, waits for frame refresh (vsync)
|
|
||||||
// vk::PresentModeKHR::eFifoRelaxed: same as fifo but does not wait for vsync if the last frame was late
|
|
||||||
// vk::PresentModeKHR::eMailbox: same as fifo but continues rendering new frames while waiting for vsync
|
|
||||||
|
|
||||||
if(availablePresentModes.empty()) {
|
|
||||||
// fifo is guaranteed to be available so this is unreachable
|
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Error: no swap formats available!" << std::endl;
|
|
||||||
return vk::PresentModeKHR::eFifo;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefer mailbox if it exists; mailbox ensures least latency between displayed frames and cpu commands
|
|
||||||
assert(std::ranges::any_of(availablePresentModes, [](auto presentMode) { return presentMode == vk::PresentModeKHR::eFifo; }));
|
|
||||||
return std::ranges::any_of(availablePresentModes, [](const vk::PresentModeKHR value) {
|
|
||||||
return vk::PresentModeKHR::eMailbox == value; }) ? vk::PresentModeKHR::eMailbox : vk::PresentModeKHR::eFifo;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
vk::Extent2D Swapchain::chooseExtent(vk::SurfaceCapabilitiesKHR const& capabilities) {
|
|
||||||
|
|
||||||
if(capabilities.currentExtent.width != UINT32_MAX) {
|
|
||||||
return capabilities.currentExtent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise we have to get the swap extent via the window
|
|
||||||
int32_t width = 0;
|
|
||||||
int32_t height = 0;
|
|
||||||
(void)device_->getExtent(&width, &height);
|
|
||||||
vk::Extent2D extent = {
|
|
||||||
std::clamp<uint32_t>(width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width),
|
|
||||||
std::clamp<uint32_t>(height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height)
|
|
||||||
};
|
|
||||||
return extent;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Swapchain::chooseMinImageCount(vk::SurfaceCapabilitiesKHR const& capabilities) {
|
|
||||||
|
|
||||||
// prefer at least 3 images for the swapchain, otherwise default to the max the driver can support
|
|
||||||
uint32_t minImageCount = std::max(3u, capabilities.minImageCount); // TODO: magic numbers ?
|
|
||||||
if((0 < capabilities.maxImageCount) && capabilities.maxImageCount < minImageCount) {
|
|
||||||
return capabilities.maxImageCount;
|
|
||||||
} else {
|
|
||||||
return minImageCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Swapchain::createImageViews() {
|
|
||||||
|
|
||||||
if(!imageViews_.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
vk::ImageViewCreateInfo imageViewCreateInfo {
|
|
||||||
.viewType = vk::ImageViewType::e2D,
|
|
||||||
.format = surfaceFormat_.format,
|
|
||||||
.components = { vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity, vk::ComponentSwizzle::eIdentity }, // default rgba
|
|
||||||
.subresourceRange = { vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}, // aspect mask, baseMipLevel, levelCount, baseArrayLayer, layerCount
|
|
||||||
};
|
|
||||||
|
|
||||||
for(vk::Image &image : images_) {
|
|
||||||
imageViewCreateInfo.image = image;
|
|
||||||
imageViews_.emplace_back(*(device_->logicalDevice()), imageViewCreateInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Device.hpp"
|
|
||||||
|
|
||||||
// the swapchain functions as the layout for framebuffers that get written to by the gpu and read from to present to the screen
|
|
||||||
class Swapchain {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Swapchain(Device* device);
|
|
||||||
~Swapchain() = default;
|
|
||||||
|
|
||||||
std::vector<vk::Image> getImages() { return vkSwapchain_.getImages(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
vk::raii::SwapchainKHR vkSwapchain_ = nullptr;
|
|
||||||
std::vector<vk::Image> images_;
|
|
||||||
std::vector<vk::raii::ImageView> imageViews_;
|
|
||||||
|
|
||||||
Device* device_ = nullptr;
|
|
||||||
vk::SurfaceFormatKHR surfaceFormat_;
|
|
||||||
vk::PresentModeKHR presentFormat_;
|
|
||||||
vk::Extent2D extent_;
|
|
||||||
|
|
||||||
vk::SurfaceFormatKHR chooseSurfaceFormat(std::vector<vk::SurfaceFormatKHR> const& availableFormats);
|
|
||||||
vk::PresentModeKHR choosePresentMode(std::vector<vk::PresentModeKHR> const& availablePresentModes);
|
|
||||||
vk::Extent2D chooseExtent(vk::SurfaceCapabilitiesKHR const& capabilities);
|
|
||||||
uint32_t chooseMinImageCount(vk::SurfaceCapabilitiesKHR const& capabilities);
|
|
||||||
|
|
||||||
bool createSwapchain();
|
|
||||||
bool createImageViews();
|
|
||||||
|
|
||||||
};
|
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL_events.h>
|
#include <SDL3/SDL_events.h>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
Window::Window() {
|
Window::Window() {
|
||||||
|
|
||||||
@@ -44,36 +43,3 @@ void Window::handleEvent(SDL_Event& event) {
|
|||||||
rendering_ = true;
|
rendering_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::createSurface(vk::raii::Instance* instance, vk::raii::SurfaceKHR* surface) {
|
|
||||||
|
|
||||||
if(instance == nullptr) {
|
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Error: cannot create surface with a null Vulkan instance." << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __WIN32
|
|
||||||
vk::Win32SurfaceCreateInfoKHR createInfo {
|
|
||||||
.hinstance = GetModuleHandle(nullptr),
|
|
||||||
.hwnd = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(sdlWindow_), "SDL.window.win32.hwnd", nullptr);
|
|
||||||
}
|
|
||||||
surface = instance->createWin32SurfaceKHR(createInfo);
|
|
||||||
#else // linux (this technically works on windows too but vulkan gives us an explicit method for WIN32)
|
|
||||||
// its just sdl3 uses the c vulkan api and the app uses the c++ api
|
|
||||||
VkSurfaceKHR cSurface;
|
|
||||||
(void)SDL_Vulkan_CreateSurface(sdlWindow_, static_cast<VkInstance>(**instance), nullptr, &cSurface);
|
|
||||||
*surface = vk::raii::SurfaceKHR(*instance, cSurface);
|
|
||||||
#endif // __WIN32
|
|
||||||
|
|
||||||
if(surface != nullptr) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
std::cout << "[" << __FUNCTION__ << ": " << __LINE__ << "] Error: unable to create window surface." << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Window::getExtent(int32_t* width, int32_t* height) {
|
|
||||||
SDL_GetWindowSizeInPixels(sdlWindow_, width, height);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include "SDL3/SDL.h"
|
||||||
#include <SDL3/SDL_vulkan.h>
|
#include "SDL3/SDL_vulkan.h"
|
||||||
#include <vulkan/vulkan_raii.hpp>
|
|
||||||
|
|
||||||
// reference: https://wiki.libsdl.org/SDL3/SDL_CreateWindow
|
// reference: https://wiki.libsdl.org/SDL3/SDL_CreateWindow
|
||||||
class Window {
|
class Window {
|
||||||
@@ -18,8 +17,6 @@ public:
|
|||||||
|
|
||||||
bool rendering() { return rendering_; }
|
bool rendering() { return rendering_; }
|
||||||
bool open() { return open_; }
|
bool open() { return open_; }
|
||||||
bool createSurface(vk::raii::Instance* instance, vk::raii::SurfaceKHR* surface);
|
|
||||||
bool getExtent(int32_t* width, int32_t* height);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user