blob: 467571339481e07c20b4dfef3d22e2b53b438598 [file]
/* Copyright (c) 2024-2026 The Khronos Group Inc.
* Copyright (c) 2024-2026 Valve Corporation
* Copyright (c) 2024-2026 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../framework/layer_validation_tests.h"
#include "../framework/descriptor_helper.h"
#include "../framework/ray_tracing_objects.h"
class NegativeGpuAVRayHitObject : public GpuAVRayHitObjectTest {};
TEST_F(NegativeGpuAVRayHitObject, NegativeTmin) {
TEST_DESCRIPTION("hitObjectTraceRayEXT with negative tmin");
RETURN_IF_SKIP(InitHitObjectTest());
vkt::rt::Pipeline pipeline(*this, m_device);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { float tmin; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
hitObjectTraceRayEXT(hObj, tlas, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0,
vec3(0,0,0), params.tmin, vec3(0,0,1), 100.0, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<float*>(uniform_buffer.Memory().Map());
ptr[0] = -1.0f; // negative tmin
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11879");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, TmaxLessThanTmin) {
TEST_DESCRIPTION("hitObjectTraceRayEXT with tmax < tmin");
RETURN_IF_SKIP(InitHitObjectTest());
vkt::rt::Pipeline pipeline(*this, m_device);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { float tmin; float tmax; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
hitObjectTraceRayEXT(hObj, tlas, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0,
vec3(0,0,0), params.tmin, vec3(0,0,1), params.tmax, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<float*>(uniform_buffer.Memory().Map());
ptr[0] = 10.0f; // tmin
ptr[1] = 5.0f; // tmax < tmin
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11880");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, OriginNaN) {
TEST_DESCRIPTION("hitObjectTraceRayEXT with NaN in origin");
RETURN_IF_SKIP(InitHitObjectTest());
vkt::rt::Pipeline pipeline(*this, m_device);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { float x; float y; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
float nan_val = fract(params.x / params.y); // 1.0/0.0 then fract = NaN
hitObjectTraceRayEXT(hObj, tlas, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0,
vec3(nan_val, 0, 0), 0.1, vec3(0,0,1), 100.0, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<float*>(uniform_buffer.Memory().Map());
ptr[0] = 1.0f;
ptr[1] = 0.0f; // division by zero -> inf, fract(inf) = NaN
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11881");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, OriginNonFinite) {
TEST_DESCRIPTION("hitObjectTraceRayEXT with infinity in origin");
RETURN_IF_SKIP(InitHitObjectTest());
vkt::rt::Pipeline pipeline(*this, m_device);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { float x; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
float inf_val = 1.0 / params.x; // 1.0/0.0 = +infinity
hitObjectTraceRayEXT(hObj, tlas, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0,
vec3(inf_val, 0, 0), 0.1, vec3(0,0,1), 100.0, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<float*>(uniform_buffer.Memory().Map());
ptr[0] = 0.0f; // causes division by zero -> +infinity
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11878");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, BothSkipFlags) {
TEST_DESCRIPTION("hitObjectTraceRayEXT with both SkipTriangles and SkipAABBs flags");
RETURN_IF_SKIP(InitHitObjectTest());
vkt::rt::Pipeline pipeline(*this, m_device);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
#extension GL_EXT_ray_flags_primitive_culling : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { uint flags; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
hitObjectTraceRayEXT(hObj, tlas, params.flags, 0xff, 0, 0, 0,
vec3(0,0,0), 0.1, vec3(0,0,1), 100.0, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<uint32_t*>(uniform_buffer.Memory().Map());
ptr[0] = 0x100 | 0x200; // SkipTrianglesKHR | SkipAABBsKHR
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11883");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, OpaqueFlags) {
TEST_DESCRIPTION("hitObjectTraceRayEXT with conflicting opaque flags");
RETURN_IF_SKIP(InitHitObjectTest());
vkt::rt::Pipeline pipeline(*this, m_device);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { uint flags; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
hitObjectTraceRayEXT(hObj, tlas, params.flags, 0xff, 0, 0, 0,
vec3(0,0,0), 0.1, vec3(0,0,1), 100.0, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<uint32_t*>(uniform_buffer.Memory().Map());
ptr[0] = 0x1 | 0x2; // OpaqueKHR | NoOpaqueKHR
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11885");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, SkipAndCullFlags) {
TEST_DESCRIPTION("hitObjectTraceRayEXT with SkipTriangles and CullBackFacing flags");
RETURN_IF_SKIP(InitHitObjectTest());
vkt::rt::Pipeline pipeline(*this, m_device);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
#extension GL_EXT_ray_flags_primitive_culling : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { uint flags; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
hitObjectTraceRayEXT(hObj, tlas, params.flags, 0xff, 0, 0, 0,
vec3(0,0,0), 0.1, vec3(0,0,1), 100.0, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<uint32_t*>(uniform_buffer.Memory().Map());
ptr[0] = 0x100 | 0x10; // SkipTrianglesKHR | CullBackFacingTrianglesKHR
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11884");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, SkipTrianglesWithPipelineSkipAABBs) {
TEST_DESCRIPTION("hitObjectTraceRayEXT with SkipTriangles flag and pipeline SKIP_AABBS");
RETURN_IF_SKIP(InitHitObjectTest());
vkt::rt::Pipeline pipeline(*this, m_device);
pipeline.AddCreateInfoFlags(VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
#extension GL_EXT_ray_flags_primitive_culling : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { uint flags; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
hitObjectTraceRayEXT(hObj, tlas, params.flags, 0xff, 0, 0, 0,
vec3(0,0,0), 0.1, vec3(0,0,1), 100.0, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<uint32_t*>(uniform_buffer.Memory().Map());
ptr[0] = 0x100; // SkipTrianglesKHR
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11886");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, SkipAABBsWithPipelineSkipTriangles) {
TEST_DESCRIPTION("hitObjectTraceRayEXT with SkipAABBs flag and pipeline SKIP_TRIANGLES");
RETURN_IF_SKIP(InitHitObjectTest());
vkt::rt::Pipeline pipeline(*this, m_device);
pipeline.AddCreateInfoFlags(VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
#extension GL_EXT_ray_flags_primitive_culling : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { uint flags; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
hitObjectTraceRayEXT(hObj, tlas, params.flags, 0xff, 0, 0, 0,
vec3(0,0,0), 0.1, vec3(0,0,1), 100.0, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<uint32_t*>(uniform_buffer.Memory().Map());
ptr[0] = 0x200; // SkipAABBsKHR
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11887");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, MotionTimeOutOfRange) {
TEST_DESCRIPTION("hitObjectTraceRayMotionEXT with time outside [0.0, 1.0]");
RETURN_IF_SKIP(InitHitObjectMotionTest());
vkt::rt::Pipeline pipeline(*this, m_device);
pipeline.AddCreateInfoFlags(VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
#extension GL_NV_ray_tracing_motion_blur : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { float time; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
hitObjectTraceRayMotionEXT(hObj, tlas, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0,
vec3(0,0,0), 0.1, vec3(0,0,1), 100.0, params.time, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<float*>(uniform_buffer.Memory().Map());
ptr[0] = 1.5f; // time > 1.0, invalid
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11882");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, SBTIndexExceedsLimit) {
TEST_DESCRIPTION("hitObjectSetShaderBindingTableRecordIndexEXT with index exceeding limit");
AddRequiredExtensions(VK_KHR_RAY_QUERY_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::rayQuery);
RETURN_IF_SKIP(InitHitObjectTest());
// Get the max SBT index from device properties
VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT reorder_props = vku::InitStructHelper();
VkPhysicalDeviceProperties2 props2 = vku::InitStructHelper(&reorder_props);
vk::GetPhysicalDeviceProperties2(Gpu(), &props2);
if (reorder_props.rayTracingInvocationReorderReorderingHint == VK_RAY_TRACING_INVOCATION_REORDER_MODE_NONE_EXT) {
GTEST_SKIP() << "Ray tracing invocation reorder not supported";
}
if (reorder_props.maxShaderBindingTableRecordIndex == std::numeric_limits<uint32_t>::max()) {
GTEST_SKIP() << "Cannot test exceeding limit when maxShaderBindingTableRecordIndex is UINT32_MAX";
}
vkt::rt::Pipeline pipeline(*this, m_device);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_ray_query : require
#extension GL_EXT_shader_invocation_reorder : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { uint sbt_index; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
rayQueryEXT rq;
rayQueryInitializeEXT(rq, tlas, gl_RayFlagsOpaqueEXT, 0xff, vec3(0), 0.1, vec3(0,0,1), 100.0);
hitObjectRecordFromQueryEXT(hObj, rq, 0, 0);
hitObjectSetShaderBindingTableRecordIndexEXT(hObj, params.sbt_index);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<uint32_t*>(uniform_buffer.Memory().Map());
ptr[0] = reorder_props.maxShaderBindingTableRecordIndex + 1; // Exceed the limit
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-maxShaderBindingTableRecordIndex-11888");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, TraceReorderExecuteNegativeTmin) {
TEST_DESCRIPTION("hitObjectTraceReorderExecuteEXT with negative tmin");
RETURN_IF_SKIP(InitHitObjectTest());
vkt::rt::Pipeline pipeline(*this, m_device);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { float tmin; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
hitObjectTraceReorderExecuteEXT(hObj, tlas, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0,
vec3(0,0,0), params.tmin, vec3(0,0,1), 100.0, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<float*>(uniform_buffer.Memory().Map());
ptr[0] = -1.0f; // negative tmin
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11879");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, TraceMotionReorderExecuteNegativeTmin) {
TEST_DESCRIPTION("hitObjectTraceMotionReorderExecuteEXT with negative tmin");
RETURN_IF_SKIP(InitHitObjectMotionTest());
vkt::rt::Pipeline pipeline(*this, m_device);
pipeline.AddCreateInfoFlags(VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
#extension GL_NV_ray_tracing_motion_blur : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { float tmin; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
hitObjectTraceMotionReorderExecuteEXT(hObj, tlas, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0,
vec3(0,0,0), params.tmin, vec3(0,0,1), 100.0, 0.5, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<float*>(uniform_buffer.Memory().Map());
ptr[0] = -1.0f; // negative tmin
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11879");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeGpuAVRayHitObject, TraceMotionReorderExecuteTimeOutOfRange) {
TEST_DESCRIPTION("hitObjectTraceMotionReorderExecuteEXT with time outside [0.0, 1.0]");
RETURN_IF_SKIP(InitHitObjectMotionTest());
vkt::rt::Pipeline pipeline(*this, m_device);
pipeline.AddCreateInfoFlags(VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV);
const char* ray_gen = R"glsl(
#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_shader_invocation_reorder : require
#extension GL_NV_ray_tracing_motion_blur : require
layout(binding = 0, set = 0) uniform accelerationStructureEXT tlas;
layout(binding = 1, set = 0) uniform Params { float time; } params;
layout(location = 0) rayPayloadEXT vec3 payload;
layout(location = 0) hitObjectAttributeEXT vec2 attr;
void main() {
hitObjectEXT hObj;
hitObjectTraceMotionReorderExecuteEXT(hObj, tlas, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0,
vec3(0,0,0), 0.1, vec3(0,0,1), 100.0, params.time, 0);
}
)glsl";
pipeline.SetGlslRayGenShader(ray_gen);
pipeline.AddGlslMissShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddGlslClosestHitShader(kRayTracingPayloadMinimalGlsl);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
pipeline.CreateDescriptorSet();
vkt::as::BuildGeometryInfoKHR tlas(vkt::as::blueprint::BuildOnDeviceTopLevel(*m_device, *m_default_queue, m_command_buffer));
pipeline.GetDescriptorSet().WriteDescriptorAccelStruct(0, 1, &tlas.GetDstAS()->handle());
vkt::Buffer uniform_buffer(*m_device, 4096, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, kHostVisibleMemProps);
auto* ptr = static_cast<float*>(uniform_buffer.Memory().Map());
ptr[0] = 1.5f; // time > 1.0, invalid
pipeline.GetDescriptorSet().WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE);
pipeline.GetDescriptorSet().UpdateDescriptorSets();
pipeline.Build();
m_command_buffer.Begin();
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.GetPipelineLayout(), 0, 1,
&pipeline.GetDescriptorSet().set_, 0, nullptr);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
vkt::rt::TraceRaysSbt trace_rays_sbt = pipeline.GetTraceRaysSbt();
vk::CmdTraceRaysKHR(m_command_buffer, &trace_rays_sbt.ray_gen_sbt, &trace_rays_sbt.miss_sbt, &trace_rays_sbt.hit_sbt,
&trace_rays_sbt.callable_sbt, 1, 1, 1);
m_command_buffer.End();
m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-OpHitObjectTraceRayEXT-11882");
m_default_queue->Submit(m_command_buffer);
m_device->Wait();
m_errorMonitor->VerifyFound();
}