vulkan triangle

This commit is contained in:
Jorijn van der Graaf 2026-01-29 19:18:47 +01:00
commit 96b5d1a299
8 changed files with 170 additions and 48 deletions

View file

@ -0,0 +1,12 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_nonuniform_qualifier : enable
layout(location = 0) rayPayloadInEXT vec3 hitValue;
hitAttributeEXT vec2 attribs;
void main()
{
const vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y);
hitValue = barycentricCoords;
}

View file

@ -5,9 +5,12 @@ using namespace Crafter;
import std; import std;
typedef VulkanShader<"raygen.spv", "main", VK_SHADER_STAGE_RAYGEN_BIT_KHR, 2, {{{VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0}, {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1}}}> Raygenspv; typedef VulkanShader<"raygen.spv", "main", VK_SHADER_STAGE_RAYGEN_BIT_KHR, 2, {{{VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0}, {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1}}}> Raygenspv;
typedef VulkanShader<"closesthit.spv", "main", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0, {{}}> Closesthitspv;
typedef VulkanShader<"miss.spv", "main", VK_SHADER_STAGE_MISS_BIT_KHR, 0, {{}}> Misspv;
int main() { int main() {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
/* /*
This sets up all necessary things and creates the vulkan device. This sets up all necessary things and creates the vulkan device.
This must be called before any vulkan related things. This must be called before any vulkan related things.
@ -15,9 +18,11 @@ int main() {
*/ */
VulkanDevice::CreateDevice(); VulkanDevice::CreateDevice();
Raygenspv::CreateShader(); Raygenspv::CreateShader();
DescriptorLayoutVulkan<Raygenspv>::Init(); Closesthitspv::CreateShader();
PipelineRTVulkan<Raygenspv, Raygenspv>::Init(); Misspv::CreateShader();
DescriptorPool<1, Raygenspv> pool; DescriptorLayoutVulkan<Raygenspv, Closesthitspv, Misspv>::Init();
PipelineRTVulkan<Raygenspv, Closesthitspv, Misspv, Raygenspv, Closesthitspv, Misspv>::Init();
DescriptorPool<1, Raygenspv, Closesthitspv, Misspv> pool;
pool.setsCount = 1; pool.setsCount = 1;
pool.BuildPool(0); pool.BuildPool(0);
@ -30,8 +35,8 @@ int main() {
VkCommandBuffer cmd = window.StartInit(); VkCommandBuffer cmd = window.StartInit();
Mesh triangleMesh; Mesh triangleMesh;
std::array<Vertex, 3> verts {{{-0.1, 0, 0}, {0, 0.1, 0}, {0.1, 0, 0}}}; std::array<Vertex, 3> verts {{{-150, -150, 100}, {0, 150, 100}, {150, -150, 100}}};
std::array<std::uint32_t, 3> index {{0,1,2}}; std::array<std::uint32_t, 3> index {{2,1,0}};
triangleMesh.Build(verts, index, cmd); triangleMesh.Build(verts, index, cmd);
RenderingElement3DVulkan::elements.emplace_back(triangleMesh); RenderingElement3DVulkan::elements.emplace_back(triangleMesh);
RenderingElement3DVulkan::BuildTLAS(cmd); RenderingElement3DVulkan::BuildTLAS(cmd);
@ -41,8 +46,6 @@ int main() {
.imageLayout = VK_IMAGE_LAYOUT_GENERAL .imageLayout = VK_IMAGE_LAYOUT_GENERAL
}; };
std::cout << pool.sets.size() << std::endl;
VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorSetAccelerationStructure { VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorSetAccelerationStructure {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
.accelerationStructureCount = 1, .accelerationStructureCount = 1,
@ -55,14 +58,15 @@ int main() {
.pNext = &writeDescriptorSetAccelerationStructure, .pNext = &writeDescriptorSetAccelerationStructure,
.dstSet = pool.sets[0], .dstSet = pool.sets[0],
.dstBinding = 0, .dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1, .descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, .descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
.pBufferInfo = &RenderingElement3DVulkan::tlasBuffer.descriptor
}, },
{ {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = pool.sets[0], .dstSet = pool.sets[0],
.dstBinding = 1, .dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1, .descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.pImageInfo = &imageInfo .pImageInfo = &imageInfo
@ -77,9 +81,18 @@ int main() {
*/ */
window.FinishInit(); window.FinishInit();
window.SetPipelineRT<Raygenspv, Raygenspv>(); window.SetPipelineRT<Raygenspv, Closesthitspv, Misspv, Raygenspv, Closesthitspv, Misspv>();
window.descriptorsRt = pool.sets; window.descriptorsRt = pool.sets;
window.Render(); window.Render();
window.Render();
window.Render();
window.Render();
// window.Render();
// window.Render();
// window.Render();
// window.Render();
// window.Render();
// window.Render();
window.StartSync(); window.StartSync();
} }

View file

@ -0,0 +1,9 @@
#version 460
#extension GL_EXT_ray_tracing : enable
layout(location = 0) rayPayloadInEXT vec3 hitValue;
void main()
{
hitValue = vec3(1, 1, 1);
}

View file

@ -15,6 +15,16 @@
"path":"raygen.glsl", "path":"raygen.glsl",
"type": 6, "type": 6,
"entrypoint":"main" "entrypoint":"main"
},
{
"path":"closesthit.glsl",
"type": 9,
"entrypoint":"main"
},
{
"path":"miss.glsl",
"type": 10,
"entrypoint":"main"
} }
] ]
} }

