Skip to content

Instantly share code, notes, and snippets.

@Loulfy

Loulfy/main.cpp Secret

Last active December 13, 2022 13:33
Show Gist options
  • Save Loulfy/b4fdef7a99ae0c72c74c81469d2a69cf to your computer and use it in GitHub Desktop.
Save Loulfy/b4fdef7a99ae0c72c74c81469d2a69cf to your computer and use it in GitHub Desktop.
Minimal Vulkan KickstartRT
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
#include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
// Be careful! This example uses VulkanMemoryAllocatorHpp v3.0.1
// https://github.com/YaaZ/VulkanMemoryAllocator-Hpp
#define VMA_IMPLEMENTATION
#include <vk_mem_alloc.hpp>
#define KickstartRT_Graphics_API_Vulkan
#include <KickstartRT.h>
namespace KS = KickstartRT::VK;
// CUBE MESH
static const std::array<uint32_t,36> indices = {
2, 1, 0,
5, 4, 3,
8, 7, 6,
11, 10, 9,
14, 13, 12,
17, 16, 15,
2, 0, 18,
5, 3, 19,
8, 6, 20,
11, 9, 21,
14, 12, 22,
17, 15, 23,
};
static const std::array<float,72> vertices = {
1, -1, -1,
-1, -1, -1,
-1, -1, 1,
-1, 1, 1,
-1, 1, -1,
1, 1, -1,
1, 1, 1,
1, 1, -1,
1, -1, -1,
1, 1, -1,
-1, 1, -1,
-1, -1, -1,
-1, -1, -1,
-1, 1, -1,
-1, 1, 1,
1, -1, 1,
-1, -1, 1,
-1, 1, 1,
1, -1, 1,
1, 1, 1,
1, -1, 1,
1, -1, -1,
-1, -1, 1,
1, 1, 1,
};
int main()
{
static const vk::DynamicLoader dl;
const auto vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
std::initializer_list<const char*> extensions = {
VK_EXT_DEBUG_UTILS_EXTENSION_NAME
};
std::initializer_list<const char*> layers = {
"VK_LAYER_KHRONOS_validation"
};
std::initializer_list<const char*> devices = {
VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME,
VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME
};
// Create instance
vk::ApplicationInfo appInfo;
appInfo.setApiVersion(VK_API_VERSION_1_3);
appInfo.setPEngineName("minimalKS");
vk::InstanceCreateInfo instInfo;
instInfo.setPApplicationInfo(&appInfo);
instInfo.setPEnabledLayerNames(layers);
instInfo.setPEnabledExtensionNames(extensions);
auto instance = vk::createInstanceUnique(instInfo);
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance.get());
// Pick First GPU
auto physicalDevice = instance->enumeratePhysicalDevices().front();
// Device Features
auto features = physicalDevice.getFeatures();
// Find Graphics Queue
const auto queueFamilies = physicalDevice.getQueueFamilyProperties();
const auto family = std::find_if(queueFamilies.begin(), queueFamilies.end(), [](const vk::QueueFamilyProperties& queueFamily) {
return queueFamily.queueCount > 0 && queueFamily.queueFlags & vk::QueueFlagBits::eGraphics;
});
uint32_t graphicsQueueFamily = std::distance(queueFamilies.begin(), family);
// Create queues
float queuePriority = 1.0f;
std::initializer_list<vk::DeviceQueueCreateInfo> queueCreateInfos = {
{ {}, graphicsQueueFamily, 1, &queuePriority }
};
// Create Device
vk::DeviceCreateInfo deviceInfo;
deviceInfo.setQueueCreateInfos(queueCreateInfos);
deviceInfo.setPEnabledExtensionNames(devices);
deviceInfo.setPEnabledLayerNames(layers);
deviceInfo.setPEnabledFeatures(&features);
vk::PhysicalDeviceVulkan12Features vulkan12Features;
vulkan12Features.setBufferDeviceAddress(true);
vulkan12Features.setDescriptorBindingVariableDescriptorCount(true);
vk::StructureChain<vk::DeviceCreateInfo,
vk::PhysicalDeviceRayTracingPipelineFeaturesKHR,
vk::PhysicalDeviceAccelerationStructureFeaturesKHR,
vk::PhysicalDeviceVulkan12Features> createInfoChain(deviceInfo, {true}, {true}, vulkan12Features);
auto device = physicalDevice.createDeviceUnique(createInfoChain.get<vk::DeviceCreateInfo>());
VULKAN_HPP_DEFAULT_DISPATCHER.init(device.get());
auto queue = device->getQueue(graphicsQueueFamily, 0);
auto commandPool = device->createCommandPoolUnique({ vk::CommandPoolCreateFlagBits::eResetCommandBuffer, graphicsQueueFamily });
// Create VMA Allocator
vma::AllocatorCreateInfo allocatorInfo = {};
vma::AllocationCreateInfo buffAllocInfo = {};
buffAllocInfo.usage = vma::MemoryUsage::eCpuOnly;
allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_3;
allocatorInfo.physicalDevice = physicalDevice;
allocatorInfo.instance = instance.get();
allocatorInfo.device = device.get();
auto allocator = vma::createAllocator(allocatorInfo);
// Create Buffers
vk::BufferUsageFlags usageFlags = vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eTransferDst;
usageFlags |= vk::BufferUsageFlagBits::eIndexBuffer;
usageFlags |= vk::BufferUsageFlagBits::eVertexBuffer;
usageFlags |= vk::BufferUsageFlagBits::eUniformTexelBuffer;
usageFlags |= vk::BufferUsageFlagBits::eAccelerationStructureBuildInputReadOnlyKHR;
auto buffInfo = vk::BufferCreateInfo();
buffInfo.setUsage(usageFlags);
buffInfo.setSharingMode(vk::SharingMode::eExclusive);
// Index Buffer
buffInfo.setSize(indices.size() * sizeof(uint32_t));
auto [indexBuffer, indexAlloc] = allocator.createBuffer(buffInfo, buffAllocInfo);
void* data = allocator.mapMemory(indexAlloc);
std::memcpy(data, indices.data(), indices.size() * sizeof(uint32_t));
allocator.unmapMemory(indexAlloc);
// Vertex Buffer
buffInfo.setSize(vertices.size() * sizeof(float));
auto [vertexBuffer, vertexAlloc] = allocator.createBuffer(buffInfo, buffAllocInfo);
data = allocator.mapMemory(vertexAlloc);
std::memcpy(data, vertices.data(), vertices.size() * sizeof(float));
allocator.unmapMemory(vertexAlloc);
// Init KickstartRT
KS::ExecuteContext* context;
KS::ExecuteContext_InitSettings settings;
settings.physicalDevice = physicalDevice;
settings.instance = instance.get();
settings.device = device.get();
KS::ExecuteContext::Init(&settings, &context);
auto taskContainer = context->CreateTaskContainer();
// Create BVH
KS::BVHTask::GeometryTask taskGeom;
// create a geometry handle
context->CreateGeometryHandles(&taskGeom.handle, 1);
taskGeom.taskOperation = KS::BVHTask::TaskOperation::Register;
taskGeom.input.allowUpdate = false;
taskGeom.input.type = decltype(taskGeom.input)::Type::TrianglesIndexed;
taskGeom.input.surfelType = KS::BVHTask::GeometryInput::SurfelType::WarpedBarycentricStorage;
// populate the index buffer and vertex buffer data
decltype(taskGeom.input)::GeometryComponent cmp;
cmp.indexBuffer.typedBuffer = indexBuffer;
cmp.indexBuffer.format = VK_FORMAT_R32_UINT;
cmp.indexBuffer.offsetInBytes = 0;
cmp.indexBuffer.count = indices.size();
cmp.vertexBuffer.typedBuffer = vertexBuffer;
cmp.vertexBuffer.format = VK_FORMAT_R32G32B32_SFLOAT;
cmp.vertexBuffer.offsetInBytes = 0;
cmp.vertexBuffer.strideInBytes = sizeof(float) * 3;
cmp.vertexBuffer.count = vertices.size()/3;
cmp.useTransform = false;
taskGeom.input.components.push_back(cmp);
taskContainer->ScheduleBVHTask(&taskGeom);
KS::BVHTask::BVHBuildTask task;
taskContainer->ScheduleBVHTask(&task);
// Allocate command buffer
auto allocInfo = vk::CommandBufferAllocateInfo();
allocInfo.setLevel(vk::CommandBufferLevel::ePrimary);
allocInfo.setCommandPool(commandPool.get());
allocInfo.setCommandBufferCount(1);
vk::Result res;
vk::CommandBuffer cmd;
res = device->allocateCommandBuffers(&allocInfo, &cmd);
assert(res == vk::Result::eSuccess);
// Record the task
KS::BuildGPUTaskInput input = {};
KS::GPUTaskHandle taskHandleTicket;
input.commandBuffer = cmd;
cmd.begin({vk::CommandBufferUsageFlagBits::eOneTimeSubmit});
// Record the scheduled work to the command list
context->BuildGPUTask(&taskHandleTicket, taskContainer, &input);
cmd.end();
vk::SubmitInfo submitInfo;
submitInfo.setCommandBuffers(cmd);
// Submit & wait
queue.submit(submitInfo);
queue.waitIdle();
// Complete
context->MarkGPUTaskAsCompleted(taskHandleTicket);
// Clean
context->DestroyAllInstanceHandles();
context->DestroyAllGeometryHandles();
KS::ExecuteContext::Destruct(context);
allocator.destroyBuffer(indexBuffer, indexAlloc);
allocator.destroyBuffer(vertexBuffer, vertexAlloc);
allocator.destroy();
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment