Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion attachments/.gitignore

This file was deleted.

4 changes: 2 additions & 2 deletions attachments/00_base_code.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class HelloTriangleApplication {
}

private:
GLFWwindow* window;
GLFWwindow* window = nullptr;

void initWindow() {
glfwInit();
Expand Down Expand Up @@ -47,7 +47,7 @@ class HelloTriangleApplication {
};

int main() {
HelloTriangleApplication app;
HelloTriangleApplication app{};

try {
app.run();
Expand Down
14 changes: 10 additions & 4 deletions attachments/01_instance_creation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class HelloTriangleApplication {
GLFWwindow* window = nullptr;

vk::raii::Context context;
std::unique_ptr<vk::raii::Instance> instance;
vk::raii::Instance instance = nullptr;

void initWindow() {
glfwInit();
Expand Down Expand Up @@ -53,11 +53,17 @@ class HelloTriangleApplication {
}

void createInstance() {
constexpr auto appInfo = vk::ApplicationInfo("Hello Triangle", 1, "No Engine", 1, vk::ApiVersion14);
constexpr vk::ApplicationInfo appInfo{ .pApplicationName = "Hello Triangle",
.applicationVersion = VK_MAKE_VERSION( 1, 0, 0 ),
.pEngineName = "No Engine",
.engineVersion = VK_MAKE_VERSION( 1, 0, 0 ),
.apiVersion = vk::ApiVersion14 };
uint32_t glfwExtensionCount = 0;
auto glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
vk::InstanceCreateInfo createInfo({}, &appInfo, {}, glfwExtensions);
instance = std::make_unique<vk::raii::Instance>(context, createInfo);
vk::InstanceCreateInfo createInfo{
.pApplicationInfo = &appInfo,
.ppEnabledLayerNames = glfwExtensions};
instance = vk::raii::Instance(context, createInfo);
}
};

Expand Down
27 changes: 20 additions & 7 deletions attachments/02_validation_layers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class HelloTriangleApplication {
GLFWwindow* window = nullptr;

vk::raii::Context context;
std::unique_ptr<vk::raii::Instance> instance;
std::unique_ptr<vk::raii::DebugUtilsMessengerEXT> debugMessenger;
vk::raii::Instance instance = nullptr;
vk::raii::DebugUtilsMessengerEXT debugMessenger = nullptr;

void initWindow() {
glfwInit();
Expand Down Expand Up @@ -72,23 +72,36 @@ class HelloTriangleApplication {
throw std::runtime_error("validation layers requested, but not available!");
}

constexpr auto appInfo = vk::ApplicationInfo("Hello Triangle", 1, "No Engine", 1, vk::ApiVersion14);
constexpr vk::ApplicationInfo appInfo{ .pApplicationName = "Hello Triangle",
.applicationVersion = VK_MAKE_VERSION( 1, 0, 0 ),
.pEngineName = "No Engine",
.engineVersion = VK_MAKE_VERSION( 1, 0, 0 ),
.apiVersion = vk::ApiVersion14 };
auto extensions = getRequiredExtensions();
std::vector<char const *> enabledLayers;
if (enableValidationLayers) {
enabledLayers.assign(validationLayers.begin(), validationLayers.end());
}
vk::InstanceCreateInfo createInfo({}, &appInfo, enabledLayers.size(), enabledLayers.data(), extensions.size(), extensions.data());
instance = std::make_unique<vk::raii::Instance>(context, createInfo);
vk::InstanceCreateInfo createInfo{
.pApplicationInfo = &appInfo,
.enabledLayerCount = static_cast<uint32_t>(enabledLayers.size()),
.ppEnabledLayerNames = enabledLayers.data(),
.enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
.ppEnabledExtensionNames = extensions.data() };
instance = vk::raii::Instance(context, createInfo);
}

void setupDebugMessenger() {
if (!enableValidationLayers) return;

vk::DebugUtilsMessageSeverityFlagsEXT severityFlags( vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError );
vk::DebugUtilsMessageTypeFlagsEXT messageTypeFlags( vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation );
vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT({}, severityFlags, messageTypeFlags, &debugCallback);
debugMessenger = std::make_unique<vk::raii::DebugUtilsMessengerEXT>( *instance, debugUtilsMessengerCreateInfoEXT );
vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT{
.messageSeverity = severityFlags,
.messageType = messageTypeFlags,
.pfnUserCallback = &debugCallback
};
debugMessenger = instance.createDebugUtilsMessengerEXT(debugUtilsMessengerCreateInfoEXT);
}

std::vector<const char*> getRequiredExtensions() {
Expand Down
64 changes: 55 additions & 9 deletions attachments/03_physical_device_selection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,17 @@ class HelloTriangleApplication {
GLFWwindow* window = nullptr;

vk::raii::Context context;
std::unique_ptr<vk::raii::Instance> instance;
std::unique_ptr<vk::raii::DebugUtilsMessengerEXT> debugMessenger;
vk::raii::Instance instance = nullptr;
vk::raii::DebugUtilsMessengerEXT debugMessenger = nullptr;

std::unique_ptr<vk::raii::PhysicalDevice> physicalDevice;
vk::raii::PhysicalDevice physicalDevice = nullptr;

std::vector<const char*> deviceExtensions = {
vk::KHRSwapchainExtensionName,
vk::KHRSpirv14ExtensionName,
vk::KHRSynchronization2ExtensionName,
vk::KHRCreateRenderpass2ExtensionName
};

void initWindow() {
glfwInit();
Expand Down Expand Up @@ -75,27 +82,66 @@ class HelloTriangleApplication {
throw std::runtime_error("validation layers requested, but not available!");
}

constexpr auto appInfo = vk::ApplicationInfo("Hello Triangle", 1, "No Engine", 1, vk::ApiVersion14);
constexpr vk::ApplicationInfo appInfo{ .pApplicationName = "Hello Triangle",
.applicationVersion = VK_MAKE_VERSION( 1, 0, 0 ),
.pEngineName = "No Engine",
.engineVersion = VK_MAKE_VERSION( 1, 0, 0 ),
.apiVersion = vk::ApiVersion14 };
auto extensions = getRequiredExtensions();
std::vector<char const *> enabledLayers;
if (enableValidationLayers) {
enabledLayers.assign(validationLayers.begin(), validationLayers.end());
}
vk::InstanceCreateInfo createInfo({}, &appInfo, enabledLayers.size(), enabledLayers.data(), extensions.size(), extensions.data());
instance = std::make_unique<vk::raii::Instance>(context, createInfo);
vk::InstanceCreateInfo createInfo{
.pApplicationInfo = &appInfo,
.enabledLayerCount = static_cast<uint32_t>(enabledLayers.size()),
.ppEnabledLayerNames = enabledLayers.data(),
.enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
.ppEnabledExtensionNames = extensions.data() };
instance = vk::raii::Instance(context, createInfo);
}

void setupDebugMessenger() {
if (!enableValidationLayers) return;

vk::DebugUtilsMessageSeverityFlagsEXT severityFlags( vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError );
vk::DebugUtilsMessageTypeFlagsEXT messageTypeFlags( vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation );
vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT({}, severityFlags, messageTypeFlags, &debugCallback);
debugMessenger = std::make_unique<vk::raii::DebugUtilsMessengerEXT>( *instance, debugUtilsMessengerCreateInfoEXT );
vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT{
.messageSeverity = severityFlags,
.messageType = messageTypeFlags,
.pfnUserCallback = &debugCallback
};
debugMessenger = instance.createDebugUtilsMessengerEXT(debugUtilsMessengerCreateInfoEXT);
}

void pickPhysicalDevice() {
physicalDevice = std::make_unique<vk::raii::PhysicalDevice>(vk::raii::PhysicalDevices( *instance ).front());
std::vector<vk::raii::PhysicalDevice> devices = instance.enumeratePhysicalDevices();
const auto devIter = std::ranges::find_if(devices,
[&](auto const & device) {
auto queueFamilies = device.getQueueFamilyProperties();
bool isSuitable = device.getProperties().apiVersion >= VK_API_VERSION_1_3;
const auto qfpIter = std::ranges::find_if(queueFamilies,
[]( vk::QueueFamilyProperties const & qfp )
{
return (qfp.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast<vk::QueueFlags>(0);
} );
Comment thread
gpx1000 marked this conversation as resolved.
Outdated
isSuitable = isSuitable && ( qfpIter != queueFamilies.end() );
auto extensions = device.enumerateDeviceExtensionProperties( );
bool found = true;
for (auto const & extension : deviceExtensions) {
auto extensionIter = std::ranges::find_if(extensions, [extension](auto const & ext) {return strcmp(ext.extensionName, extension) == 0;});
found = found && extensionIter != extensions.end();
}
Comment thread
gpx1000 marked this conversation as resolved.
Outdated
isSuitable = isSuitable && found;
printf("\n");
if (isSuitable) {
physicalDevice = device;
}
return isSuitable;
});
if (devIter == devices.end()) {
throw std::runtime_error("failed to find a suitable GPU!");
}
Comment thread
gpx1000 marked this conversation as resolved.
}

std::vector<const char*> getRequiredExtensions() {
Expand Down
96 changes: 75 additions & 21 deletions attachments/04_logical_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,20 @@ class HelloTriangleApplication {
GLFWwindow* window = nullptr;

vk::raii::Context context;
std::unique_ptr<vk::raii::Instance> instance;
std::unique_ptr<vk::raii::DebugUtilsMessengerEXT> debugMessenger;
vk::raii::Instance instance = nullptr;
vk::raii::DebugUtilsMessengerEXT debugMessenger = nullptr;

std::unique_ptr<vk::raii::PhysicalDevice> physicalDevice;
std::unique_ptr<vk::raii::Device> device;
vk::raii::PhysicalDevice physicalDevice = nullptr;
vk::raii::Device device = nullptr;

std::unique_ptr<vk::raii::Queue> graphicsQueue;
vk::raii::Queue graphicsQueue = nullptr;

std::vector<const char*> deviceExtensions = {
vk::KHRSwapchainExtensionName,
vk::KHRSpirv14ExtensionName,
vk::KHRSynchronization2ExtensionName,
vk::KHRCreateRenderpass2ExtensionName
};

void initWindow() {
glfwInit();
Expand Down Expand Up @@ -79,48 +86,95 @@ class HelloTriangleApplication {
throw std::runtime_error("validation layers requested, but not available!");
}

constexpr auto appInfo = vk::ApplicationInfo("Hello Triangle", 1, "No Engine", 1, vk::ApiVersion14);
constexpr vk::ApplicationInfo appInfo{ .pApplicationName = "Hello Triangle",
.applicationVersion = VK_MAKE_VERSION( 1, 0, 0 ),
.pEngineName = "No Engine",
.engineVersion = VK_MAKE_VERSION( 1, 0, 0 ),
.apiVersion = vk::ApiVersion14 };
auto extensions = getRequiredExtensions();
std::vector<char const *> enabledLayers;
if (enableValidationLayers) {
enabledLayers.assign(validationLayers.begin(), validationLayers.end());
}
vk::InstanceCreateInfo createInfo({}, &appInfo, enabledLayers.size(), enabledLayers.data(), extensions.size(), extensions.data());
instance = std::make_unique<vk::raii::Instance>(context, createInfo);
vk::InstanceCreateInfo createInfo{
.pApplicationInfo = &appInfo,
.enabledLayerCount = static_cast<uint32_t>(enabledLayers.size()),
.ppEnabledLayerNames = enabledLayers.data(),
.enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
.ppEnabledExtensionNames = extensions.data() };
instance = vk::raii::Instance(context, createInfo);
}

void setupDebugMessenger() {
if (!enableValidationLayers) return;

vk::DebugUtilsMessageSeverityFlagsEXT severityFlags( vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError );
vk::DebugUtilsMessageTypeFlagsEXT messageTypeFlags( vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation );
vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT({}, severityFlags, messageTypeFlags, &debugCallback);
debugMessenger = std::make_unique<vk::raii::DebugUtilsMessengerEXT>( *instance, debugUtilsMessengerCreateInfoEXT );
vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT{
.messageSeverity = severityFlags,
.messageType = messageTypeFlags,
.pfnUserCallback = &debugCallback
};
debugMessenger = instance.createDebugUtilsMessengerEXT(debugUtilsMessengerCreateInfoEXT);
}

void pickPhysicalDevice() {
physicalDevice = std::make_unique<vk::raii::PhysicalDevice>(vk::raii::PhysicalDevices( *instance ).front());
std::vector<vk::raii::PhysicalDevice> devices = instance.enumeratePhysicalDevices();
const auto devIter = std::ranges::find_if(devices,
[&](auto const & device) {
auto queueFamilies = device.getQueueFamilyProperties();
bool isSuitable = device.getProperties().apiVersion >= VK_API_VERSION_1_3;
const auto qfpIter = std::ranges::find_if(queueFamilies,
[]( vk::QueueFamilyProperties const & qfp )
{
return (qfp.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast<vk::QueueFlags>(0);
} );
isSuitable = isSuitable && ( qfpIter != queueFamilies.end() );
auto extensions = device.enumerateDeviceExtensionProperties( );
bool found = true;
for (auto const & extension : deviceExtensions) {
auto extensionIter = std::ranges::find_if(extensions, [extension](auto const & ext) {return strcmp(ext.extensionName, extension) == 0;});
found = found && extensionIter != extensions.end();
}
isSuitable = isSuitable && found;
printf("\n");
if (isSuitable) {
physicalDevice = device;
}
return isSuitable;
});
if (devIter == devices.end()) {
throw std::runtime_error("failed to find a suitable GPU!");
}
}

void createLogicalDevice() {
// find the index of the first queue family that supports graphics
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice->getQueueFamilyProperties();
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();

// get the first index into queueFamiliyProperties which supports graphics
auto graphicsQueueFamilyProperty =
std::find_if( queueFamilyProperties.begin(),
queueFamilyProperties.end(),
[]( vk::QueueFamilyProperties const & qfp ) { return qfp.queueFlags & vk::QueueFlagBits::eGraphics; } );
// get the first index into queueFamilyProperties which supports graphics
auto graphicsQueueFamilyProperty = std::ranges::find_if( queueFamilyProperties, []( auto const & qfp )
{ return (qfp.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast<vk::QueueFlags>(0); } );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe:
return (qfp.queueFlags & vk::QueueFlagBits::eGraphics);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compiler error complaining that the type is not a bool. I could cast it, but I bet the compiler would give the same asm output from casting as simply comparing against 0.


auto graphicsIndex = static_cast<uint32_t>( std::distance( queueFamilyProperties.begin(), graphicsQueueFamilyProperty ) );

// query for Vulkan 1.3 features
auto features = physicalDevice.getFeatures2();
vk::PhysicalDeviceVulkan13Features vulkan13Features;
vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT extendedDynamicStateFeatures;
vulkan13Features.dynamicRendering = vk::True;
extendedDynamicStateFeatures.extendedDynamicState = vk::True;
vulkan13Features.pNext = &extendedDynamicStateFeatures;
features.pNext = &vulkan13Features;
// create a Device
float queuePriority = 0.0f;
vk::DeviceQueueCreateInfo deviceQueueCreateInfo( {}, graphicsIndex, 1, &queuePriority );
vk::DeviceCreateInfo deviceCreateInfo( {}, deviceQueueCreateInfo );
vk::DeviceQueueCreateInfo deviceQueueCreateInfo { .queueFamilyIndex = graphicsIndex, .queueCount = 1, .pQueuePriorities = &queuePriority };
vk::DeviceCreateInfo deviceCreateInfo{ .pNext = &features, .queueCreateInfoCount = 1, .pQueueCreateInfos = &deviceQueueCreateInfo };
deviceCreateInfo.enabledExtensionCount = deviceExtensions.size();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static_cast<uint32_t>(deviceExtensions.size() ?

And why have you moved the initialization of enabledExtensionCount and ppEnabledExtensionNames out of the contructor call?

deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
Comment thread
gpx1000 marked this conversation as resolved.
Outdated

device = std::make_unique<vk::raii::Device>( *physicalDevice, deviceCreateInfo );
graphicsQueue = std::make_unique<vk::raii::Queue>( *device, graphicsIndex, 0 );
device = vk::raii::Device( physicalDevice, deviceCreateInfo );
graphicsQueue = vk::raii::Queue( device, graphicsIndex, 0 );
}

std::vector<const char*> getRequiredExtensions() {
Expand Down
Loading