View file

@ -3,10 +3,45 @@
#extension GL_EXT_shader_image_load_formatted : enable #extension GL_EXT_shader_image_load_formatted : enable
layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS;
layout(binding = 1, set = 0) uniform image2D image; layout(binding = 1, set = 0, rgba32f) uniform image2D image;
layout(location = 0) rayPayloadEXT vec3 hitValue; layout(location = 0) rayPayloadEXT vec3 hitValue;
void main() { void main()
imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(1,1,1, 0.0)); {
// Pixel coordinates
uvec2 pixel = gl_LaunchIDEXT.xy;
uvec2 resolution = gl_LaunchSizeEXT.xy;
// Normalized coordinates in range [-1, 1]
vec2 uv = (vec2(pixel) + 0.5) / vec2(resolution);
vec2 ndc = uv * 2.0 - 1.0;
// Camera parameters
vec3 origin = vec3(0.0, 0.0, -300.0);
float aspect = float(resolution.x) / float(resolution.y);
float fov = radians(60.0);
float tanHalfFov = tan(fov * 0.5);
// Simple pinhole camera facing +Z
vec3 direction = normalize(vec3(
ndc.x * aspect * tanHalfFov,
-ndc.y * tanHalfFov,
1.0
));
traceRayEXT(
topLevelAS,
gl_RayFlagsNoneEXT,
0xff,
0, 0, 0,
origin,
0.001,
direction,
10000.0,
0
);
imageStore(image, ivec2(pixel), vec4(hitValue, 1.0));
} }

View file

