Added HLSL shaders for ray tracing callable sample

Minor cleanup
This commit is contained in:
Sascha Willems 2021-03-06 16:21:09 +01:00
parent 35288a6f2b
commit 5db9781d52
14 changed files with 168 additions and 63 deletions

View file

@ -308,7 +308,7 @@ Renders a complex scene with reflective surfaces using the new ray tracing exten
#### [Callable ray tracing shaders](examples/raytracingcallable) #### [Callable ray tracing shaders](examples/raytracingcallable)
Callable shaders can be dynamically invoked from within other ray tracing shaders to execute different shaders based on your own conditions. The example ray traces multiple geometries, with each calling a different callable shader from the closest hit shader. Callable shaders can be dynamically invoked from within other ray tracing shaders to execute different shaders based on dynamic conditions. The example ray traces multiple geometries, with each calling a different callable shader from the closest hit shader.
#### [Ray query](examples/rayquery) #### [Ray query](examples/rayquery)

View file

@ -8,6 +8,4 @@ void main()
// Generate a line pattern // Generate a line pattern
vec2 pos = vec2(gl_LaunchIDEXT / 8); vec2 pos = vec2(gl_LaunchIDEXT / 8);
outColor = vec3(mod(pos.y, 2.0)); outColor = vec3(mod(pos.y, 2.0));
// outColor = vec3(0.0, 0.0, 1.0);
} }

View file

@ -1,9 +0,0 @@
#version 460
#extension GL_EXT_ray_tracing : require
layout(location = 2) rayPayloadInEXT bool shadowed;
void main()
{
shadowed = false;
}

View file

@ -0,0 +1,14 @@
// Copyright 2021 Sascha Willems
struct CallData
{
vec3 outColor;
};
[shader("callable")]
void main(inout CallData data)
{
// Generate a checker board pattern
float2 pos = float2(DispatchRaysIndex() / 8);
data.outColor = float3(mod(pos.x + mod(pos.y, 2.0), 2.0));
}

View file

@ -0,0 +1,12 @@
// Copyright 2021 Sascha Willems
struct CallData
{
vec3 outColor;
};
[shader("callable")]
void main(inout CallData data)
{
data.outColor = float3(0.0, 1.0, 0.0);
}

View file

@ -0,0 +1,14 @@
// Copyright 2021 Sascha Willems
struct CallData
{
vec3 outColor;
};
[shader("callable")]
void main(inout CallData data)
{
// Generate a checker board pattern
float2 pos = float2(DispatchRaysIndex() / 8);
data.outColor = float3(mod(pos.y, 2.0));
}

View file

@ -0,0 +1,26 @@
// Copyright 2021 Sascha Willems
struct Attribute
{
float2 attribs;
};
struct Payload
{
[[vk::location(0)]] float3 hitValue;
};
struct CallData
{
float3 outColor;
};
[shader("closesthit")]
void main(inout Payload p, in float3 attribs)
{
// Execute the callable shader indexed by the current geometry being hit
// For our sample this means that the first callable shader in the SBT is invoked for the first triangle, the second callable shader for the second triangle, etc.
CallData callData;
CallShader(GeometryIndex(), callData);
p.hitValue = callData.outColor;
}

View file

@ -0,0 +1,12 @@
// Copyright 2021 Sascha Willems
struct Payload
{
[[vk::location(0)]] float3 hitValue;
};
[shader("miss")]
void main(inout Payload p)
{
p.hitValue = float3(0.0, 0.0, 0.2);
}

Binary file not shown.

View file

