Using final KHR ray tracing extension: VK_KHR_acceleration_structure, VK_KHR_ray_tracing_pipeline and VK_KHR_ray_query

This commit is contained in:
mklefrancois 2020-11-23 11:33:51 +01:00
parent 7179569ec3
commit b26ff92473
80 changed files with 2446 additions and 2351 deletions

View file

@ -1,32 +1,38 @@
cmake_minimum_required(VERSION 2.8)
#*****************************************************************************
# Copyright 2020 NVIDIA Corporation. All rights reserved.
#*****************************************************************************
cmake_minimum_required(VERSION 3.9.6 FATAL_ERROR)
#--------------------------------------------------------------------------------------------------
# Project setting
get_filename_component(PROJNAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
SET(PROJNAME vk_${PROJNAME}_KHR)
project(${PROJNAME} LANGUAGES C CXX)
message(STATUS "-------------------------------")
message(STATUS "Processing Project ${PROJNAME}:")
Project(${PROJNAME})
Message(STATUS "-------------------------------")
Message(STATUS "Processing Project ${PROJNAME}:")
#####################################################################################
_add_project_definitions(${PROJNAME})
#--------------------------------------------------------------------------------------------------
# C++ target and defines
set(CMAKE_CXX_STANDARD 17)
add_executable(${PROJNAME})
target_compile_definitions(${PROJNAME} PUBLIC PROJECT_NAME="${PROJNAME}")
#####################################################################################
#--------------------------------------------------------------------------------------------------
# Source files for this project
#
file(GLOB SOURCE_FILES *.cpp *.hpp *.inl *.h *.c)
file(GLOB EXTRA_COMMON "../common/*.*")
file(GLOB EXTRA_COMMON ${TUTO_KHR_DIR}/common/*.*)
list(APPEND COMMON_SOURCE_FILES ${EXTRA_COMMON})
include_directories("../common")
include_directories(${TUTO_KHR_DIR}/common)
#####################################################################################
#--------------------------------------------------------------------------------------------------
# GLSL to SPIR-V custom build
#
# more than one file can be given: _compile_GLSL("GLSL_mesh.vert;GLSL_mesh.frag" "GLSL_mesh.spv" GLSL_SOURCES)
# the SpirV validator is fine as long as files are for different pipeline stages (entry points still need to be main())
#_compile_GLSL(<source(s)> <target spv> <LIST where files are appended>)
SET(VULKAN_TARGET_ENV vulkan1.2)
UNSET(GLSL_SOURCES)
UNSET(SPV_OUTPUT)
file(GLOB_RECURSE GLSL_HEADER_FILES "shaders/*.h" "shaders/*.glsl")
@ -36,48 +42,36 @@ file(GLOB_RECURSE GLSL_SOURCE_FILES
"shaders/*.vert"
"shaders/*.rchit"
"shaders/*.rahit"
"shaders/*.rint"
"shaders/*.rmiss"
"shaders/*.rgen"
"shaders/*.rcall"
)
foreach(GLSL ${GLSL_SOURCE_FILES})
get_filename_component(FILE_NAME ${GLSL} NAME)
_compile_GLSL(${GLSL} "shaders/${FILE_NAME}.spv" GLSL_SOURCES SPV_OUTPUT)
endforeach(GLSL)
list(APPEND GLSL_SOURCES ${GLSL_HEADER_FILES})
source_group(Shader_Files FILES ${GLSL_SOURCES})
#####################################################################################
# Executable
#--------------------------------------------------------------------------------------------------
# Sources
target_sources(${PROJNAME} PUBLIC ${SOURCE_FILES} ${HEADER_FILES})
target_sources(${PROJNAME} PUBLIC ${COMMON_SOURCE_FILES})
target_sources(${PROJNAME} PUBLIC ${PACKAGE_SOURCE_FILES})
target_sources(${PROJNAME} PUBLIC ${GLSL_SOURCES})
#--------------------------------------------------------------------------------------------------
# Sub-folders in Visual Studio
#
# if(WIN32 AND NOT GLUT_FOUND)
# add_definitions(/wd4996) #remove printf warning
# add_definitions(/wd4244) #remove double to float conversion warning
# add_definitions(/wd4305) #remove double to float truncation warning
# else()
# add_definitions(-fpermissive)
# endif()
add_executable(${PROJNAME} ${SOURCE_FILES} ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES} ${GLSL_SOURCES} ${CUDA_FILES} ${CUBIN_SOURCES})
source_group("Common" FILES ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES})
source_group("Sources" FILES ${SOURCE_FILES})
source_group("Headers" FILES ${HEADER_FILES})
source_group("Shader_Files" FILES ${GLSL_SOURCES})
#_set_subsystem_console(${PROJNAME})
#####################################################################################
# common source code needed for this sample
#
source_group(common FILES
${COMMON_SOURCE_FILES}
${PACKAGE_SOURCE_FILES}
)
source_group("Source Files" FILES ${SOURCE_FILES})
# if(UNIX)
# set(UNIXLINKLIBS dl pthread)
# else()
# set(UNIXLINKLIBS)
# endif()
#####################################################################################
#--------------------------------------------------------------------------------------------------
# Linkage
#
target_link_libraries(${PROJNAME} ${PLATFORM_LIBRARIES} shared_sources)
@ -90,15 +84,28 @@ foreach(RELEASELIB ${LIBRARIES_OPTIMIZED})
target_link_libraries(${PROJNAME} optimized ${RELEASELIB})
endforeach(RELEASELIB)
#####################################################################################
#--------------------------------------------------------------------------------------------------
# copies binaries that need to be put next to the exe files (ZLib, etc.)
#
_copy_binaries_to_target( ${PROJNAME} )
install(FILES ${SPV_OUTPUT} CONFIGURATIONS Release DESTINATION "bin_${ARCH}/${PROJNAME}/shaders")
install(FILES ${SPV_OUTPUT} CONFIGURATIONS Debug DESTINATION "bin_${ARCH}_debug/${PROJNAME}/shaders")
install(FILES ${CUBIN_SOURCES} CONFIGURATIONS Release DESTINATION "bin_${ARCH}/${PROJNAME}")
install(FILES ${CUBIN_SOURCES} CONFIGURATIONS Debug DESTINATION "bin_${ARCH}_debug/${PROJNAME}")
install(DIRECTORY "../media" CONFIGURATIONS Release DESTINATION "bin_${ARCH}/${PROJNAME}")
install(DIRECTORY "../media" CONFIGURATIONS Debug DESTINATION "bin_${ARCH}_debug/${PROJNAME}")
#install(FILES ${SPV_OUTPUT} CONFIGURATIONS Release DESTINATION "bin_${ARCH}/${PROJNAME}/shaders")
#install(FILES ${SPV_OUTPUT} CONFIGURATIONS Debug DESTINATION "bin_${ARCH}_debug/${PROJNAME}/shaders")
#install(FILES ${CUBIN_SOURCES} CONFIGURATIONS Release DESTINATION "bin_${ARCH}/${PROJNAME}")
#install(FILES ${CUBIN_SOURCES} CONFIGURATIONS Debug DESTINATION "bin_${ARCH}_debug/${PROJNAME}")
#install(DIRECTORY "../media" CONFIGURATIONS Release DESTINATION "bin_${ARCH}/${PROJNAME}")
#install(DIRECTORY "../media" CONFIGURATIONS Debug DESTINATION "bin_${ARCH}_debug/${PROJNAME}")
#----------------------------------------------------------------------------------------------------
# Copying elements
# Media
# target_copy_to_output_dir(TARGET ${PROJECT_NAME} FILES "${TUTO_KHR_DIR}/media")
# Spir-V Shaders
target_copy_to_output_dir(
TARGET ${PROJECT_NAME}
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
DEST_SUBFOLDER "${PROJECT_NAME}/"
FILES ${SPV_OUTPUT}
)

View file

@ -30,9 +30,9 @@ Then replace the calls to `helloVk.loadModel` in `main()` by
~~~~ C++
// Creation of the example
helloVk.loadModel(nvh::findFile("media/scenes/cube.obj", defaultSearchPaths));
helloVk.loadModel(nvh::findFile("media/scenes/cube_multi.obj", defaultSearchPaths));
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths));
helloVk.loadModel(nvh::findFile("media/scenes/cube.obj", defaultSearchPaths, true));
helloVk.loadModel(nvh::findFile("media/scenes/cube_multi.obj", defaultSearchPaths, true));
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths, true));
std::random_device rd; // Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
@ -55,7 +55,7 @@ Then replace the calls to `helloVk.loadModel` in `main()` by
}
~~~~
:warning: **Note:**
**Note:**
This will create 3 models (OBJ) and their instances, and then add 2000 instances
distributed between green cubes and cubes with one color per face.
@ -73,7 +73,7 @@ Remove the previous code and replace it with the following
std::normal_distribution<float> disn(0.05f, 0.05f);
for(int n = 0; n < 2000; ++n)
{
helloVk.loadModel(nvh::findFile("media/scenes/cube_multi.obj", defaultSearchPaths));
helloVk.loadModel(nvh::findFile("media/scenes/cube_multi.obj", defaultSearchPaths, true));
HelloVulkan::ObjInstance& inst = helloVk.m_objInstance.back();
float scale = fabsf(disn(gen));
@ -85,7 +85,7 @@ Remove the previous code and replace it with the following
inst.transformIT = nvmath::transpose(nvmath::invert((inst.transform)));
}
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths));
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths, true));
~~~~
The example might still work, but the console will print the following error after loading 1363 objects. All other objects allocated after the 1363rd will fail to be displayed.

View file

@ -41,6 +41,7 @@ extern std::vector<std::string> defaultSearchPaths;
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvh/alignment.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
@ -178,7 +179,7 @@ void HelloVulkan::updateDescriptorSet()
std::vector<vk::DescriptorImageInfo> diit;
for(auto& texture : m_textures)
{
diit.push_back(texture.descriptor);
diit.emplace_back(texture.descriptor);
}
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
@ -209,8 +210,8 @@ void HelloVulkan::createGraphicsPipeline()
std::vector<std::string> paths = defaultSearchPaths;
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths, true), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths, true), vkSS::eFragment);
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
@ -228,6 +229,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
{
using vkBU = vk::BufferUsageFlagBits;
LOGI("Loading File: %s \n", filename.c_str());
ObjLoader loader;
loader.loadModel(filename);
@ -254,10 +256,12 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress
| vkBU::eAccelerationStructureBuildInputReadOnlyKHR);
model.indexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_indices,
vkBU::eIndexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
vkBU::eIndexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress
| vkBU::eAccelerationStructureBuildInputReadOnlyKHR);
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, vkBU::eStorageBuffer);
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found
@ -330,7 +334,7 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the dummy texure
// Creating the dummy texture
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
@ -348,9 +352,10 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
std::stringstream o;
int texWidth, texHeight, texChannels;
o << "media/textures/" << texture;
std::string txtFile = nvh::findFile(o.str(), defaultSearchPaths);
std::string txtFile = nvh::findFile(o.str(), defaultSearchPaths, true);
stbi_uc* stbi_pixels = stbi_load(txtFile.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
stbi_uc* stbi_pixels =
stbi_load(txtFile.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
std::array<stbi_uc, 4> color{255u, 0u, 255u, 255u};
@ -575,9 +580,9 @@ void HelloVulkan::createPostPipeline()
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
m_renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths, true),
vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths, true),
vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.createPipeline();
@ -641,47 +646,43 @@ void HelloVulkan::drawPost(vk::CommandBuffer cmdBuf)
void HelloVulkan::initRayTracing()
{
// Requesting ray tracing properties
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
auto properties =
m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPipelinePropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPipelinePropertiesKHR>();
m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
}
//--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
//
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
nvvk::RaytracingBuilderKHR::BlasInput HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{
nvvk::RaytracingBuilderKHR::Blas blas;
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asCreate.setIndexType(vk::IndexType::eUint32);
asCreate.setVertexFormat(vk::Format::eR32G32B32Sfloat);
asCreate.setMaxPrimitiveCount(model.nbIndices / 3); // Nb triangles
asCreate.setMaxVertexCount(model.nbVertices);
asCreate.setAllowsTransforms(VK_FALSE); // No adding transformation matrices
vk::DeviceAddress vertexAddress = m_device.getBufferAddress({model.vertexBuffer.buffer});
vk::DeviceAddress indexAddress = m_device.getBufferAddress({model.indexBuffer.buffer});
vk::AccelerationStructureGeometryTrianglesDataKHR triangles;
triangles.setVertexFormat(asCreate.vertexFormat);
triangles.setVertexFormat(vk::Format::eR32G32B32Sfloat);
triangles.setVertexData(vertexAddress);
triangles.setVertexStride(sizeof(VertexObj));
triangles.setIndexType(asCreate.indexType);
triangles.setIndexType(vk::IndexType::eUint32);
triangles.setIndexData(indexAddress);
triangles.setTransformData({});
triangles.setMaxVertex(model.nbVertices);
vk::AccelerationStructureGeometryKHR asGeom;
asGeom.setGeometryType(asCreate.geometryType);
// Consider the geometry opaque for optimization
asGeom.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asGeom.setFlags(vk::GeometryFlagBitsKHR::eOpaque);
asGeom.geometry.setTriangles(triangles);
vk::AccelerationStructureBuildOffsetInfoKHR offset;
vk::AccelerationStructureBuildRangeInfoKHR offset;
offset.setFirstVertex(0);
offset.setPrimitiveCount(asCreate.maxPrimitiveCount);
offset.setPrimitiveCount(model.nbIndices / 3); // nb triangles
offset.setPrimitiveOffset(0);
offset.setTransformOffset(0);
nvvk::RaytracingBuilderKHR::BlasInput blas;
blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset);
return blas;
}
@ -689,7 +690,7 @@ nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjMod
void HelloVulkan::createBottomLevelAS()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::BlasInput> allBlas;
allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel)
{
@ -775,16 +776,15 @@ void HelloVulkan::createRtPipeline()
vk::ShaderModule raygenSM =
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths, true));
vk::ShaderModule missSM =
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths, true));
// The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
vk::ShaderModule shadowmissSM = nvvk::createShaderModule(
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths, true));
std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -811,7 +811,7 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM =
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths, true));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -846,10 +846,10 @@ void HelloVulkan::createRtPipeline()
m_rtShaderGroups.size())); // 1-raygen, n-miss, n-(hit[+anyhit+intersect])
rayPipelineInfo.setPGroups(m_rtShaderGroups.data());
rayPipelineInfo.setMaxRecursionDepth(2); // Ray depth
rayPipelineInfo.setMaxPipelineRayRecursionDepth(2); // Ray depth
rayPipelineInfo.setLayout(m_rtPipelineLayout);
m_rtPipeline =
static_cast<const vk::Pipeline&>(m_device.createRayTracingPipelineKHR({}, rayPipelineInfo));
m_rtPipeline = static_cast<const vk::Pipeline&>(
m_device.createRayTracingPipelineKHR({}, {}, rayPipelineInfo));
m_device.destroy(raygenSM);
m_device.destroy(missSM);
@ -868,18 +868,23 @@ void HelloVulkan::createRtShaderBindingTable()
auto groupCount =
static_cast<uint32_t>(m_rtShaderGroups.size()); // 3 shaders: raygen, miss, chit
uint32_t groupHandleSize = m_rtProperties.shaderGroupHandleSize; // Size of a program identifier
uint32_t baseAlignment = m_rtProperties.shaderGroupBaseAlignment; // Size of shader alignment
uint32_t groupSizeAligned =
nvh::align_up(groupHandleSize, m_rtProperties.shaderGroupBaseAlignment);
// Fetch all the shader handles used in the pipeline, so that they can be written in the SBT
uint32_t sbtSize = groupCount * baseAlignment;
uint32_t sbtSize = groupCount * groupSizeAligned;
std::vector<uint8_t> shaderHandleStorage(sbtSize);
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data());
auto result = m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data());
assert(result == vk::Result::eSuccess);
// Write the handles in the SBT
m_rtSBTBuffer = m_alloc.createBuffer(sbtSize, vk::BufferUsageFlagBits::eTransferSrc,
vk::MemoryPropertyFlagBits::eHostVisible
| vk::MemoryPropertyFlagBits::eHostCoherent);
m_rtSBTBuffer = m_alloc.createBuffer(
sbtSize,
vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eShaderDeviceAddressKHR
| vk::BufferUsageFlagBits::eShaderBindingTableKHR,
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
m_debug.setObjectName(m_rtSBTBuffer.buffer, std::string("SBT").c_str());
// Write the handles in the SBT
@ -888,7 +893,7 @@ void HelloVulkan::createRtShaderBindingTable()
for(uint32_t g = 0; g < groupCount; g++)
{
memcpy(pData, shaderHandleStorage.data() + g * groupHandleSize, groupHandleSize); // raygen
pData += baseAlignment;
pData += groupSizeAligned;
}
m_alloc.unmap(m_rtSBTBuffer);
@ -917,25 +922,22 @@ void HelloVulkan::raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f&
| vk::ShaderStageFlagBits::eMissKHR,
0, m_rtPushConstants);
vk::DeviceSize progSize =
m_rtProperties.shaderGroupBaseAlignment; // Size of a program identifier
vk::DeviceSize rayGenOffset = 0u * progSize; // Start at the beginning of m_sbtBuffer
vk::DeviceSize missOffset = 1u * progSize; // Jump over raygen
vk::DeviceSize hitGroupOffset = 3u * progSize; // Jump over the previous shaders
vk::DeviceSize sbtSize = progSize * (vk::DeviceSize)m_rtShaderGroups.size();
// Size of a program identifier
uint32_t groupSize =
nvh::align_up(m_rtProperties.shaderGroupHandleSize, m_rtProperties.shaderGroupBaseAlignment);
uint32_t groupStride = groupSize;
vk::DeviceAddress sbtAddress = m_device.getBufferAddress({m_rtSBTBuffer.buffer});
// m_sbtBuffer holds all the shader handles: raygen, n-miss, hit...
const vk::StridedBufferRegionKHR raygenShaderBindingTable = {m_rtSBTBuffer.buffer, rayGenOffset,
progSize, sbtSize};
const vk::StridedBufferRegionKHR missShaderBindingTable = {m_rtSBTBuffer.buffer, missOffset,
progSize, sbtSize};
const vk::StridedBufferRegionKHR hitShaderBindingTable = {m_rtSBTBuffer.buffer, hitGroupOffset,
progSize, sbtSize};
const vk::StridedBufferRegionKHR callableShaderBindingTable;
cmdBuf.traceRaysKHR(&raygenShaderBindingTable, &missShaderBindingTable, &hitShaderBindingTable,
&callableShaderBindingTable, //
using Stride = vk::StridedDeviceAddressRegionKHR;
std::array<Stride, 4> strideAddresses{
Stride{sbtAddress + 0u * groupSize, groupStride, groupSize * 1}, // raygen
Stride{sbtAddress + 1u * groupSize, groupStride, groupSize * 2}, // miss
Stride{sbtAddress + 3u * groupSize, groupStride, groupSize * 1}, // hit
Stride{0u, 0u, 0u}}; // callable
cmdBuf.traceRaysKHR(&strideAddresses[0], &strideAddresses[1], &strideAddresses[2],
&strideAddresses[3], //
m_size.width, m_size.height, 1); //
m_debug.endLabel(cmdBuf);
}

View file

@ -145,18 +145,18 @@ public:
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay
void initRayTracing();
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS();
void createTopLevelAS();
void createRtDescriptorSet();
void updateRtDescriptorSet();
void createRtPipeline();
void createRtShaderBindingTable();
void initRayTracing();
nvvk::RaytracingBuilderKHR::BlasInput objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS();
void createTopLevelAS();
void createRtDescriptorSet();
void updateRtDescriptorSet();
void createRtPipeline();
void createRtShaderBindingTable();
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
vk::PhysicalDeviceRayTracingPipelinePropertiesKHR m_rtProperties;
nvvk::RaytracingBuilderKHR m_rtBuilder;
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool;

View file

@ -38,6 +38,7 @@ VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui_impl_glfw.h"
#include "hello_vulkan.h"
#include "imgui_camera_widget.h"
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
@ -62,19 +63,16 @@ static void onErrorCallback(int error, const char* description)
// Extra UI
void renderUI(HelloVulkan& helloVk)
{
static int item = 1;
if(ImGui::Combo("Up Vector", &item, "X\0Y\0Z\0\0"))
ImGuiH::CameraWidget();
if(ImGui::CollapsingHeader("Light"))
{
nvmath::vec3f pos, eye, up;
CameraManip.getLookat(pos, eye, up);
up = nvmath::vec3f(item == 0, item == 1, item == 2);
CameraManip.setLookat(pos, eye, up);
ImGui::RadioButton("Point", &helloVk.m_pushConstant.lightType, 0);
ImGui::SameLine();
ImGui::RadioButton("Infinite", &helloVk.m_pushConstant.lightType, 1);
ImGui::SliderFloat3("Position", &helloVk.m_pushConstant.lightPosition.x, -20.f, 20.f);
ImGui::SliderFloat("Intensity", &helloVk.m_pushConstant.lightIntensity, 0.f, 150.f);
}
ImGui::SliderFloat3("Light Position", &helloVk.m_pushConstant.lightPosition.x, -20.f, 20.f);
ImGui::SliderFloat("Light Intensity", &helloVk.m_pushConstant.lightIntensity, 0.f, 100.f);
ImGui::RadioButton("Point", &helloVk.m_pushConstant.lightType, 0);
ImGui::SameLine();
ImGui::RadioButton("Infinite", &helloVk.m_pushConstant.lightType, 1);
}
//////////////////////////////////////////////////////////////////////////
@ -116,20 +114,17 @@ int main(int argc, char** argv)
// Search path for shaders and other media
defaultSearchPaths = {
PROJECT_ABSDIRECTORY, // shaders
PROJECT_ABSDIRECTORY "../", // media
PROJECT_NAME, // installed: shaders + media
NVPSystem::exePath(),
NVPSystem::exePath() + "..",
NVPSystem::exePath() + std::string(PROJECT_NAME),
};
// Enabling the extension feature
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers
nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true);
#ifdef WIN32
contextInfo.addInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
#else
@ -143,11 +138,16 @@ int main(int argc, char** argv)
contextInfo.addDeviceExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
// #VKRay: Activate the ray tracing extension
contextInfo.addDeviceExtension(VK_KHR_RAY_TRACING_EXTENSION_NAME, false, &raytracingFeature);
contextInfo.addDeviceExtension(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
contextInfo.addDeviceExtension(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME);
contextInfo.addDeviceExtension(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
vk::PhysicalDeviceAccelerationStructureFeaturesKHR accelFeature;
contextInfo.addDeviceExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, false,
&accelFeature);
vk::PhysicalDeviceRayTracingPipelineFeaturesKHR rtPipelineFeature;
contextInfo.addDeviceExtension(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, false,
&rtPipelineFeature);
// Creating Vulkan base application
nvvk::Context vkctx{};
@ -167,7 +167,7 @@ int main(int argc, char** argv)
helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createSwapchain(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer();
helloVk.createRenderPass();
helloVk.createFrameBuffers();
@ -182,7 +182,7 @@ int main(int argc, char** argv)
std::normal_distribution<float> disn(0.05f, 0.05f);
for(int n = 0; n < 2000; ++n)
{
helloVk.loadModel(nvh::findFile("media/scenes/cube_multi.obj", defaultSearchPaths));
helloVk.loadModel(nvh::findFile("media/scenes/cube_multi.obj", defaultSearchPaths, true));
HelloVulkan::ObjInstance& inst = helloVk.m_objInstance.back();
float scale = fabsf(disn(gen));
@ -194,7 +194,7 @@ int main(int argc, char** argv)
inst.transformIT = nvmath::transpose(nvmath::invert((inst.transform)));
}
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths));
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths, true));
helloVk.createOffscreenRender();
helloVk.createDescriptorSetLayout();
@ -238,15 +238,17 @@ int main(int argc, char** argv)
helloVk.updateUniformBuffer();
// Show UI window.
if(1 == 1)
if(helloVk.showGui())
{
ImGuiH::Panel::Begin();
ImGui::ColorEdit3("Clear color", reinterpret_cast<float*>(&clearColor));
ImGui::Checkbox("Ray Tracer mode", &useRaytracer); // Switch between raster and ray tracing
renderUI(helloVk);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::Render();
ImGuiH::Control::Info("", "", "(F10) Toggle Pane", ImGuiH::Control::Flags::Disabled);
ImGuiH::Panel::End();
}
// Start rendering the scene
@ -299,6 +301,7 @@ int main(int argc, char** argv)
// Rendering tonemapper
helloVk.drawPost(cmdBuff);
// Rendering UI
ImGui::Render();
ImGui::RenderDrawDataVK(cmdBuff, ImGui::GetDrawData());
cmdBuff.endRenderPass();
}