https://nvpro-samples.github.io/vk_mini_path_tracer/
https://github.com/nvpro-samples/vk_mini_path_tracer
Preview of later output
Navigate to the where the code should go
Run in a command line:
Then open the build_all folder and run either clone_all.bat (Windows) or clone_all.sh (Linux)
git clone https://github.com/nvpro-samples/build_all.git#include <nvvk/context_vk.hpp>
int main(int argc, const char** argv)
{
// Create the Vulkan context, consisting of an instance, device, physical device, and queues.
// One can modify this to load different extensions or pick the Vulkan core version
nvvk::ContextCreateInfo deviceInfo;
nvvk::Context context; // Encapsulates device state in a single object
context.init(deviceInfo); // Initialize the context
context.deinit(); // Don't forget to clean up at the end of the program!
}context.init(deviceInfo);
ContextCreateInfo(bool bUseValidation = true);nvvk::ContextCreateInfo deviceInfo;
nvvk::Context context;
context.init(deviceInfo);
// Invalid call!
vkAllocateCommandBuffers(context, nullptr, nullptr);ERROR: VUID-vkAllocateCommandBuffers-pAllocateInfo-parameter
--> Validation Error: [ VUID-vkAllocateCommandBuffers-pAllocateInfo-parameter ]
Object 0: handle = 0x158dfd26f68, type = VK_OBJECT_TYPE_DEVICE; |
MessageID = 0x72e32441 | vkAllocateCommandBuffers: required parameter
pAllocateInfo specified as NULL The Vulkan spec states: pAllocateInfo must be a
valid pointer to a valid VkCommandBufferAllocateInfo structure
(https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/
vkspec.html#VUID-vkAllocateCommandBuffers-pAllocateInfo-parameter)What validation reports
Add these additional includes to the code
#include <cassert>
#include <nvvk/context_vk.hpp>
#include <nvvk/structs_vk.hpp> // For nvvk::makedeviceInfo.apiMajor = 1; // Specify the version of Vulkan we'll use
deviceInfo.apiMinor = 2;Output should be now have something like
_______________
Vulkan Version:
- available: 1.2.154
- requesting: 1.2.0Many Vulkan structures have `sType` as the first member
This is for the driver & layer to know the 'type'
Multiple methods to set it
Manual:
nvvk::make
auto + nvvk::make
use vulkan.hpp
VkPhysicalDeviceRayQueryFeaturesKHR rtFeatures =
{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR};VkPhysicalDeviceRayQueryFeaturesKHR rtFeatures =
nvvk::make<VkPhysicalDeviceRayQueryFeaturesKHR>();auto rtFeatures = nvvk::make<VkPhysicalDeviceRayQueryFeaturesKHR>();Done through ContextCreateInfo
// Required by VK_KHR_ray_query; allows work to be offloaded
// onto background threads and parallelized
deviceInfo.addDeviceExtension(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);Some extensions have 'Features' that aren't guaranteed
We can query them by giving the context a`Features` struct by pointer that the driver fills in.
auto asFeatures = nvvk::make<VkPhysicalDeviceAccelerationStructureFeaturesKHR>();
deviceInfo.addDeviceExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, false, &asFeatures);
auto rayQueryFeatures = nvvk::make<VkPhysicalDeviceRayQueryFeaturesKHR>();
deviceInfo.addDeviceExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME, false, &rayQueryFeatures);
// Device must support acceleration structures and ray queries:
assert(asFeatures.accelerationStructure == VK_TRUE && rayQueryFeatures.rayQuery == VK_TRUE);'false' indicates the extension is 'required' and should abort if not available
In general, this means we try to do what we need on the CPU, upload the data all at once, then let the GPU work on it as much as possible before sending it back.
We need to include it first
#define NVVK_ALLOC_DEDICATED
#include <nvvk/allocator_vk.hpp> // For NVVK memory allocatorsThen we create and initialize it
// Create the allocator
nvvk::AllocatorDedicated allocator;
allocator.init(context, context.m_physicalDevice);After we are done, we need to destroy it
allocator.deinit();Helpful wrapper to handle memory allocation
// Create a buffer
VkDeviceSize bufferSizeBytes =
pushConstants.render_width * pushConstants.render_height * 3 * sizeof(float);
VkBufferCreateInfo bufferCreateInfo = nvvk::make<VkBufferCreateInfo>();
bufferCreateInfo.size = bufferSizeBytes;
bufferCreateInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
// VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT means that the CPU can read this buffer's memory.
// VK_MEMORY_PROPERTY_HOST_CACHED_BIT means that the CPU caches this memory.
// VK_MEMORY_PROPERTY_HOST_COHERENT_BIT means that the CPU side of cache management
// is handled automatically, with potentially slower reads/writes.
nvvk::BufferDedicated buffer = allocator.createBuffer(bufferCreateInfo,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);void* data = allocator.map(buffer);
float* fltData = reinterpret_cast<float*>(data);
printf("First four elements: %f, %f, %f, %f\n", fltData[0], fltData[1], fltData[2], fltData[3]);
allocator.unmap(buffer);First four elements: 0.000, 0.000, 0.000, 0.000
Run the program...