@ -44,7 +44,10 @@ RenderingElement3DVulkan::RenderingElement3DVulkan(Mesh& mesh) {
instance = { instance = {
.transform = identity, .transform = identity,
.instanceCustomIndex = 0,
.mask = 0xFF, .mask = 0xFF,
.instanceShaderBindingTableRecordOffset = 0,
.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR | VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR,
.accelerationStructureReference = blasDeviceAddr .accelerationStructureReference = blasDeviceAddr
}; };
} }
@ -56,6 +59,8 @@ void RenderingElement3DVulkan::BuildTLAS(VkCommandBuffer cmd) {
instanceBuffer.value[i] = elements[i].instance; instanceBuffer.value[i] = elements[i].instance;
} }
instanceBuffer.FlushDevice(cmd, VK_ACCESS_MEMORY_READ_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
VkAccelerationStructureGeometryInstancesDataKHR instancesData = VkAccelerationStructureGeometryInstancesDataKHR { VkAccelerationStructureGeometryInstancesDataKHR instancesData = VkAccelerationStructureGeometryInstancesDataKHR {
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR, .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR,
.arrayOfPointers = VK_FALSE, .arrayOfPointers = VK_FALSE,

View file

@ -30,7 +30,7 @@ import :VulkanBuffer;
import :Types; import :Types;
export namespace Crafter { export namespace Crafter {
template <typename Raygen, typename... Shaders> template <typename Raygen, typename ClosestHit, typename Miss, typename... Shaders>
class PipelineRTVulkan { class PipelineRTVulkan {
public: public:
inline static VkPipeline pipeline; inline static VkPipeline pipeline;
@ -51,7 +51,7 @@ export namespace Crafter {
VulkanDevice::CheckVkResult(vkCreatePipelineLayout(VulkanDevice::device, &pipelineLayoutInfo, nullptr, &pipelineLayout)); VulkanDevice::CheckVkResult(vkCreatePipelineLayout(VulkanDevice::device, &pipelineLayoutInfo, nullptr, &pipelineLayout));
std::array<VkPipelineShaderStageCreateInfo, 1> shaderStages; std::array<VkPipelineShaderStageCreateInfo, 3> shaderStages;
shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[0].stage = Raygen::_stage; shaderStages[0].stage = Raygen::_stage;
@ -61,20 +61,56 @@ export namespace Crafter {
shaderStages[0].pSpecializationInfo = nullptr; shaderStages[0].pSpecializationInfo = nullptr;
shaderStages[0].pNext = nullptr; shaderStages[0].pNext = nullptr;
VkRayTracingShaderGroupCreateInfoKHR group { shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[1].stage = Miss::_stage;
shaderStages[1].module = Miss::shader;
shaderStages[1].pName = Miss::_entrypoint.value;
shaderStages[1].flags = 0;
shaderStages[1].pSpecializationInfo = nullptr;
shaderStages[1].pNext = nullptr;
shaderStages[2].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[2].stage = ClosestHit::_stage;
shaderStages[2].module = ClosestHit::shader;
shaderStages[2].pName = ClosestHit::_entrypoint.value;
shaderStages[2].flags = 0;
shaderStages[2].pSpecializationInfo = nullptr;
shaderStages[2].pNext = nullptr;
std::array<VkRayTracingShaderGroupCreateInfoKHR, 3> groups {{
{
.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, .sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR,
.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR,
.generalShader = 0, .generalShader = 0,
.closestHitShader = VK_SHADER_UNUSED_KHR, .closestHitShader = VK_SHADER_UNUSED_KHR,
.anyHitShader = VK_SHADER_UNUSED_KHR, .anyHitShader = VK_SHADER_UNUSED_KHR,
.intersectionShader = VK_SHADER_UNUSED_KHR .intersectionShader = VK_SHADER_UNUSED_KHR
}; },
{
.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR,
.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR,
.generalShader = 1,
.closestHitShader = VK_SHADER_UNUSED_KHR,
.anyHitShader = VK_SHADER_UNUSED_KHR,
.intersectionShader = VK_SHADER_UNUSED_KHR
},
{
.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR,
.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR,
.generalShader = VK_SHADER_UNUSED_KHR,
.closestHitShader = 2,
.anyHitShader = VK_SHADER_UNUSED_KHR,
.intersectionShader = VK_SHADER_UNUSED_KHR
}
}};
VkRayTracingPipelineCreateInfoKHR rtPipelineInfo{ VkRayTracingPipelineCreateInfoKHR rtPipelineInfo{
.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR, .sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR,
.stageCount = static_cast<std::uint32_t>(shaderStages.size()), .stageCount = static_cast<std::uint32_t>(shaderStages.size()),
.pStages = shaderStages.data(), .pStages = shaderStages.data(),
.groupCount = static_cast<std::uint32_t>(1), .groupCount = static_cast<std::uint32_t>(groups.size()),
.pGroups = &group, .pGroups = groups.data(),
.maxPipelineRayRecursionDepth = 1, .maxPipelineRayRecursionDepth = 1,
.layout = pipelineLayout .layout = pipelineLayout
}; };
@ -110,13 +146,15 @@ export namespace Crafter {
raygenRegion.stride = raygenSize; raygenRegion.stride = raygenSize;
raygenRegion.size = raygenSize; raygenRegion.size = raygenSize;
missRegion.deviceAddress = 0; std::memcpy(sbtBuffer.value + missOffset, shaderHandles.data() + 1 * handleSize, handleSize);
missRegion.stride = 0; missRegion.deviceAddress = sbtBuffer.address + missOffset;
missRegion.size = 0; missRegion.stride = missSize;
missRegion.size = missSize;
hitRegion.deviceAddress = 0; std::memcpy(sbtBuffer.value + hitOffset, shaderHandles.data() + 2 * handleSize, handleSize);
hitRegion.stride = 0; hitRegion.deviceAddress = sbtBuffer.address + hitOffset;
hitRegion.size = 0; hitRegion.stride = hitSize;
hitRegion.size = hitSize;
callableRegion.deviceAddress = 0; callableRegion.deviceAddress = 0;
callableRegion.stride = 0; callableRegion.stride = 0;

View file

@ -311,14 +311,14 @@ export namespace Crafter {
VkCommandBuffer StartInit(); VkCommandBuffer StartInit();
void FinishInit(); void FinishInit();
template <typename Raygen, typename... Shaders> template <typename Raygen, typename Closesthit, typename Miss, typename... Shaders>
void SetPipelineRT() { void SetPipelineRT() {
rtPipeline = PipelineRTVulkan<Raygen, Shaders...>::pipeline; rtPipeline = PipelineRTVulkan<Raygen, Closesthit, Miss, Shaders...>::pipeline;
rtPipelineLayout = PipelineRTVulkan<Raygen, Shaders...>::pipelineLayout; rtPipelineLayout = PipelineRTVulkan<Raygen, Closesthit, Miss, Shaders...>::pipelineLayout;
raygenRegion = PipelineRTVulkan<Raygen, Shaders...>::raygenRegion; raygenRegion = PipelineRTVulkan<Raygen, Closesthit, Miss, Shaders...>::raygenRegion;
missRegion = PipelineRTVulkan<Raygen, Shaders...>::missRegion; missRegion = PipelineRTVulkan<Raygen, Closesthit, Miss, Shaders...>::missRegion;
hitRegion = PipelineRTVulkan<Raygen, Shaders...>::hitRegion; hitRegion = PipelineRTVulkan<Raygen, Closesthit, Miss, Shaders...>::hitRegion;
callableRegion = PipelineRTVulkan<Raygen, Shaders...>::callableRegion; callableRegion = PipelineRTVulkan<Raygen, Closesthit, Miss, Shaders...>::callableRegion;
} }
inline static wl_compositor* compositor = nullptr; inline static wl_compositor* compositor = nullptr;
static void wl_surface_frame_done(void *data, wl_callback *cb, uint32_t time); static void wl_surface_frame_done(void *data, wl_callback *cb, uint32_t time);