Compare commits
6 Commits
14b4e60d3a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 26a392b1d0 | |||
| b90c980bee | |||
| f5c4ac0790 | |||
| bd6c4523dd | |||
| 7d50f6c148 | |||
| aa39f81bb1 |
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include "GLFW/glfw3.h"
|
||||
#include "shared/logger.h"
|
||||
#include "shared/window.h"
|
||||
@@ -17,14 +18,21 @@ int main() {
|
||||
|
||||
GLFWwindow *window = OatmealUtils::initWindow("Oatmeal - createContext", 800, 600);
|
||||
|
||||
|
||||
std::shared_ptr<Oatmeal::ctx> ctx = nullptr;
|
||||
|
||||
OatmealUtils::getLogger("context")->info("Creating context");
|
||||
try {
|
||||
Oatmeal::ctx ctx(window);
|
||||
ctx = std::make_shared<Oatmeal::ctx>(window);
|
||||
} 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("Starting main loop");
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
namespace OatmealUtils {
|
||||
inline GLFWwindow *initWindow(const char *title, uint32_t width, uint32_t height) {
|
||||
OatmealUtils::createLogger("window", nullptr);
|
||||
OatmealUtils::get("window")->debug("Initializing window backend");
|
||||
OatmealUtils::getLogger("window")->debug("Initializing window backend");
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
OatmealUtils::get("window")->debug("Creating window");
|
||||
OatmealUtils::getLogger("window")->debug("Creating window");
|
||||
GLFWwindow *window = glfwCreateWindow(width, height, title, nullptr, nullptr);
|
||||
if (window == nullptr) {
|
||||
const char *desc;
|
||||
uint32_t code = glfwGetError(&desc);
|
||||
OatmealUtils::get("window")->critical("Failed to create window: ({}) {}", code, desc);
|
||||
OatmealUtils::getLogger("window")->critical("Failed to create window: ({}) {}", code, desc);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
64
oatmeal/src/ctx-device.cpp
Normal file
64
oatmeal/src/ctx-device.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#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,8 +1,14 @@
|
||||
#include "ctx.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace Oatmeal {
|
||||
ctx::ctx(GLFWwindow *window) { createInstance(); }
|
||||
ctx::ctx(GLFWwindow *window) {
|
||||
createInstance();
|
||||
m_window = window;
|
||||
createSurface();
|
||||
pickPhysicalDevice();
|
||||
m_msaaSamples = getMaxUsableSampleCount();
|
||||
createLogicalDevice();
|
||||
}
|
||||
|
||||
ctx::~ctx() {}
|
||||
|
||||
|
||||
@@ -41,11 +41,17 @@ namespace Oatmeal {
|
||||
class ctx {
|
||||
public:
|
||||
ctx(GLFWwindow *window);
|
||||
|
||||
std::string getDeviceName() const;
|
||||
std::string getDeviceType() const;
|
||||
|
||||
~ctx();
|
||||
|
||||
private:
|
||||
// Members //
|
||||
|
||||
GLFWwindow *m_window = nullptr;
|
||||
|
||||
vk::raii::Context m_context;
|
||||
vk::raii::Instance m_instance = nullptr;
|
||||
vk::DebugUtilsMessengerEXT m_debugMessenger = nullptr;
|
||||
@@ -81,5 +87,14 @@ namespace Oatmeal {
|
||||
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
|
||||
|
||||
27
oatmeal/src/ctx_attachments.cpp
Normal file
27
oatmeal/src/ctx_attachments.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#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,5 +1,4 @@
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
83
oatmeal/src/ctx_physicalDevice.cpp
Normal file
83
oatmeal/src/ctx_physicalDevice.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#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
|
||||
17
oatmeal/src/ctx_surface.cpp
Normal file
17
oatmeal/src/ctx_surface.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#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