-
-
Save Loulfy/b4fdef7a99ae0c72c74c81469d2a69cf to your computer and use it in GitHub Desktop.
Minimal Vulkan KickstartRT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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