List of all Vulkan tutorial posts is here.
Second thing to do, in order to use Vulkan, is to create device. Before that, one can enumerate all Vulkan devices, which are present in system running application. The code is shown below.
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <madvk/instance.h>
using namespace std;
using namespace mad::vk;
int main(int argc, char* argv[]) {
try {
auto instance = Instance("vulkan playground 01");
cout << "Vulkan instance created" << endl;
cout << "Vulkan devices:" << endl;
std::vector<::vk::PhysicalDevice> devices;
instance.enumeratePhysicalDevices(devices);
for(const auto& dev : devices) {
const auto& props = dev.getProperties();
cout
<< std::showbase << std::internal << std::setfill('0')
<< std::hex
<< "\tID: " << props.deviceID()
<< std::noshowbase << std::right << std::setfill(' ')
<< std::dec
<< "\tname: " << props.deviceName()
<< "\ttype: " << to_string(props.deviceType())
<< "\tdriver version: " << props.driverVersion()
<< "\tapi version: "
<< ((props.apiVersion() >> 22) & 0xfff) << '.' // Major.
<< ((props.apiVersion() >> 12) & 0x3ff) << '.' // Minor.
<< (props.apiVersion() & 0xfff) // Patch.
<< endl;
}
}
catch(const std::system_error& err) {
cerr << "[ERROR] " << err.what() << endl;
return 1;
}
}
There is difference in creating Vulkan instance between this post and the first one. From this post onward, I will use my RAII wrapper around vk::Instance object and not the bare object itself, to make sure that memory will be freed correctly.Creating display device object requires two steps:
- Enumerating all devices and finding one, which is capable of graphical output.
- Creating device object with proper parameters and proper queues.
#include <iostream>
#include <vector>
#include <algorithm>
#include <madvk/instance.h>
using namespace std;
using namespace mad::vk;
int main(int argc, char* argv[]) {
try {
auto instance = Instance("vulkan playground 01");
cout << "Vulkan instance created" << endl;
// Get all Vulkan devices
std::vector<::vk::PhysicalDevice> devices;
instance.enumeratePhysicalDevices(devices);
// Find Vulkan GPU
const ::vk::PhysicalDevice* gpu = nullptr;
for(const auto& dev : devices) {
const auto& qprops = dev.getQueueFamilyProperties();
const auto it = find_if(
qprops.cbegin(), qprops.cend(),
[](auto& qpr) { return qpr.queueFlags() & ::vk::QueueFlagBits::eGraphics; });
if(it != qprops.cend()) {
gpu = &dev;
break;
}
}
if(!gpu)
throw runtime_error("Unable to find GPU");
// Create device object
float priorities[] = {1.0f};
auto queue_info = ::vk::DeviceQueueCreateInfo().queueCount(1).pQueuePriorities(priorities);
auto device_info = ::vk::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(&queue_info);
auto device = gpu->createDevice(device_info, nullptr);
cout << "Vulkan device created" << endl;
device.destroy(nullptr);
cout << "Vulkan device destroyed" << endl;
}
catch(const exception& err) {
cerr << "[ERROR] " << err.what() << endl;
return 1;
}
}
If one would use Vulkan device for doing GPU calculations, then she or he should use vk::QueueFlagBits::eCompute flag in searching for proper device.
No comments:
Post a Comment