@ -0,0 +1,39 @@
// Copyright 2021 Sascha Willems
RaytracingAccelerationStructure rs : register(t0);
RWTexture2D<float4> image : register(u1);
struct CameraProperties
{
float4x4 viewInverse;
float4x4 projInverse;
};
cbuffer cam : register(b2) { CameraProperties cam; };
struct Payload
{
[[vk::location(0)]] float3 hitValue;
};
[shader("raygeneration")]
void main()
{
uint3 LaunchID = DispatchRaysIndex();
uint3 LaunchSize = DispatchRaysDimensions();
const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5);
const float2 inUV = pixelCenter/float2(LaunchSize.xy);
float2 d = inUV * 2.0 - 1.0;
float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1));
RayDesc rayDesc;
rayDesc.Origin = mul(cam.viewInverse, float4(0,0,0,1)).xyz;
rayDesc.Direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0)).xyz;
rayDesc.TMin = 0.001;
rayDesc.TMax = 10000.0;
Payload payload;
TraceRay(rs, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, payload);
image[int2(LaunchID.xy)] = float4(payload.hitValue, 0.0);
}

Binary file not shown.

View file

@ -1,9 +1,11 @@
/* /*
* Vulkan Example - Hardware accelerated ray tracing callable shaders example * Vulkan Example - Hardware accelerated ray tracing callable shaders example
* *
* Renders a complex scene using multiple hit and miss shaders for implementing shadows * Dynamically calls different shaders based on the geoemtry id in the closest hit shader
* *
* Copyright (C) by Sascha Willems - www.saschawillems.de * Relevant code parts are marked with [POI]
*
* Copyright (C) 2021 by Sascha Willems - www.saschawillems.de
* *
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/ */
@ -56,20 +58,22 @@ public:
~VulkanExample() ~VulkanExample()
{ {
vkDestroyPipeline(device, pipeline, nullptr); if (device) {
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipeline(device, pipeline, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
deleteStorageImage(); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
deleteAccelerationStructure(bottomLevelAS); deleteStorageImage();
deleteAccelerationStructure(topLevelAS); deleteAccelerationStructure(bottomLevelAS);
shaderBindingTables.raygen.destroy(); deleteAccelerationStructure(topLevelAS);
shaderBindingTables.miss.destroy(); shaderBindingTables.raygen.destroy();
shaderBindingTables.hit.destroy(); shaderBindingTables.miss.destroy();
shaderBindingTables.callable.destroy(); shaderBindingTables.hit.destroy();
vertexBuffer.destroy(); shaderBindingTables.callable.destroy();
indexBuffer.destroy(); vertexBuffer.destroy();
transformBuffer.destroy(); indexBuffer.destroy();
ubo.destroy(); transformBuffer.destroy();
ubo.destroy();
}
} }
/* /*
@ -183,6 +187,7 @@ public:
accelerationBuildGeometryInfo.pGeometries = accelerationStructureGeometries.data(); accelerationBuildGeometryInfo.pGeometries = accelerationStructureGeometries.data();
accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress; accelerationBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.deviceAddress;
// [POI] The bottom level acceleration structure for this sample contains three separate triangle geometries, so we can use gl_GeometryIndexEXT in the closest hit shader to select different callable shaders
std::vector<VkAccelerationStructureBuildRangeInfoKHR> accelerationStructureBuildRangeInfos{}; std::vector<VkAccelerationStructureBuildRangeInfoKHR> accelerationStructureBuildRangeInfos{};
for (uint32_t i = 0; i < objectCount; i++) { for (uint32_t i = 0; i < objectCount; i++) {
VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{}; VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfo{};
@ -350,7 +355,7 @@ public:
createShaderBindingTable(shaderBindingTables.raygen, 1); createShaderBindingTable(shaderBindingTables.raygen, 1);
createShaderBindingTable(shaderBindingTables.miss, 1); createShaderBindingTable(shaderBindingTables.miss, 1);
createShaderBindingTable(shaderBindingTables.hit, 1); createShaderBindingTable(shaderBindingTables.hit, 1);
// The callable shader binding table contains one shader handle per ray traced object // [POI] The callable shader binding table contains one shader handle per ray traced object
createShaderBindingTable(shaderBindingTables.callable, objectCount); createShaderBindingTable(shaderBindingTables.callable, objectCount);
// Copy handles // Copy handles
@ -437,50 +442,44 @@ public:
Setup ray tracing shader groups Setup ray tracing shader groups
*/ */
std::vector<VkPipelineShaderStageCreateInfo> shaderStages; std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
VkRayTracingShaderGroupCreateInfoKHR shaderGroup;
// Ray generation shader group // Ray generation shader group
{ shaderStages.push_back(loadShader(getShadersPath() + "raytracingcallable/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR));
shaderStages.push_back(loadShader(getShadersPath() + "raytracingcallable/raygen.rgen.spv", VK_SHADER_STAGE_RAYGEN_BIT_KHR)); shaderGroup = vks::initializers::rayTracingShaderGroupCreateInfoKHR();
VkRayTracingShaderGroupCreateInfoKHR shaderGroup = vks::initializers::rayTracingShaderGroupCreateInfoKHR(); shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1;
shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1; shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR;
shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; shaderGroups.push_back(shaderGroup);
shaderGroups.push_back(shaderGroup);
}
// Miss shader group // Miss shader group
{ shaderStages.push_back(loadShader(getShadersPath() + "raytracingcallable/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR));
shaderStages.push_back(loadShader(getShadersPath() + "raytracingcallable/miss.rmiss.spv", VK_SHADER_STAGE_MISS_BIT_KHR)); shaderGroup = vks::initializers::rayTracingShaderGroupCreateInfoKHR();
VkRayTracingShaderGroupCreateInfoKHR shaderGroup = vks::initializers::rayTracingShaderGroupCreateInfoKHR(); shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1;
shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1; shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR;
shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; shaderGroups.push_back(shaderGroup);
shaderGroups.push_back(shaderGroup);
}
// Closest hit shader group // Closest hit shader group
{ shaderStages.push_back(loadShader(getShadersPath() + "raytracingcallable/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR));
shaderStages.push_back(loadShader(getShadersPath() + "raytracingcallable/closesthit.rchit.spv", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR)); shaderGroup = vks::initializers::rayTracingShaderGroupCreateInfoKHR();
VkRayTracingShaderGroupCreateInfoKHR shaderGroup = vks::initializers::rayTracingShaderGroupCreateInfoKHR(); shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; shaderGroup.generalShader = VK_SHADER_UNUSED_KHR;
shaderGroup.generalShader = VK_SHADER_UNUSED_KHR; shaderGroup.closestHitShader = static_cast<uint32_t>(shaderStages.size()) - 1;
shaderGroup.closestHitShader = static_cast<uint32_t>(shaderStages.size()) - 1; shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
shaderGroup.anyHitShader = VK_SHADER_UNUSED_KHR; shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
shaderGroup.intersectionShader = VK_SHADER_UNUSED_KHR; shaderGroups.push_back(shaderGroup);
shaderGroups.push_back(shaderGroup);
}
// Callable shader group // [POI] Callable shader group
// This sample's hit shader will call different callable shaders depending on the geometry index, so as we render three different geometries, we'll also use three callable shaders // This sample's hit shader will call different callable shaders depending on the geometry index using executeCallableEXT, so as we render three geometries, we'll also use three callable shaders
for (uint32_t i = 0; i < objectCount; i++) for (uint32_t i = 0; i < objectCount; i++)
{ {
shaderStages.push_back(loadShader(getShadersPath() + "raytracingcallable/callable" + std::to_string(i+1) + ".rcall.spv", VK_SHADER_STAGE_CALLABLE_BIT_KHR)); shaderStages.push_back(loadShader(getShadersPath() + "raytracingcallable/callable" + std::to_string(i+1) + ".rcall.spv", VK_SHADER_STAGE_CALLABLE_BIT_KHR));
VkRayTracingShaderGroupCreateInfoKHR shaderGroup{}; shaderGroup = vks::initializers::rayTracingShaderGroupCreateInfoKHR();
shaderGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; shaderGroup.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1; shaderGroup.generalShader = static_cast<uint32_t>(shaderStages.size()) - 1;
shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR; shaderGroup.closestHitShader = VK_SHADER_UNUSED_KHR;