Skip to content

Commit

Permalink
Now work with VK_LAYER_KHRONOS_validation.
Browse files Browse the repository at this point in the history
  • Loading branch information
anirul committed Jan 5, 2024
1 parent 7892a0a commit 4151b10
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 195 deletions.
1 change: 1 addition & 0 deletions src/frame/vulkan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ add_library(FrameVulkan
sdl_vulkan_none.cpp
sdl_vulkan_window.h
sdl_vulkan_window.cpp
vulkan_window_interface.h
window_factory.h
window_factory.cpp
)
Expand Down
115 changes: 53 additions & 62 deletions src/frame/vulkan/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,76 +3,39 @@
namespace frame::vulkan
{

Device::Device(
void* vk_instance,
glm::uvec2 size,
vk::SurfaceKHR& surface,
vk::DispatchLoaderDynamic& dispatch)
: vk_instance_(static_cast<VkInstance>(vk_instance)), size_(size),
vk_surface_(surface), vk_dispatch_loader_(dispatch)
{
logger_->info("Creating Vulkan Device");
std::vector<vk::PhysicalDevice> physical_devices =
vk_instance_.enumeratePhysicalDevices();
if (physical_devices.empty())
Device::Device(glm::uvec2 size) : size_(size)
{
// Log the Vulkan version.
logger_->info("Creating Vulkan Device ({}, {})", size.x, size.y);
auto api_version = vk_context_.enumerateInstanceVersion();
logger_->info(
"Vulkan version: {}.{} total: {}",
VK_VERSION_MAJOR(api_version),
VK_VERSION_MINOR(api_version),
api_version);
// List all available extensions.
std::vector<vk::ExtensionProperties> availableExtensions =
vk::enumerateInstanceExtensionProperties();
logger_->info("Available Extensions:");
for (const auto& extension : availableExtensions)
{
throw std::runtime_error("No Vulkan Physical Device found");
std::string extension_name = extension.extensionName;
logger_->info("\t[{}]", extension_name);
}
// Check and select physical device properties.
int last_best_score = 0;
for (const auto& physical_device : physical_devices)
// List all available layers.
std::vector<vk::LayerProperties> availableLayers =
vk::enumerateInstanceLayerProperties();
logger_->info("Available Layers:");
for (const auto& layer : availableLayers)
{
int score = 0;
logger_->info(
"Physical Device: {}",
static_cast<char*>(physical_device.getProperties().deviceName));
if (physical_device.getProperties().deviceType ==
vk::PhysicalDeviceType::eDiscreteGpu)
{
logger_->info("\tis a GPU");
score += 10000;
}
score += physical_device.getProperties().limits.maxImageDimension2D;
if (physical_device.getFeatures().geometryShader)
{
if (score > last_best_score)
{
last_best_score = score;
vk_physical_device_ = physical_device;
}
}
}
if (!vk_physical_device_)
{
throw std::runtime_error("No Vulkan Physical Device found");
}
// Select a queue family.
std::vector<vk::QueueFamilyProperties> queue_families =
vk_physical_device_.getQueueFamilyProperties(vk_dispatch_loader_);
int i = 0;
int selected_index = -1;
for (auto& queue_family : queue_families)
{
if (queue_family.queueFlags & vk::QueueFlagBits::eGraphics)
{
selected_index = i;
}
i++;
std::string layer_name = layer.layerName;
logger_->info("\t[{}]", layer_name);
}
if (selected_index == -1)
{
throw std::runtime_error("No Vulkan Queue Family found");
}
// Get the device.
vk::DeviceQueueCreateInfo device_queue_create_info(
{}, selected_index, 1, &queue_family_priority_);
vk::DeviceCreateInfo device_create_info({}, 1, &device_queue_create_info);
vk_unique_device_ = vk_physical_device_.createDeviceUnique(
device_create_info, nullptr, vk_dispatch_loader_);
}

Device::~Device()
{
logger_->info("Destroying Vulkan Device");
}

void Device::SetStereo(
Expand All @@ -84,6 +47,34 @@ void Device::SetStereo(
throw std::runtime_error("Not implemented!");
}

void Device::Init(vk::InstanceCreateInfo instance_create_info)
{
logger_->info("Initializing Vulkan Device");
// Create the instance.
vk_instance_.emplace(vk_context_, instance_create_info);
// Get all vk::PhysicalDeviceGroupProperties from a vk::raii::Instance
// instance.
std::vector<vk::PhysicalDeviceGroupProperties>
physical_device_group_properties =
vk_instance_.value().enumeratePhysicalDeviceGroups();
logger_->info(
"Number of physical devices: {}",
physical_device_group_properties.size());
for (const auto& physical_device_group : physical_device_group_properties)
{
logger_->info(
"\t- group({})", physical_device_group.physicalDeviceCount);
for (std::uint32_t i = 0; i < physical_device_group.physicalDeviceCount;
++i)
{
std::string device_name = physical_device_group.physicalDevices[i]
.getProperties()
.deviceName;
logger_->info("\t\t- {}", device_name);
}
}
}

void Device::Clear(
const glm::vec4& color /*= glm::vec4(.2f, 0.f, .2f, 1.0f)*/) const
{
Expand Down
46 changes: 21 additions & 25 deletions src/frame/vulkan/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "frame/camera.h"
#include "frame/device_interface.h"
#include "frame/logger.h"
#include "frame/vulkan/vulkan_window_interface.h"
#include "frame/window_interface.h"

namespace frame::vulkan
{
Expand All @@ -18,20 +20,19 @@ class Device : public DeviceInterface
public:
/**
* @brief Constructor will initialize the Vulkan context.
* @param vk_instance: The vk::Instance passed as a void*.
* @param sdl_vulkan_window: Window interface to the windowing system.
* @param size: Window size.
* @param surface: Surface for the drawing.
* @param dispatch: Dispatch from vulkan.
*/
Device(
void* vk_instance,
glm::uvec2 size,
vk::SurfaceKHR& surface,
vk::DispatchLoaderDynamic& dispatch);
*/
Device(glm::uvec2 size);
//! @brief Destructor this is where the memory is freed.
virtual ~Device();

public:
/**
* @brief Initialize the device by passing the instance create info.
* @param instance_create_info: The instance create info.
*/
void Init(vk::InstanceCreateInfo instance_create_info);
/**
* @brief Set the stereo mode (by default this is NONE), interocular
* distance and focus point.
Expand Down Expand Up @@ -77,6 +78,11 @@ class Device : public DeviceInterface
* @param name: The name of the plugin to remove.
*/
void RemovePluginByName(const std::string& name) final;
/**
* @brief Display to the screen.
* @param dt: Delta time from the beginning of the software in seconds.
*/
void Display(double dt = 0.0) final;
/** @brief Cleanup the mess. */
void Cleanup() final;
/**
Expand All @@ -89,11 +95,6 @@ class Device : public DeviceInterface
* @return The size of the window.
*/
glm::uvec2 GetSize() const final;
/**
* @brief Display to the screen.
* @param dt: Delta time from the beginning of the software in seconds.
*/
void Display(double dt = 0.0) final;
/**
* @brief Make a screen shot to a file.
* @param file: File name of the screenshot (usually with the *.png)
Expand Down Expand Up @@ -140,13 +141,12 @@ class Device : public DeviceInterface
return *level_.get();
}
/**
* @brief Get the current context.
* @return A pointer to the current context (this is used by the
* windowing system).
* @brief Get a device context on the underlying graphic API.
* @return A device context on the underlying graphic API.
*/
void* GetDeviceContext() const final
{
return vk_instance_;
throw std::runtime_error("Not implemented!");
}
/**
* @brief Get the enum describing the stereo situation.
Expand Down Expand Up @@ -187,13 +187,6 @@ class Device : public DeviceInterface
std::unique_ptr<LevelInterface> level_ = nullptr;
// Storage of the plugin.
std::vector<std::unique_ptr<PluginInterface>> plugin_interfaces_ = {};
// Vulkan stuff.
vk::Instance vk_instance_ = {};
vk::PhysicalDevice vk_physical_device_ = {};
float queue_family_priority_ = 1.0f;
vk::UniqueHandle<vk::Device, vk::DispatchLoaderDynamic> vk_unique_device_;
vk::SurfaceKHR& vk_surface_;
vk::DispatchLoaderDynamic& vk_dispatch_loader_;
// Size.
glm::uvec2 size_ = {0, 0};
const proto::PixelElementSize pixel_element_size_ =
Expand All @@ -207,6 +200,9 @@ class Device : public DeviceInterface
bool invert_left_right_ = false;
// Logger for the device.
const Logger& logger_ = Logger::GetInstance();
// Vulkan crap.
vk::raii::Context vk_context_;
std::optional<vk::raii::Instance> vk_instance_;
};

} // End namespace frame::vulkan.
69 changes: 36 additions & 33 deletions src/frame/vulkan/sdl_vulkan_none.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "frame/vulkan/sdl_vulkan_none.h"

#include "frame/vulkan/debug_callback.h"
#include "frame/vulkan/device.h"
#include <SDL2/SDL_vulkan.h>

namespace frame::vulkan
Expand Down Expand Up @@ -34,39 +35,46 @@ SDLVulkanNone::SDLVulkanNone(glm::uvec2 size) : size_(size)
throw std::runtime_error(
fmt::format("Couldn't initialize window: {}", SDL_GetError()));
}
}

std::vector<const char*> sdlExtensions;
unsigned int sdlExtensionCount = 0;
SDL_Vulkan_GetInstanceExtensions(sdl_window_, &sdlExtensionCount, nullptr);
sdlExtensions.resize(sdlExtensionCount);
vk::InstanceCreateInfo SDLVulkanNone::GetInstanceCreateInfo(
vk::ApplicationInfo app_info) const
{
static std::vector<const char*> sdl_extensions;
unsigned int sdl_extension_count = 0;
SDL_Vulkan_GetInstanceExtensions(
sdl_window_, &sdlExtensionCount, sdlExtensions.data());

vk::ApplicationInfo appInfo(
"Frame Vulkan",
VK_MAKE_VERSION(1, 0, 0),
"Frame (SDL Vulkan None)",
VK_MAKE_VERSION(1, 0, 0),
VK_API_VERSION_1_3);

vk::InstanceCreateInfo instanceCreateInfo(
sdl_window_, &sdl_extension_count, nullptr);
sdl_extensions.resize(sdl_extension_count);
SDL_Vulkan_GetInstanceExtensions(
sdl_window_, &sdl_extension_count, sdl_extensions.data());
#ifdef _DEBUG
// Enable the debug callback extension.
sdl_extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
#endif
static std::vector<const char*> layers;
#ifdef _DEBUG
layers.push_back("VK_LAYER_KHRONOS_validation");
#endif
return vk::InstanceCreateInfo(
{},
&appInfo,
0,
nullptr,
static_cast<uint32_t>(sdlExtensions.size()),
sdlExtensions.data());

vk_instance_ = vk::raii::Instance(vk_context_, instanceCreateInfo);
&app_info,
static_cast<uint32_t>(layers.size()),
layers.data(),
static_cast<uint32_t>(sdl_extensions.size()),
sdl_extensions.data());
}

// Select Physical Device
std::vector<vk::raii::PhysicalDevice> physicalDevices =
vk_instance_.value().enumeratePhysicalDevices();
if (physicalDevices.empty())
void SDLVulkanNone::SetUniqueDevice(std::unique_ptr<DeviceInterface>&& device)
{
device_ = std::move(device);
vulkan::Device* vulkan_device =
dynamic_cast<vulkan::Device*>(device_.get());
if (!vulkan_device)
{
throw std::runtime_error("Failed to find GPUs with Vulkan support!");
std::runtime_error("Device is not a vulkan device.");
}
vk::raii::PhysicalDevice& physicalDevice = physicalDevices[0];

vulkan_device->Init(GetInstanceCreateInfo());
}

SDLVulkanNone::~SDLVulkanNone()
Expand All @@ -93,12 +101,7 @@ void SDLVulkanNone::Run(std::function<void()> /* lambda*/)

void* SDLVulkanNone::GetGraphicContext() const
{
if (vk_instance_)
{
return vk_instance_.value().operator*();
}
throw std::runtime_error(
"Try to access an uninitialized pointer to a vulkan instance.");
return sdl_window_;
}

} // End namespace frame::vulkan.
19 changes: 10 additions & 9 deletions src/frame/vulkan/sdl_vulkan_none.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
#include <vulkan/vulkan_raii.hpp>

#include "frame/logger.h"
#include "frame/vulkan/vulkan_window_interface.h"
#include "frame/window_interface.h"

namespace frame::vulkan
{

class SDLVulkanNone : public WindowInterface
class SDLVulkanNone : public VulkanWindowInterface
{
public:
SDLVulkanNone(glm::uvec2 size);
Expand All @@ -20,6 +21,14 @@ class SDLVulkanNone : public WindowInterface
public:
void Run(std::function<void()> lambda) override;
void* GetGraphicContext() const override;
vk::InstanceCreateInfo GetInstanceCreateInfo(
vk::ApplicationInfo app_info = {
"Frame Vulkan",
VK_MAKE_VERSION(1, 0, 0),
"Frame (SDL Vulkan None)",
VK_MAKE_VERSION(1, 0, 0),
VK_API_VERSION_1_3}) const override;
void SetUniqueDevice(std::unique_ptr<DeviceInterface>&& device) override;

public:
void SetInputInterface(
Expand All @@ -31,10 +40,6 @@ class SDLVulkanNone : public WindowInterface
{
throw std::runtime_error("Not implemented yet!");
}
void SetUniqueDevice(std::unique_ptr<DeviceInterface>&& device) override
{
device_ = std::move(device);
}
DeviceInterface& GetDevice() override
{
return *device_.get();
Expand Down Expand Up @@ -78,10 +83,6 @@ class SDLVulkanNone : public WindowInterface
std::unique_ptr<InputInterface> input_interface_ = nullptr;
SDL_Window* sdl_window_ = nullptr;
frame::Logger& logger_ = frame::Logger::GetInstance();
vk::raii::Context vk_context_;
// Trick around the fact that they don't have a default constructor.
std::optional<vk::raii::Instance> vk_instance_;
std::optional<vk::raii::SurfaceKHR> vk_surface_KHR_;
};

} // namespace frame::vulkan.
Loading

0 comments on commit 4151b10

Please sign in to comment.