This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,5 @@ build/
|
||||
.zed
|
||||
!deps/JoltPhysics/Build
|
||||
.cache
|
||||
.vscode
|
||||
build-clion/
|
||||
bin/
|
||||
|
||||
77
.vscode/tasks.json
vendored
Normal file
77
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Configure: Debug",
|
||||
"type": "shell",
|
||||
"command": "cd scripts; ./configure-debug.sh",
|
||||
"group": {
|
||||
"isDefault": false
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "Configure Debug"
|
||||
},
|
||||
{
|
||||
"label": "Build: Debug",
|
||||
"type": "shell",
|
||||
"command": "cd scripts; ./build-debug.sh",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "Build Debug"
|
||||
},
|
||||
{
|
||||
"label": "Configure: Relwithdeb",
|
||||
"type": "shell",
|
||||
"command": "cd scripts; ./configure-relwithdeb.sh",
|
||||
"group": {
|
||||
"isDefault": false
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "Configure Release with debug info"
|
||||
},
|
||||
{
|
||||
"label": "Build: Relwithdeb",
|
||||
"type": "shell",
|
||||
"command": "cd scripts; ./build-relwithdeb.sh",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "Build Release with debug info"
|
||||
},
|
||||
{
|
||||
"label": "Clean: Debug",
|
||||
"type": "shell",
|
||||
"command": "cd build/debug; ninja clean",
|
||||
"group": {
|
||||
"isDefault": false
|
||||
},
|
||||
"detail": "Clean debug files"
|
||||
},
|
||||
{
|
||||
"label": "Build: All",
|
||||
"type": "shell",
|
||||
"command": "cd scripts; ./build.sh",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "Build all types"
|
||||
},
|
||||
{
|
||||
"label": "Clean: All",
|
||||
"type": "shell",
|
||||
"command": "cd scripts; ./clean.sh",
|
||||
"group": {
|
||||
"isDefault": false
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "Clean All files"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -23,14 +23,14 @@ int main() {
|
||||
|
||||
OatmealUtils::getLogger("context")->info("Creating context");
|
||||
try {
|
||||
ctx = std::make_shared<Oatmeal::ctx>(window);
|
||||
ctx = std::make_shared<Oatmeal::ctx>(window, Oatmeal::CtxCfg{.backend = Oatmeal::BACKEND_VULKAN});
|
||||
} catch (const std::exception &e) {
|
||||
OatmealUtils::getLogger("context")->critical("{}", e.what());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
OatmealUtils::getLogger("context")->info("Device name: {}", ctx->getDeviceName());
|
||||
OatmealUtils::getLogger("context")->info("Device Type: {}", ctx->getDeviceType());
|
||||
// OatmealUtils::getLogger("context")->info("Device name: {}", ctx->getDeviceName());
|
||||
// OatmealUtils::getLogger("context")->info("Device Type: {}", ctx->getDeviceType());
|
||||
|
||||
OatmealUtils::getLogger("context")->info("Starting main loop");
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
#include <stdexcept>
|
||||
#include "ctx.h"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
#include "vulkan/vulkan_raii.hpp"
|
||||
|
||||
namespace Oatmeal {
|
||||
|
||||
void ctx::createLogicalDevice() {
|
||||
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = m_physicalDevice.getQueueFamilyProperties();
|
||||
|
||||
m_queueIndex = ~0;
|
||||
for (uint32_t qfpIndex = 0; qfpIndex < queueFamilyProperties.size(); qfpIndex++) {
|
||||
if ((queueFamilyProperties[qfpIndex].queueFlags & vk::QueueFlagBits::eGraphics) &&
|
||||
m_physicalDevice.getSurfaceSupportKHR(qfpIndex, *m_surface)) {
|
||||
m_queueIndex = qfpIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_queueIndex == ~0) {
|
||||
// TODO: Find a better solution then just throwing a fit
|
||||
throw std::runtime_error("Failed to find a queue that supports graphics and presentation");
|
||||
}
|
||||
|
||||
vk::PhysicalDeviceFeatures deviceFeatures;
|
||||
|
||||
vk::StructureChain<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan13Features,
|
||||
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>
|
||||
featureChain = {
|
||||
{.features = {.samplerAnisotropy = true}},
|
||||
{.synchronization2 = true, .dynamicRendering = true},
|
||||
{.extendedDynamicState = true},
|
||||
};
|
||||
|
||||
float queuePriority = 0.5f;
|
||||
vk::DeviceQueueCreateInfo deviceQueueCreateInfo = {
|
||||
.queueFamilyIndex = m_queueIndex,
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = &queuePriority,
|
||||
};
|
||||
|
||||
vk::DeviceCreateInfo deviceCreateInfo = {
|
||||
.pNext = &featureChain.get<vk::PhysicalDeviceFeatures2>(),
|
||||
.queueCreateInfoCount = 1,
|
||||
.pQueueCreateInfos = &deviceQueueCreateInfo,
|
||||
.enabledExtensionCount = static_cast<uint32_t>(requiredDeviceExtensions.size()),
|
||||
.ppEnabledExtensionNames = requiredDeviceExtensions.data(),
|
||||
};
|
||||
|
||||
m_device = vk::raii::Device(m_physicalDevice, deviceCreateInfo);
|
||||
m_queue = vk::raii::Queue(m_device, m_queueIndex, 0);
|
||||
}
|
||||
|
||||
|
||||
std::string ctx::getDeviceName() const {
|
||||
const vk::PhysicalDeviceProperties deviceProperties = m_physicalDevice.getProperties();
|
||||
return deviceProperties.deviceName;
|
||||
}
|
||||
|
||||
std::string ctx::getDeviceType() const {
|
||||
const vk::PhysicalDeviceProperties deviceProperties = m_physicalDevice.getProperties();
|
||||
return vk::to_string(deviceProperties.deviceType);
|
||||
}
|
||||
} // namespace Oatmeal
|
||||
@@ -1,16 +1,9 @@
|
||||
#include "ctx.h"
|
||||
|
||||
namespace Oatmeal {
|
||||
ctx::ctx(GLFWwindow *window) {
|
||||
createInstance();
|
||||
m_window = window;
|
||||
createSurface();
|
||||
pickPhysicalDevice();
|
||||
m_msaaSamples = getMaxUsableSampleCount();
|
||||
createLogicalDevice();
|
||||
}
|
||||
|
||||
ctx::ctx(GLFWwindow *window, CtxCfg ctxCfg) {}
|
||||
|
||||
ctx::~ctx() {}
|
||||
|
||||
|
||||
} // namespace Oatmeal
|
||||
|
||||
@@ -1,100 +1,23 @@
|
||||
#include <sys/types.h>
|
||||
#include "vulkan/vulkan.hpp"
|
||||
#if defined(__INTELLISENSE__) || !defined(USE_CPP20_MODULES)
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
#else
|
||||
import vulkan_hpp;
|
||||
#endif
|
||||
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
#define VK_USE_PLATFORM_WIN32_KHR
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#elif defined(PLATFORM_LINUX)
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#define GLFW_EXPOSE_NATIVE_X11
|
||||
#elif defined(PLATFORM_MACOS)
|
||||
#define VK_USE_PLATFORM_MACOS_MVK
|
||||
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
#endif
|
||||
|
||||
#define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES
|
||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <GLFW/glfw3native.h>
|
||||
#include <cstdint>
|
||||
|
||||
constexpr int MAX_FRAMES_IN_FLIGHT = 2;
|
||||
const std::vector<char const *> validationLayers = {"VK_LAYER_KHRONOS_validation"};
|
||||
const std::vector<const char *> requiredDeviceExtensions = {vk::KHRSwapchainExtensionName};
|
||||
|
||||
#ifndef NDEBUG
|
||||
constexpr bool enableValidationLayers = false;
|
||||
#else
|
||||
constexpr bool enableValidationLayers = true;
|
||||
#endif
|
||||
|
||||
namespace Oatmeal {
|
||||
|
||||
enum Backend {
|
||||
BACKEND_VULKAN,
|
||||
};
|
||||
|
||||
struct CtxCfg {
|
||||
Backend backend;
|
||||
};
|
||||
|
||||
|
||||
class ctx {
|
||||
public:
|
||||
ctx(GLFWwindow *window);
|
||||
|
||||
std::string getDeviceName() const;
|
||||
std::string getDeviceType() const;
|
||||
|
||||
ctx(GLFWwindow *window, CtxCfg cfg);
|
||||
~ctx();
|
||||
|
||||
private:
|
||||
// Members //
|
||||
|
||||
GLFWwindow *m_window = nullptr;
|
||||
|
||||
vk::raii::Context m_context;
|
||||
vk::raii::Instance m_instance = nullptr;
|
||||
vk::DebugUtilsMessengerEXT m_debugMessenger = nullptr;
|
||||
vk::raii::PhysicalDevice m_physicalDevice = nullptr;
|
||||
vk::raii::Device m_device = nullptr;
|
||||
vk::raii::Queue m_queue = nullptr;
|
||||
uint32_t m_queueIndex;
|
||||
|
||||
vk::raii::SurfaceKHR m_surface = nullptr;
|
||||
vk::raii::SwapchainKHR m_swapchain = nullptr;
|
||||
std::vector<vk::Image> m_swapchainImages;
|
||||
vk::SurfaceFormatKHR m_swapchainSurfaceFormat;
|
||||
vk::Extent2D m_swapchainExtent;
|
||||
std::vector<vk::raii::ImageView> m_swapchainImageViews;
|
||||
std::vector<vk::raii::Semaphore> m_presentCompleteSemaphores;
|
||||
std::vector<vk::raii::Semaphore> m_renderFinishSemaphores;
|
||||
std::vector<vk::raii::Fence> m_inFlightFences;
|
||||
bool m_framebufferResized = false;
|
||||
uint32_t m_frameIndex = 0;
|
||||
|
||||
vk::SampleCountFlagBits m_msaaSamples = vk::SampleCountFlagBits::e1;
|
||||
vk::raii::Image m_colorImage = nullptr;
|
||||
vk::raii::DeviceMemory m_colorImageMemory = nullptr;
|
||||
vk::raii::ImageView m_colorImageView = nullptr;
|
||||
|
||||
vk::raii::Image m_depthImage = nullptr;
|
||||
vk::raii::DeviceMemory m_depthImageMemory = nullptr;
|
||||
vk::raii::ImageView m_depthImageView = nullptr;
|
||||
vk::Format m_depthFormat;
|
||||
|
||||
// Functions //
|
||||
|
||||
void createInstance();
|
||||
std::vector<const char *> getRequiredExtensions();
|
||||
void setupDebugMessenger();
|
||||
|
||||
void createSurface();
|
||||
|
||||
void pickPhysicalDevice();
|
||||
bool isPhysicalDeviceSupported(vk::raii::PhysicalDevice device);
|
||||
uint32_t scorePhysicalDevice(vk::raii::PhysicalDevice device);
|
||||
vk::SampleCountFlagBits getMaxUsableSampleCount();
|
||||
|
||||
void createLogicalDevice();
|
||||
};
|
||||
|
||||
|
||||
} // namespace Oatmeal
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#include "ctx.h"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
|
||||
namespace Oatmeal {
|
||||
|
||||
vk::SampleCountFlagBits ctx::getMaxUsableSampleCount() {
|
||||
vk::PhysicalDeviceProperties physicalDeviceProperties = m_physicalDevice.getProperties();
|
||||
|
||||
vk::SampleCountFlags count = physicalDeviceProperties.limits.framebufferColorSampleCounts &
|
||||
physicalDeviceProperties.limits.framebufferDepthSampleCounts;
|
||||
|
||||
if (count & vk::SampleCountFlagBits::e16) {
|
||||
return vk::SampleCountFlagBits::e16;
|
||||
}
|
||||
if (count & vk::SampleCountFlagBits::e8) {
|
||||
return vk::SampleCountFlagBits::e8;
|
||||
}
|
||||
if (count & vk::SampleCountFlagBits::e4) {
|
||||
return vk::SampleCountFlagBits::e4;
|
||||
}
|
||||
if (count & vk::SampleCountFlagBits::e2) {
|
||||
return vk::SampleCountFlagBits::e2;
|
||||
}
|
||||
|
||||
return vk::SampleCountFlagBits::e1;
|
||||
}
|
||||
} // namespace Oatmeal
|
||||
@@ -1,114 +0,0 @@
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <vulkan/vk_platform.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include "ctx.h"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
|
||||
namespace Oatmeal {
|
||||
|
||||
void ctx::createInstance() {
|
||||
// Create the application info
|
||||
constexpr vk::ApplicationInfo appInfo{
|
||||
.pApplicationName = "Oatmeal",
|
||||
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||
.pEngineName = "No engine",
|
||||
.engineVersion = VK_MAKE_API_VERSION(1, 0, 0, 0),
|
||||
.apiVersion = vk::ApiVersion14,
|
||||
};
|
||||
|
||||
// Loop through the required layers, making sure they are supported
|
||||
std::vector<char const *> requiredLayers;
|
||||
if (enableValidationLayers) {
|
||||
requiredLayers.assign(validationLayers.begin(), validationLayers.end());
|
||||
}
|
||||
|
||||
auto layerProperties = m_context.enumerateInstanceLayerProperties();
|
||||
for (auto const &requiredLayer: requiredLayers) {
|
||||
bool found = false;
|
||||
for (auto const &layerProperty: layerProperties) {
|
||||
if (strcmp(layerProperty.layerName, requiredLayer)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// TODO: Not sure i like throwing runtime errors, might need to find a better solution
|
||||
throw std::runtime_error("Required layer not supported: " + std::string(requiredLayer));
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through the required extensions, making sure they are supported
|
||||
auto requiredExtensions = getRequiredExtensions();
|
||||
auto extensionProperties = m_context.enumerateInstanceExtensionProperties();
|
||||
for (auto const &requiredExtension: requiredExtensions) {
|
||||
bool found = false;
|
||||
for (auto const &extensionProperty: extensionProperties) {
|
||||
if (strcmp(extensionProperty.extensionName, requiredExtension)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// TODO: Not sure i like just throwing a runtime error, might need to find a better solution for error
|
||||
// handling
|
||||
throw std::runtime_error("Required extension not found: " + std::string(requiredExtension));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Create the instance
|
||||
vk::InstanceCreateInfo createInfo{
|
||||
.pApplicationInfo = &appInfo,
|
||||
.enabledLayerCount = static_cast<uint32_t>(requiredLayers.size()),
|
||||
.ppEnabledLayerNames = requiredLayers.data(),
|
||||
.enabledExtensionCount = static_cast<uint32_t>(requiredExtensions.size()),
|
||||
.ppEnabledExtensionNames = requiredExtensions.data(),
|
||||
};
|
||||
|
||||
m_instance = vk::raii::Instance(m_context, createInfo);
|
||||
}
|
||||
|
||||
std::vector<const char *> ctx::getRequiredExtensions() {
|
||||
uint32_t glfwExtensionCount = 0;
|
||||
auto glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
|
||||
std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
|
||||
|
||||
if (enableValidationLayers) {
|
||||
extensions.push_back(vk::EXTDebugUtilsExtensionName);
|
||||
}
|
||||
|
||||
return extensions;
|
||||
}
|
||||
|
||||
static VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback(vk::DebugUtilsMessageSeverityFlagBitsEXT severity,
|
||||
vk::DebugUtilsMessageTypeFlagsEXT type,
|
||||
const vk::DebugUtilsMessengerCallbackDataEXT *pCallbackData,
|
||||
void *) {
|
||||
std::cerr << "Validation layer: type " << vk::to_string(type) << "msg: " << pCallbackData->pMessage
|
||||
<< std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ctx::setupDebugMessenger() {
|
||||
if (!enableValidationLayers) {
|
||||
return;
|
||||
}
|
||||
|
||||
vk::DebugUtilsMessageSeverityFlagsEXT severityFlags(vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
|
||||
vk::DebugUtilsMessageSeverityFlagBitsEXT::eError);
|
||||
|
||||
vk::DebugUtilsMessageTypeFlagsEXT typeFlags(vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
|
||||
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
|
||||
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance);
|
||||
|
||||
vk::DebugUtilsMessengerCreateInfoEXT createInfo{
|
||||
.messageSeverity = severityFlags,
|
||||
.messageType = typeFlags,
|
||||
.pfnUserCallback = &debugCallback,
|
||||
};
|
||||
|
||||
m_debugMessenger = m_instance.createDebugUtilsMessengerEXT(createInfo);
|
||||
}
|
||||
|
||||
} // namespace Oatmeal
|
||||
@@ -1,83 +0,0 @@
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
#include "ctx.h"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
|
||||
namespace Oatmeal {
|
||||
|
||||
void ctx::pickPhysicalDevice() {
|
||||
std::vector<vk::raii::PhysicalDevice> physicalDevices = m_instance.enumeratePhysicalDevices();
|
||||
std::vector<vk::raii::PhysicalDevice> supportedDevices{};
|
||||
|
||||
for (const auto device: physicalDevices) {
|
||||
if (isPhysicalDeviceSupported(device)) {
|
||||
supportedDevices.emplace_back(device);
|
||||
}
|
||||
}
|
||||
if (supportedDevices.empty()) {
|
||||
throw std::runtime_error("Failed to find a supported device");
|
||||
}
|
||||
|
||||
std::multimap<uint32_t, vk::raii::PhysicalDevice> scores;
|
||||
for (const auto device: supportedDevices) {
|
||||
uint32_t score = scorePhysicalDevice(device);
|
||||
scores.insert(std::make_pair(score, device));
|
||||
}
|
||||
m_physicalDevice = scores.rbegin()->second;
|
||||
}
|
||||
|
||||
bool ctx::isPhysicalDeviceSupported(vk::raii::PhysicalDevice device) {
|
||||
// Check for vulkan 1.4 support
|
||||
bool supportsVulkan14 = device.getProperties().apiVersion >= VK_API_VERSION_1_4;
|
||||
|
||||
// Check for graphics queue support
|
||||
auto queueFamilies = device.getQueueFamilyProperties();
|
||||
bool supportsGraphics = std::ranges::any_of(
|
||||
queueFamilies, [](auto const &qfp) { return !!(qfp.queueFlags & vk::QueueFlagBits::eGraphics); });
|
||||
|
||||
// Check for extension support
|
||||
auto availableDeviceExtensions = device.enumerateDeviceExtensionProperties();
|
||||
bool supportsAllRequiredExtensions = std::ranges::all_of(
|
||||
requiredDeviceExtensions, [&availableDeviceExtensions](auto const &requiredDeviceExtension) {
|
||||
return std::ranges::any_of(
|
||||
availableDeviceExtensions, [requiredDeviceExtension](auto const &availableDeviceExtension) {
|
||||
return strcmp(availableDeviceExtension.extensionName, requiredDeviceExtension) == 0;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Check for feature support
|
||||
auto features = device.template getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan13Features,
|
||||
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>();
|
||||
|
||||
bool supportsRequiredFeatures =
|
||||
features.template get<vk::PhysicalDeviceFeatures2>().features.samplerAnisotropy &&
|
||||
features.template get<vk::PhysicalDeviceVulkan13Features>().dynamicRendering &&
|
||||
features.template get<vk::PhysicalDeviceVulkan13Features>().synchronization2 &&
|
||||
features.template get<vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT>().extendedDynamicState;
|
||||
|
||||
return supportsVulkan14 && supportsGraphics && supportsAllRequiredExtensions && supportsRequiredFeatures;
|
||||
}
|
||||
|
||||
|
||||
uint32_t ctx::scorePhysicalDevice(vk::raii::PhysicalDevice device) {
|
||||
uint32_t score = 0;
|
||||
vk::PhysicalDeviceProperties physicalDeviceProperties = device.getProperties();
|
||||
|
||||
if (physicalDeviceProperties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) {
|
||||
score += 100;
|
||||
} else if (physicalDeviceProperties.deviceType == vk::PhysicalDeviceType::eIntegratedGpu) {
|
||||
score += 50;
|
||||
} else if (physicalDeviceProperties.deviceType == vk::PhysicalDeviceType::eVirtualGpu) {
|
||||
score += 10;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
} // namespace Oatmeal
|
||||
@@ -1,17 +0,0 @@
|
||||
#include "ctx.h"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <GLFW/glfw3native.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
|
||||
namespace Oatmeal {
|
||||
|
||||
void ctx::createSurface() {
|
||||
VkSurfaceKHR _surface;
|
||||
if (glfwCreateWindowSurface(*m_instance, m_window, nullptr, &_surface)) {
|
||||
throw std::runtime_error("Failed to create window surface");
|
||||
}
|
||||
m_surface = vk::raii::SurfaceKHR(m_instance, _surface);
|
||||
}
|
||||
} // namespace Oatmeal
|
||||
Reference in New Issue
Block a user