Compare commits
8 Commits
c412073c23
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 26a392b1d0 | |||
| b90c980bee | |||
| f5c4ac0790 | |||
| bd6c4523dd | |||
| 7d50f6c148 | |||
| aa39f81bb1 | |||
| 14b4e60d3a | |||
| fd35e93831 |
@@ -1,33 +1,55 @@
|
|||||||
|
// basicGLFWWindow
|
||||||
|
// While I've got a basic initWindow() function in shared/window.h, I mostly just wanted to give an example of how to
|
||||||
|
// create a window with glfw without it. You can always figure out from the window.h file as well, but it is nice and
|
||||||
|
// easy to just look here instead, as you're probably already here anyways.
|
||||||
|
// Oatmeal does ship with GLFW linked as public, so you should be able to just link with it in your CMakeLists.txt file
|
||||||
|
// without having to add it yourself.
|
||||||
|
// - Firewire
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include "GLFW/glfw3.h"
|
#include "GLFW/glfw3.h"
|
||||||
#include "shared/logger.h"
|
#include "shared/logger.h"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
// Init and create the logger
|
||||||
OatmealUtils::initLogging();
|
OatmealUtils::initLogging();
|
||||||
OatmealUtils::createLogger("window", nullptr);
|
OatmealUtils::createLogger("window", nullptr);
|
||||||
|
|
||||||
OatmealUtils::get("window")->info("Initializing GLFW");
|
// Initialize the GLFW backend
|
||||||
|
OatmealUtils::getLogger("window")->info("Initializing GLFW");
|
||||||
glfwInit();
|
glfwInit();
|
||||||
|
|
||||||
OatmealUtils::get("window")->info("Setting window hints");
|
// GLFW works on hints for configuration.
|
||||||
|
// Since oatmeal is entirely vulkan based and GLFW creates an opengl context by default, we need to tell it not to.
|
||||||
|
// At the time of writing (very very early indev) there is no resizable window support, so thats turned off here as
|
||||||
|
// well.
|
||||||
|
OatmealUtils::getLogger("window")->info("Setting window hints");
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||||
|
|
||||||
OatmealUtils::get("window")->info("Create window");
|
// Create the window, running a small error check just in case it failed for whatever reason; and if it did, grab
|
||||||
|
// the error from glfw and print it out.
|
||||||
|
OatmealUtils::getLogger("window")->info("Create window");
|
||||||
GLFWwindow *window = glfwCreateWindow(800, 600, "Oatmeal - Basic GLFW window", nullptr, nullptr);
|
GLFWwindow *window = glfwCreateWindow(800, 600, "Oatmeal - Basic GLFW window", nullptr, nullptr);
|
||||||
if (window == nullptr) {
|
if (window == nullptr) {
|
||||||
const char *desc;
|
const char *desc;
|
||||||
uint32_t code = glfwGetError(&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);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This here is whats known as the main application loop. Everything with graphics/games/whatever runs in a loop,
|
||||||
|
// updating values as needed before it starts over again. The time it takes to run that loop is known at the
|
||||||
|
// frametime, and how many times you can run that loop per second is the FPS (sorta)
|
||||||
|
// Since we are just creating a window and have no way of updating it yet, we can just poll for any events and
|
||||||
|
// continue.
|
||||||
while (!glfwWindowShouldClose(window)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
OatmealUtils::get("window")->info("Cleaning up");
|
// Cleanup the window and terminate the glfw backend
|
||||||
|
OatmealUtils::getLogger("window")->info("Cleaning up");
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
|
|
||||||
|
|||||||
@@ -1,45 +1,43 @@
|
|||||||
#include <cstdint>
|
// createContext
|
||||||
|
// Still in progress, although I'm 95% sure this wont get changed.
|
||||||
|
// Come back later!
|
||||||
|
// - Firewire
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <memory>
|
||||||
#include "GLFW/glfw3.h"
|
#include "GLFW/glfw3.h"
|
||||||
#include "shared/logger.h"
|
#include "shared/logger.h"
|
||||||
|
#include "shared/window.h"
|
||||||
|
|
||||||
#include "ctx.h"
|
#include "ctx.h"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
OatmealUtils::initLogging();
|
OatmealUtils::initLogging();
|
||||||
OatmealUtils::createLogger("window", nullptr);
|
|
||||||
OatmealUtils::createLogger("context", nullptr);
|
OatmealUtils::createLogger("context", nullptr);
|
||||||
|
|
||||||
OatmealUtils::get("window")->info("Initializing GLFW");
|
GLFWwindow *window = OatmealUtils::initWindow("Oatmeal - createContext", 800, 600);
|
||||||
glfwInit();
|
|
||||||
|
|
||||||
OatmealUtils::get("window")->info("Setting window hints");
|
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
|
||||||
|
|
||||||
OatmealUtils::get("window")->info("Create window");
|
std::shared_ptr<Oatmeal::ctx> ctx = nullptr;
|
||||||
GLFWwindow *window = glfwCreateWindow(800, 600, "Oatmeal - Basic GLFW window", nullptr, nullptr);
|
|
||||||
if (window == nullptr) {
|
|
||||||
const char *desc;
|
|
||||||
uint32_t code = glfwGetError(&desc);
|
|
||||||
OatmealUtils::get("window")->critical("Failed to create window: ({}) {}", code, desc);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
OatmealUtils::getLogger("context")->info("Creating context");
|
||||||
try {
|
try {
|
||||||
Oatmeal::ctx ctx(window);
|
ctx = std::make_shared<Oatmeal::ctx>(window);
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
OatmealUtils::get("context")->critical("{}", e.what());
|
OatmealUtils::getLogger("context")->critical("{}", e.what());
|
||||||
return EXIT_FAILURE;
|
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)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
OatmealUtils::get("window")->info("Cleaning up");
|
OatmealUtils::getLogger("window")->info("Cleaning up");
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
// Logging
|
||||||
|
// This program is just to test out/show any new features I add to the shared/logging.h file.
|
||||||
|
// It is mostly a wrapper around spdlog, nothing fancy at all.
|
||||||
|
// The code should be self explanatory enough so I'm not going to bother commenting everything out.
|
||||||
|
// - Firewire
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "shared/logger.h"
|
#include "shared/logger.h"
|
||||||
|
|
||||||
@@ -5,13 +11,13 @@ int main() {
|
|||||||
OatmealUtils::initLogging();
|
OatmealUtils::initLogging();
|
||||||
OatmealUtils::createLogger("logger", nullptr);
|
OatmealUtils::createLogger("logger", nullptr);
|
||||||
|
|
||||||
OatmealUtils::get("logger")->debug("This is a debug message!");
|
OatmealUtils::getLogger("logger")->debug("This is a debug message!");
|
||||||
OatmealUtils::get("logger")->info("This is an info message!");
|
OatmealUtils::getLogger("logger")->info("This is an info message!");
|
||||||
OatmealUtils::get("logger")->warn("This is a warning message!");
|
OatmealUtils::getLogger("logger")->warn("This is a warning message!");
|
||||||
OatmealUtils::get("logger")->critical("This is a critical message!");
|
OatmealUtils::getLogger("logger")->critical("This is a critical message!");
|
||||||
uint32_t a = 5;
|
uint32_t a = 5;
|
||||||
std::string b = "Test string arg!";
|
std::string b = "Test string arg!";
|
||||||
OatmealUtils::get("logger")->info("String arg: {} uint32_t args: {}", b, a);
|
OatmealUtils::getLogger("logger")->info("String arg: {} uint32_t args: {}", b, a);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
#include "logger.h"
|
|
||||||
#include <memory>
|
|
||||||
#include <spdlog/async_logger.h>
|
|
||||||
#include <spdlog/common.h>
|
|
||||||
#include "spdlog/async.h"
|
|
||||||
#include "spdlog/sinks/basic_file_sink.h"
|
|
||||||
#include "spdlog/sinks/stdout_color_sinks.h"
|
|
||||||
#include "spdlog/spdlog.h"
|
|
||||||
|
|
||||||
namespace OatmealUtils {
|
|
||||||
|
|
||||||
void initLogging() {
|
|
||||||
spdlog::init_thread_pool(8192, 1);
|
|
||||||
spdlog::flush_every(std::chrono::seconds(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void createLogger(const char *name, const char *filename) {
|
|
||||||
std::vector<spdlog::sink_ptr> sinks{};
|
|
||||||
|
|
||||||
const auto stdoutSink = std::make_shared<spdlog::sinks::stderr_color_sink_mt>();
|
|
||||||
stdoutSink->set_level(spdlog::level::debug);
|
|
||||||
stdoutSink->set_pattern("%^[%D %r %z] [%n] [%l] [thread %t] %v%$");
|
|
||||||
sinks.emplace_back(stdoutSink);
|
|
||||||
|
|
||||||
if (filename != nullptr) {
|
|
||||||
const auto fileSink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename);
|
|
||||||
fileSink->set_level(spdlog::level::debug);
|
|
||||||
fileSink->set_pattern("%^[%D %r %z] [%n] [%l] [thread %t] %v%$");
|
|
||||||
sinks.emplace_back(fileSink);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto logger = std::make_shared<spdlog::async_logger>(
|
|
||||||
name, sinks.begin(), sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block);
|
|
||||||
|
|
||||||
logger->flush_on(spdlog::level::warn);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
logger->set_level(spdlog::level::debug);
|
|
||||||
#else
|
|
||||||
logger->set_level(spdlog::level::info);
|
|
||||||
#endif // !NDEBUG
|
|
||||||
|
|
||||||
spdlog::register_logger(logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
void createLogger(std::string name, std::string filename) { createLogger(name.c_str(), filename.c_str()); }
|
|
||||||
std::shared_ptr<logger> get(const char *name) { return spdlog::get(name); }
|
|
||||||
std::shared_ptr<logger> get(std::string name) { return spdlog::get(name); }
|
|
||||||
} // namespace OatmealUtils
|
|
||||||
@@ -1,20 +1,57 @@
|
|||||||
#ifndef OATMEAL_LOGGER
|
#ifndef OATMEAL_UTILS_LOGGER
|
||||||
#define OATMEAL_LOGGER
|
#define OATMEAL_UTILS_LOGGER
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <spdlog/async_logger.h>
|
||||||
|
#include <spdlog/common.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
#include "spdlog/async.h"
|
||||||
|
#include "spdlog/sinks/basic_file_sink.h"
|
||||||
|
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
#include "string"
|
#include "string"
|
||||||
|
|
||||||
namespace OatmealUtils {
|
namespace OatmealUtils {
|
||||||
|
|
||||||
using logger = spdlog::logger;
|
using logger = spdlog::logger;
|
||||||
|
|
||||||
void initLogging();
|
inline void initLogging() {
|
||||||
void createLogger(const char *name, const char *filename);
|
spdlog::init_thread_pool(8192, 1);
|
||||||
void createLogger(std::string name, std::string filename);
|
spdlog::flush_every(std::chrono::seconds(1));
|
||||||
std::shared_ptr<logger> get(const char *name);
|
}
|
||||||
std::shared_ptr<logger> get(std::string name);
|
|
||||||
|
inline void createLogger(const char *name, const char *filename) {
|
||||||
|
std::vector<spdlog::sink_ptr> sinks{};
|
||||||
|
|
||||||
|
const auto stdoutSink = std::make_shared<spdlog::sinks::stderr_color_sink_mt>();
|
||||||
|
stdoutSink->set_level(spdlog::level::debug);
|
||||||
|
stdoutSink->set_pattern("%^[%D %r %z] [%n] [%l] [thread %t] %v%$");
|
||||||
|
sinks.emplace_back(stdoutSink);
|
||||||
|
|
||||||
|
if (filename != nullptr) {
|
||||||
|
const auto fileSink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename);
|
||||||
|
fileSink->set_level(spdlog::level::debug);
|
||||||
|
fileSink->set_pattern("%^[%D %r %z] [%n] [%l] [thread %t] %v%$");
|
||||||
|
sinks.emplace_back(fileSink);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto logger = std::make_shared<spdlog::async_logger>(
|
||||||
|
name, sinks.begin(), sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block);
|
||||||
|
|
||||||
|
logger->flush_on(spdlog::level::warn);
|
||||||
|
#ifndef NDEBUG
|
||||||
|
logger->set_level(spdlog::level::debug);
|
||||||
|
#else
|
||||||
|
logger->set_level(spdlog::level::info);
|
||||||
|
#endif // !NDEBUG
|
||||||
|
|
||||||
|
spdlog::register_logger(logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void createLogger(std::string name, std::string filename) { createLogger(name.c_str(), filename.c_str()); }
|
||||||
|
inline std::shared_ptr<logger> getLogger(const char *name) { return spdlog::get(name); }
|
||||||
|
inline std::shared_ptr<logger> getLogger(std::string name) { return spdlog::get(name); }
|
||||||
|
|
||||||
} // namespace OatmealUtils
|
} // namespace OatmealUtils
|
||||||
|
|
||||||
#endif // !OATMEAL_LOGGER
|
#endif // !OATMEAL_UTILS_LOGGER
|
||||||
|
|||||||
24
examples/shared/shared/window.h
Normal file
24
examples/shared/shared/window.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "GLFW/glfw3.h"
|
||||||
|
#include "shared/logger.h"
|
||||||
|
|
||||||
|
namespace OatmealUtils {
|
||||||
|
inline GLFWwindow *initWindow(const char *title, uint32_t width, uint32_t height) {
|
||||||
|
OatmealUtils::createLogger("window", nullptr);
|
||||||
|
OatmealUtils::getLogger("window")->debug("Initializing window backend");
|
||||||
|
glfwInit();
|
||||||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||||
|
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::getLogger("window")->critical("Failed to create window: ({}) {}", code, desc);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
} // namespace OatmealUtils
|
||||||
29
examples/shared/window.h
Normal file
29
examples/shared/window.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef OATMEAL_UTILS_WINDOW
|
||||||
|
#define OATMEAL_UTILS_WINDOW
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include "GLFW/glfw3.h"
|
||||||
|
#include "shared/logger.h"
|
||||||
|
|
||||||
|
namespace OatmealUtils {
|
||||||
|
inline GLFWwindow *initWindow(const char *title, uint32_t width, uint32_t height) {
|
||||||
|
OatmealUtils::initLogging();
|
||||||
|
OatmealUtils::createLogger("window", nullptr);
|
||||||
|
OatmealUtils::get("window")->debug("Initializing window backend");
|
||||||
|
glfwInit();
|
||||||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||||
|
OatmealUtils::get("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);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
} // namespace OatmealUtils
|
||||||
|
|
||||||
|
#endif // !OATMEAL_UTILS_WINDOW
|
||||||
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 "ctx.h"
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace Oatmeal {
|
namespace Oatmeal {
|
||||||
ctx::ctx(GLFWwindow *window) { createInstance(); }
|
ctx::ctx(GLFWwindow *window) {
|
||||||
|
createInstance();
|
||||||
|
m_window = window;
|
||||||
|
createSurface();
|
||||||
|
pickPhysicalDevice();
|
||||||
|
m_msaaSamples = getMaxUsableSampleCount();
|
||||||
|
createLogicalDevice();
|
||||||
|
}
|
||||||
|
|
||||||
ctx::~ctx() {}
|
ctx::~ctx() {}
|
||||||
|
|
||||||
|
|||||||
@@ -41,11 +41,17 @@ namespace Oatmeal {
|
|||||||
class ctx {
|
class ctx {
|
||||||
public:
|
public:
|
||||||
ctx(GLFWwindow *window);
|
ctx(GLFWwindow *window);
|
||||||
|
|
||||||
|
std::string getDeviceName() const;
|
||||||
|
std::string getDeviceType() const;
|
||||||
|
|
||||||
~ctx();
|
~ctx();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Members //
|
// Members //
|
||||||
|
|
||||||
|
GLFWwindow *m_window = nullptr;
|
||||||
|
|
||||||
vk::raii::Context m_context;
|
vk::raii::Context m_context;
|
||||||
vk::raii::Instance m_instance = nullptr;
|
vk::raii::Instance m_instance = nullptr;
|
||||||
vk::DebugUtilsMessengerEXT m_debugMessenger = nullptr;
|
vk::DebugUtilsMessengerEXT m_debugMessenger = nullptr;
|
||||||
@@ -81,5 +87,14 @@ namespace Oatmeal {
|
|||||||
void createInstance();
|
void createInstance();
|
||||||
std::vector<const char *> getRequiredExtensions();
|
std::vector<const char *> getRequiredExtensions();
|
||||||
void setupDebugMessenger();
|
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
|
} // 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 <GLFW/glfw3.h>
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#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