| /* |
| * Copyright (c) 2015-2023 The Khronos Group Inc. |
| * Copyright (c) 2015-2023 Valve Corporation |
| * Copyright (c) 2015-2023 LunarG, Inc. |
| * Copyright (c) 2015-2023 Google, Inc. |
| * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. |
| * |
| * 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 |
| */ |
| |
| #include "../framework/layer_validation_tests.h" |
| #include "../framework/ray_tracing_objects.h" |
| #include "../framework/ray_tracing_nv.h" |
| #include "../layers/utils/vk_layer_utils.h" |
| |
| void RayTracingTest::OOBRayTracingShadersTestBody(bool gpu_assisted) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_NV_RAY_TRACING_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); |
| AddOptionalExtensions(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); |
| VkValidationFeatureEnableEXT validation_feature_enables[] = {VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT}; |
| VkValidationFeatureDisableEXT validation_feature_disables[] = { |
| VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT, VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT, |
| VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT, VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT}; |
| VkValidationFeaturesEXT validation_features = {}; |
| validation_features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT; |
| validation_features.enabledValidationFeatureCount = 1; |
| validation_features.pEnabledValidationFeatures = validation_feature_enables; |
| validation_features.disabledValidationFeatureCount = 4; |
| validation_features.pDisabledValidationFeatures = validation_feature_disables; |
| RETURN_IF_SKIP(InitFramework(gpu_assisted ? &validation_features : nullptr)); |
| bool descriptor_indexing = IsExtensionsEnabled(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); |
| |
| if (gpu_assisted && IsPlatformMockICD()) { |
| GTEST_SKIP() << "GPU-AV can't run on MockICD"; |
| } |
| |
| VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(); |
| VkPhysicalDeviceDescriptorIndexingFeaturesEXT indexing_features = vku::InitStructHelper(); |
| if (descriptor_indexing) { |
| features2 = GetPhysicalDeviceFeatures2(indexing_features); |
| if (!indexing_features.runtimeDescriptorArray || !indexing_features.descriptorBindingPartiallyBound || |
| !indexing_features.descriptorBindingSampledImageUpdateAfterBind || |
| !indexing_features.descriptorBindingVariableDescriptorCount) { |
| printf("Not all descriptor indexing features supported, skipping descriptor indexing tests\n"); |
| descriptor_indexing = false; |
| } |
| } |
| |
| VkCommandPoolCreateFlags pool_flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; |
| RETURN_IF_SKIP(InitState(nullptr, &features2, pool_flags)); |
| |
| PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = |
| (PFN_vkGetPhysicalDeviceProperties2KHR)vk::GetInstanceProcAddr(instance(), "vkGetPhysicalDeviceProperties2KHR"); |
| ASSERT_TRUE(vkGetPhysicalDeviceProperties2KHR != nullptr); |
| |
| VkPhysicalDeviceRayTracingPropertiesNV ray_tracing_properties = vku::InitStructHelper(); |
| VkPhysicalDeviceProperties2KHR properties2 = vku::InitStructHelper(&ray_tracing_properties); |
| vkGetPhysicalDeviceProperties2KHR(gpu(), &properties2); |
| if (ray_tracing_properties.maxTriangleCount == 0) { |
| GTEST_SKIP() << "Did not find required ray tracing properties"; |
| } |
| |
| VkQueue ray_tracing_queue = m_default_queue; |
| uint32_t ray_tracing_queue_family_index = 0; |
| |
| // If supported, run on the compute only queue. |
| const std::optional<uint32_t> compute_only_queue_family_index = |
| m_device->QueueFamilyMatching(VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT); |
| if (compute_only_queue_family_index) { |
| const auto &compute_only_queues = m_device->queue_family_queues(compute_only_queue_family_index.value()); |
| if (!compute_only_queues.empty()) { |
| ray_tracing_queue = compute_only_queues[0]->handle(); |
| ray_tracing_queue_family_index = compute_only_queue_family_index.value(); |
| } |
| } |
| |
| vkt::CommandPool ray_tracing_command_pool(*m_device, ray_tracing_queue_family_index, |
| VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); |
| vkt::CommandBuffer ray_tracing_command_buffer(m_device, &ray_tracing_command_pool); |
| |
| constexpr std::array<VkAabbPositionsKHR, 1> aabbs = {{{-1.0f, -1.0f, -1.0f, +1.0f, +1.0f, +1.0f}}}; |
| |
| struct VkGeometryInstanceNV { |
| float transform[12]; |
| uint32_t instanceCustomIndex : 24; |
| uint32_t mask : 8; |
| uint32_t instanceOffset : 24; |
| uint32_t flags : 8; |
| uint64_t accelerationStructureHandle; |
| }; |
| |
| const VkDeviceSize aabb_buffer_size = sizeof(VkAabbPositionsKHR) * aabbs.size(); |
| vkt::Buffer aabb_buffer; |
| aabb_buffer.init(*m_device, aabb_buffer_size, VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, nullptr, |
| {ray_tracing_queue_family_index}); |
| |
| uint8_t *mapped_aabb_buffer_data = (uint8_t *)aabb_buffer.memory().map(); |
| std::memcpy(mapped_aabb_buffer_data, (uint8_t *)aabbs.data(), static_cast<std::size_t>(aabb_buffer_size)); |
| aabb_buffer.memory().unmap(); |
| |
| VkGeometryNV geometry = {}; |
| geometry.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV; |
| geometry.geometryType = VK_GEOMETRY_TYPE_AABBS_NV; |
| geometry.geometry.triangles = {}; |
| geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV; |
| geometry.geometry.aabbs = {}; |
| geometry.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV; |
| geometry.geometry.aabbs.aabbData = aabb_buffer.handle(); |
| geometry.geometry.aabbs.numAABBs = static_cast<uint32_t>(aabbs.size()); |
| geometry.geometry.aabbs.offset = 0; |
| geometry.geometry.aabbs.stride = static_cast<VkDeviceSize>(sizeof(VkAabbPositionsKHR)); |
| geometry.flags = 0; |
| |
| VkAccelerationStructureInfoNV bot_level_as_info = vku::InitStructHelper(); |
| bot_level_as_info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV; |
| bot_level_as_info.instanceCount = 0; |
| bot_level_as_info.geometryCount = 1; |
| bot_level_as_info.pGeometries = &geometry; |
| |
| VkAccelerationStructureCreateInfoNV bot_level_as_create_info = vku::InitStructHelper(); |
| bot_level_as_create_info.info = bot_level_as_info; |
| |
| vkt::AccelerationStructure bot_level_as(*m_device, bot_level_as_create_info); |
| |
| const std::array instances = { |
| VkGeometryInstanceNV{ |
| { |
| // clang-format off |
| 1.0f, 0.0f, 0.0f, 0.0f, |
| 0.0f, 1.0f, 0.0f, 0.0f, |
| 0.0f, 0.0f, 1.0f, 0.0f, |
| // clang-format on |
| }, |
| 0, |
| 0xFF, |
| 0, |
| VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV, |
| bot_level_as.opaque_handle(), |
| }, |
| }; |
| |
| VkDeviceSize instance_buffer_size = sizeof(instances[0]) * instances.size(); |
| vkt::Buffer instance_buffer; |
| instance_buffer.init(*m_device, instance_buffer_size, VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, nullptr, |
| {ray_tracing_queue_family_index}); |
| |
| uint8_t *mapped_instance_buffer_data = (uint8_t *)instance_buffer.memory().map(); |
| std::memcpy(mapped_instance_buffer_data, (uint8_t *)instances.data(), static_cast<std::size_t>(instance_buffer_size)); |
| instance_buffer.memory().unmap(); |
| |
| VkAccelerationStructureInfoNV top_level_as_info = vku::InitStructHelper(); |
| top_level_as_info.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV; |
| top_level_as_info.instanceCount = 1; |
| top_level_as_info.geometryCount = 0; |
| |
| VkAccelerationStructureCreateInfoNV top_level_as_create_info = vku::InitStructHelper(); |
| top_level_as_create_info.info = top_level_as_info; |
| |
| vkt::AccelerationStructure top_level_as(*m_device, top_level_as_create_info); |
| |
| VkDeviceSize scratch_buffer_size = std::max(bot_level_as.build_scratch_memory_requirements().memoryRequirements.size, |
| top_level_as.build_scratch_memory_requirements().memoryRequirements.size); |
| vkt::Buffer scratch_buffer(*m_device, scratch_buffer_size, VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, |
| VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); |
| |
| ray_tracing_command_buffer.begin(); |
| |
| // Build bot level acceleration structure |
| vk::CmdBuildAccelerationStructureNV(ray_tracing_command_buffer.handle(), &bot_level_as.info(), VK_NULL_HANDLE, 0, VK_FALSE, |
| bot_level_as.handle(), VK_NULL_HANDLE, scratch_buffer.handle(), 0); |
| |
| // Barrier to prevent using scratch buffer for top level build before bottom level build finishes |
| VkMemoryBarrier memory_barrier = vku::InitStructHelper(); |
| memory_barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV; |
| memory_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV; |
| vk::CmdPipelineBarrier(ray_tracing_command_buffer.handle(), VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, |
| VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 1, &memory_barrier, 0, nullptr, 0, nullptr); |
| |
| // Build top level acceleration structure |
| vk::CmdBuildAccelerationStructureNV(ray_tracing_command_buffer.handle(), &top_level_as.info(), instance_buffer.handle(), 0, |
| VK_FALSE, top_level_as.handle(), VK_NULL_HANDLE, scratch_buffer.handle(), 0); |
| |
| ray_tracing_command_buffer.end(); |
| |
| VkSubmitInfo submit_info = vku::InitStructHelper(); |
| submit_info.commandBufferCount = 1; |
| submit_info.pCommandBuffers = &ray_tracing_command_buffer.handle(); |
| vk::QueueSubmit(ray_tracing_queue, 1, &submit_info, VK_NULL_HANDLE); |
| vk::QueueWaitIdle(ray_tracing_queue); |
| |
| VkImageObj image(m_device); |
| image.Init(16, 16, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT); |
| VkImageView imageView = image.targetView(VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); |
| vkt::Sampler sampler(*m_device, SafeSaneSamplerCreateInfo()); |
| |
| VkDeviceSize storage_buffer_size = 1024; |
| vkt::Buffer storage_buffer; |
| storage_buffer.init(*m_device, storage_buffer_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, nullptr, |
| {ray_tracing_queue_family_index}); |
| |
| VkDeviceSize shader_binding_table_buffer_size = ray_tracing_properties.shaderGroupBaseAlignment * 4ull; |
| vkt::Buffer shader_binding_table_buffer; |
| shader_binding_table_buffer.init(*m_device, shader_binding_table_buffer_size, VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, nullptr, |
| {ray_tracing_queue_family_index}); |
| |
| // Setup descriptors! |
| const VkShaderStageFlags kAllRayTracingStages = VK_SHADER_STAGE_RAYGEN_BIT_NV | VK_SHADER_STAGE_ANY_HIT_BIT_NV | |
| VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV | VK_SHADER_STAGE_MISS_BIT_NV | |
| VK_SHADER_STAGE_INTERSECTION_BIT_NV | VK_SHADER_STAGE_CALLABLE_BIT_NV; |
| |
| void *layout_pnext = nullptr; |
| void *allocate_pnext = nullptr; |
| VkDescriptorPoolCreateFlags pool_create_flags = 0; |
| VkDescriptorSetLayoutCreateFlags layout_create_flags = 0; |
| VkDescriptorBindingFlagsEXT ds_binding_flags[3] = {}; |
| VkDescriptorSetLayoutBindingFlagsCreateInfoEXT layout_createinfo_binding_flags[1] = {}; |
| if (descriptor_indexing) { |
| ds_binding_flags[0] = 0; |
| ds_binding_flags[1] = 0; |
| ds_binding_flags[2] = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT; |
| |
| layout_createinfo_binding_flags[0] = vku::InitStructHelper(); |
| layout_createinfo_binding_flags[0].bindingCount = 3; |
| layout_createinfo_binding_flags[0].pBindingFlags = ds_binding_flags; |
| layout_create_flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; |
| pool_create_flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; |
| layout_pnext = layout_createinfo_binding_flags; |
| } |
| |
| // Prepare descriptors |
| OneOffDescriptorSet ds(m_device, |
| { |
| {0, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV, 1, kAllRayTracingStages, nullptr}, |
| {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, kAllRayTracingStages, nullptr}, |
| {2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6, kAllRayTracingStages, nullptr}, |
| }, |
| layout_create_flags, layout_pnext, pool_create_flags); |
| |
| VkDescriptorSetVariableDescriptorCountAllocateInfoEXT variable_count = |
| vku::InitStructHelper(); |
| uint32_t desc_counts; |
| if (descriptor_indexing) { |
| layout_create_flags = 0; |
| pool_create_flags = 0; |
| ds_binding_flags[2] = |
| VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT; |
| desc_counts = 6; // We'll reserve 8 spaces in the layout, but the descriptor will only use 6 |
| variable_count.descriptorSetCount = 1; |
| variable_count.pDescriptorCounts = &desc_counts; |
| allocate_pnext = &variable_count; |
| } |
| |
| OneOffDescriptorSet ds_variable(m_device, |
| { |
| {0, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV, 1, kAllRayTracingStages, nullptr}, |
| {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, kAllRayTracingStages, nullptr}, |
| {2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 8, kAllRayTracingStages, nullptr}, |
| }, |
| layout_create_flags, layout_pnext, pool_create_flags, allocate_pnext); |
| |
| VkAccelerationStructureNV top_level_as_handle = top_level_as.handle(); |
| VkWriteDescriptorSetAccelerationStructureNV write_descript_set_as = |
| vku::InitStructHelper(); |
| write_descript_set_as.accelerationStructureCount = 1; |
| write_descript_set_as.pAccelerationStructures = &top_level_as_handle; |
| |
| VkDescriptorBufferInfo descriptor_buffer_info = {}; |
| descriptor_buffer_info.buffer = storage_buffer.handle(); |
| descriptor_buffer_info.offset = 0; |
| descriptor_buffer_info.range = storage_buffer_size; |
| |
| VkDescriptorImageInfo descriptor_image_infos[6] = {}; |
| for (int i = 0; i < 6; i++) { |
| descriptor_image_infos[i] = {sampler.handle(), imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}; |
| } |
| |
| VkWriteDescriptorSet descriptor_writes[3] = {}; |
| descriptor_writes[0] = vku::InitStructHelper(&write_descript_set_as); |
| descriptor_writes[0].dstSet = ds.set_; |
| descriptor_writes[0].dstBinding = 0; |
| descriptor_writes[0].descriptorCount = 1; |
| descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV; |
| |
| descriptor_writes[1] = vku::InitStructHelper(); |
| descriptor_writes[1].dstSet = ds.set_; |
| descriptor_writes[1].dstBinding = 1; |
| descriptor_writes[1].descriptorCount = 1; |
| descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; |
| descriptor_writes[1].pBufferInfo = &descriptor_buffer_info; |
| |
| descriptor_writes[2] = vku::InitStructHelper(); |
| descriptor_writes[2].dstSet = ds.set_; |
| descriptor_writes[2].dstBinding = 2; |
| if (descriptor_indexing) { |
| descriptor_writes[2].descriptorCount = 5; // Intentionally don't write index 5 |
| } else { |
| descriptor_writes[2].descriptorCount = 6; |
| } |
| descriptor_writes[2].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; |
| descriptor_writes[2].pImageInfo = descriptor_image_infos; |
| vk::UpdateDescriptorSets(m_device->device(), 3, descriptor_writes, 0, NULL); |
| if (descriptor_indexing) { |
| descriptor_writes[0].dstSet = ds_variable.set_; |
| descriptor_writes[1].dstSet = ds_variable.set_; |
| descriptor_writes[2].dstSet = ds_variable.set_; |
| vk::UpdateDescriptorSets(m_device->device(), 3, descriptor_writes, 0, NULL); |
| } |
| |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&ds.layout_}); |
| const vkt::PipelineLayout pipeline_layout_variable(*m_device, {&ds_variable.layout_}); |
| |
| const auto SetImagesArrayLength = [](const std::string &shader_template, const std::string &length_str) { |
| const std::string to_replace = "IMAGES_ARRAY_LENGTH"; |
| |
| std::string result = shader_template; |
| auto position = result.find(to_replace); |
| assert(position != std::string::npos); |
| result.replace(position, to_replace.length(), length_str); |
| return result; |
| }; |
| |
| const std::string rgen_source_template = R"(#version 460 |
| #extension GL_EXT_nonuniform_qualifier : require |
| #extension GL_EXT_samplerless_texture_functions : require |
| #extension GL_NV_ray_tracing : require |
| |
| layout(set = 0, binding = 0) uniform accelerationStructureNV topLevelAS; |
| layout(set = 0, binding = 1, std430) buffer RayTracingSbo { |
| uint rgen_index; |
| uint ahit_index; |
| uint chit_index; |
| uint miss_index; |
| uint intr_index; |
| uint call_index; |
| |
| uint rgen_ran; |
| uint ahit_ran; |
| uint chit_ran; |
| uint miss_ran; |
| uint intr_ran; |
| uint call_ran; |
| |
| float result1; |
| float result2; |
| float result3; |
| } sbo; |
| layout(set = 0, binding = 2) uniform texture2D textures[IMAGES_ARRAY_LENGTH]; |
| |
| layout(location = 0) rayPayloadNV vec3 payload; |
| layout(location = 3) callableDataNV vec3 callableData; |
| |
| void main() { |
| sbo.rgen_ran = 1; |
| |
| executeCallableNV(0, 3); |
| sbo.result1 = callableData.x; |
| |
| vec3 origin = vec3(0.0f, 0.0f, -2.0f); |
| vec3 direction = vec3(0.0f, 0.0f, 1.0f); |
| |
| traceNV(topLevelAS, gl_RayFlagsNoneNV, 0xFF, 0, 1, 0, origin, 0.001, direction, 10000.0, 0); |
| sbo.result2 = payload.x; |
| |
| traceNV(topLevelAS, gl_RayFlagsNoneNV, 0xFF, 0, 1, 0, origin, 0.001, -direction, 10000.0, 0); |
| sbo.result3 = payload.x; |
| |
| if (sbo.rgen_index > 0) { |
| // OOB here: |
| sbo.result3 = texelFetch(textures[sbo.rgen_index], ivec2(0, 0), 0).x; |
| } |
| } |
| )"; |
| |
| const std::string rgen_source = SetImagesArrayLength(rgen_source_template, "6"); |
| const std::string rgen_source_runtime = SetImagesArrayLength(rgen_source_template, ""); |
| |
| const std::string ahit_source_template = R"(#version 460 |
| #extension GL_EXT_nonuniform_qualifier : require |
| #extension GL_EXT_samplerless_texture_functions : require |
| #extension GL_NV_ray_tracing : require |
| |
| layout(set = 0, binding = 1, std430) buffer StorageBuffer { |
| uint rgen_index; |
| uint ahit_index; |
| uint chit_index; |
| uint miss_index; |
| uint intr_index; |
| uint call_index; |
| |
| uint rgen_ran; |
| uint ahit_ran; |
| uint chit_ran; |
| uint miss_ran; |
| uint intr_ran; |
| uint call_ran; |
| |
| float result1; |
| float result2; |
| float result3; |
| } sbo; |
| layout(set = 0, binding = 2) uniform texture2D textures[IMAGES_ARRAY_LENGTH]; |
| |
| hitAttributeNV vec3 hitValue; |
| |
| layout(location = 0) rayPayloadInNV vec3 payload; |
| |
| void main() { |
| sbo.ahit_ran = 2; |
| |
| payload = vec3(0.1234f); |
| |
| if (sbo.ahit_index > 0) { |
| // OOB here: |
| payload.x = texelFetch(textures[sbo.ahit_index], ivec2(0, 0), 0).x; |
| } |
| } |
| )"; |
| const std::string ahit_source = SetImagesArrayLength(ahit_source_template, "6"); |
| const std::string ahit_source_runtime = SetImagesArrayLength(ahit_source_template, ""); |
| |
| const std::string chit_source_template = R"(#version 460 |
| #extension GL_EXT_nonuniform_qualifier : require |
| #extension GL_EXT_samplerless_texture_functions : require |
| #extension GL_NV_ray_tracing : require |
| |
| layout(set = 0, binding = 1, std430) buffer RayTracingSbo { |
| uint rgen_index; |
| uint ahit_index; |
| uint chit_index; |
| uint miss_index; |
| uint intr_index; |
| uint call_index; |
| |
| uint rgen_ran; |
| uint ahit_ran; |
| uint chit_ran; |
| uint miss_ran; |
| uint intr_ran; |
| uint call_ran; |
| |
| float result1; |
| float result2; |
| float result3; |
| } sbo; |
| layout(set = 0, binding = 2) uniform texture2D textures[IMAGES_ARRAY_LENGTH]; |
| |
| layout(location = 0) rayPayloadInNV vec3 payload; |
| |
| hitAttributeNV vec3 attribs; |
| |
| void main() { |
| sbo.chit_ran = 3; |
| |
| payload = attribs; |
| if (sbo.chit_index > 0) { |
| // OOB here: |
| payload.x = texelFetch(textures[sbo.chit_index], ivec2(0, 0), 0).x; |
| } |
| } |
| )"; |
| const std::string chit_source = SetImagesArrayLength(chit_source_template, "6"); |
| const std::string chit_source_runtime = SetImagesArrayLength(chit_source_template, ""); |
| |
| const std::string miss_source_template = R"(#version 460 |
| #extension GL_EXT_nonuniform_qualifier : enable |
| #extension GL_EXT_samplerless_texture_functions : require |
| #extension GL_NV_ray_tracing : require |
| |
| layout(set = 0, binding = 1, std430) buffer RayTracingSbo { |
| uint rgen_index; |
| uint ahit_index; |
| uint chit_index; |
| uint miss_index; |
| uint intr_index; |
| uint call_index; |
| |
| uint rgen_ran; |
| uint ahit_ran; |
| uint chit_ran; |
| uint miss_ran; |
| uint intr_ran; |
| uint call_ran; |
| |
| float result1; |
| float result2; |
| float result3; |
| } sbo; |
| layout(set = 0, binding = 2) uniform texture2D textures[IMAGES_ARRAY_LENGTH]; |
| |
| layout(location = 0) rayPayloadInNV vec3 payload; |
| |
| void main() { |
| sbo.miss_ran = 4; |
| |
| payload = vec3(1.0, 0.0, 0.0); |
| |
| if (sbo.miss_index > 0) { |
| // OOB here: |
| payload.x = texelFetch(textures[sbo.miss_index], ivec2(0, 0), 0).x; |
| } |
| } |
| )"; |
| const std::string miss_source = SetImagesArrayLength(miss_source_template, "6"); |
| const std::string miss_source_runtime = SetImagesArrayLength(miss_source_template, ""); |
| |
| const std::string intr_source_template = R"(#version 460 |
| #extension GL_EXT_nonuniform_qualifier : require |
| #extension GL_EXT_samplerless_texture_functions : require |
| #extension GL_NV_ray_tracing : require |
| |
| layout(set = 0, binding = 1, std430) buffer StorageBuffer { |
| uint rgen_index; |
| uint ahit_index; |
| uint chit_index; |
| uint miss_index; |
| uint intr_index; |
| uint call_index; |
| |
| uint rgen_ran; |
| uint ahit_ran; |
| uint chit_ran; |
| uint miss_ran; |
| uint intr_ran; |
| uint call_ran; |
| |
| float result1; |
| float result2; |
| float result3; |
| } sbo; |
| layout(set = 0, binding = 2) uniform texture2D textures[IMAGES_ARRAY_LENGTH]; |
| |
| hitAttributeNV vec3 hitValue; |
| |
| void main() { |
| sbo.intr_ran = 5; |
| |
| hitValue = vec3(0.0f, 0.5f, 0.0f); |
| |
| reportIntersectionNV(1.0f, 0); |
| |
| if (sbo.intr_index > 0) { |
| // OOB here: |
| hitValue.x = texelFetch(textures[sbo.intr_index], ivec2(0, 0), 0).x; |
| } |
| } |
| )"; |
| const std::string intr_source = SetImagesArrayLength(intr_source_template, "6"); |
| const std::string intr_source_runtime = SetImagesArrayLength(intr_source_template, ""); |
| |
| const std::string call_source_template = R"(#version 460 |
| #extension GL_EXT_nonuniform_qualifier : require |
| #extension GL_EXT_samplerless_texture_functions : require |
| #extension GL_NV_ray_tracing : require |
| |
| layout(set = 0, binding = 1, std430) buffer StorageBuffer { |
| uint rgen_index; |
| uint ahit_index; |
| uint chit_index; |
| uint miss_index; |
| uint intr_index; |
| uint call_index; |
| |
| uint rgen_ran; |
| uint ahit_ran; |
| uint chit_ran; |
| uint miss_ran; |
| uint intr_ran; |
| uint call_ran; |
| |
| float result1; |
| float result2; |
| float result3; |
| } sbo; |
| layout(set = 0, binding = 2) uniform texture2D textures[IMAGES_ARRAY_LENGTH]; |
| |
| layout(location = 3) callableDataInNV vec3 callableData; |
| |
| void main() { |
| sbo.call_ran = 6; |
| |
| callableData = vec3(0.1234f); |
| |
| if (sbo.call_index > 0) { |
| // OOB here: |
| callableData.x = texelFetch(textures[sbo.call_index], ivec2(0, 0), 0).x; |
| } |
| } |
| )"; |
| const std::string call_source = SetImagesArrayLength(call_source_template, "6"); |
| const std::string call_source_runtime = SetImagesArrayLength(call_source_template, ""); |
| |
| struct TestCase { |
| const std::string &rgen_shader_source; |
| const std::string &ahit_shader_source; |
| const std::string &chit_shader_source; |
| const std::string &miss_shader_source; |
| const std::string &intr_shader_source; |
| const std::string &call_shader_source; |
| bool variable_length; |
| uint32_t rgen_index; |
| uint32_t ahit_index; |
| uint32_t chit_index; |
| uint32_t miss_index; |
| uint32_t intr_index; |
| uint32_t call_index; |
| const char *expected_error; |
| }; |
| |
| std::vector<TestCase> tests; |
| tests.push_back({rgen_source, ahit_source, chit_source, miss_source, intr_source, call_source, false, 25, 0, 0, 0, 0, 0, |
| "Index of 25 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source, ahit_source, chit_source, miss_source, intr_source, call_source, false, 0, 25, 0, 0, 0, 0, |
| "Index of 25 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source, ahit_source, chit_source, miss_source, intr_source, call_source, false, 0, 0, 25, 0, 0, 0, |
| "Index of 25 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source, ahit_source, chit_source, miss_source, intr_source, call_source, false, 0, 0, 0, 25, 0, 0, |
| "Index of 25 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source, ahit_source, chit_source, miss_source, intr_source, call_source, false, 0, 0, 0, 0, 25, 0, |
| "Index of 25 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source, ahit_source, chit_source, miss_source, intr_source, call_source, false, 0, 0, 0, 0, 0, 25, |
| "Index of 25 used to index descriptor array of length 6."}); |
| |
| if (descriptor_indexing) { |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 25, 0, 0, 0, 0, 0, "Index of 25 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 25, 0, 0, 0, 0, "Index of 25 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 0, 25, 0, 0, 0, "Index of 25 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 0, 0, 25, 0, 0, "Index of 25 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 0, 0, 0, 25, 0, "Index of 25 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 0, 0, 0, 0, 25, "Index of 25 used to index descriptor array of length 6."}); |
| |
| // For this group, 6 is less than max specified (max specified is 8) but more than actual specified (actual specified is 5) |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 6, 0, 0, 0, 0, 0, "Index of 6 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 6, 0, 0, 0, 0, "Index of 6 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 0, 6, 0, 0, 0, "Index of 6 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 0, 0, 6, 0, 0, "Index of 6 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 0, 0, 0, 6, 0, "Index of 6 used to index descriptor array of length 6."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 0, 0, 0, 0, 6, "Index of 6 used to index descriptor array of length 6."}); |
| |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 5, 0, 0, 0, 0, 0, "Descriptor index 5 is uninitialized."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 5, 0, 0, 0, 0, "Descriptor index 5 is uninitialized."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 0, 5, 0, 0, 0, "Descriptor index 5 is uninitialized."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 0, 0, 5, 0, 0, "Descriptor index 5 is uninitialized."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 0, 0, 0, 5, 0, "Descriptor index 5 is uninitialized."}); |
| tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime, |
| call_source_runtime, true, 0, 0, 0, 0, 0, 5, "Descriptor index 5 is uninitialized."}); |
| } |
| |
| PFN_vkCreateRayTracingPipelinesNV vkCreateRayTracingPipelinesNV = reinterpret_cast<PFN_vkCreateRayTracingPipelinesNV>( |
| vk::GetDeviceProcAddr(m_device->handle(), "vkCreateRayTracingPipelinesNV")); |
| ASSERT_TRUE(vkCreateRayTracingPipelinesNV != nullptr); |
| |
| PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV = |
| reinterpret_cast<PFN_vkGetRayTracingShaderGroupHandlesNV>( |
| vk::GetDeviceProcAddr(m_device->handle(), "vkGetRayTracingShaderGroupHandlesNV")); |
| ASSERT_TRUE(vkGetRayTracingShaderGroupHandlesNV != nullptr); |
| |
| PFN_vkCmdTraceRaysNV vkCmdTraceRaysNV = |
| reinterpret_cast<PFN_vkCmdTraceRaysNV>(vk::GetDeviceProcAddr(m_device->handle(), "vkCmdTraceRaysNV")); |
| ASSERT_TRUE(vkCmdTraceRaysNV != nullptr); |
| |
| // Iteration 0 tests with no descriptor set bound (to sanity test "draw" validation). Iteration 1 |
| // tests what's in the test case vector. |
| for (const auto &test : tests) { |
| if (gpu_assisted) { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, test.expected_error); |
| } |
| |
| VkShaderObj rgen_shader(this, test.rgen_shader_source.c_str(), VK_SHADER_STAGE_RAYGEN_BIT_NV); |
| VkShaderObj ahit_shader(this, test.ahit_shader_source.c_str(), VK_SHADER_STAGE_ANY_HIT_BIT_NV); |
| VkShaderObj chit_shader(this, test.chit_shader_source.c_str(), VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV); |
| VkShaderObj miss_shader(this, test.miss_shader_source.c_str(), VK_SHADER_STAGE_MISS_BIT_NV); |
| VkShaderObj intr_shader(this, test.intr_shader_source.c_str(), VK_SHADER_STAGE_INTERSECTION_BIT_NV); |
| VkShaderObj call_shader(this, test.call_shader_source.c_str(), VK_SHADER_STAGE_CALLABLE_BIT_NV); |
| |
| VkPipelineShaderStageCreateInfo stage_create_infos[6] = {}; |
| stage_create_infos[0] = vku::InitStructHelper(); |
| stage_create_infos[0].stage = VK_SHADER_STAGE_RAYGEN_BIT_NV; |
| stage_create_infos[0].module = rgen_shader.handle(); |
| stage_create_infos[0].pName = "main"; |
| |
| stage_create_infos[1] = vku::InitStructHelper(); |
| stage_create_infos[1].stage = VK_SHADER_STAGE_ANY_HIT_BIT_NV; |
| stage_create_infos[1].module = ahit_shader.handle(); |
| stage_create_infos[1].pName = "main"; |
| |
| stage_create_infos[2] = vku::InitStructHelper(); |
| stage_create_infos[2].stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV; |
| stage_create_infos[2].module = chit_shader.handle(); |
| stage_create_infos[2].pName = "main"; |
| |
| stage_create_infos[3] = vku::InitStructHelper(); |
| stage_create_infos[3].stage = VK_SHADER_STAGE_MISS_BIT_NV; |
| stage_create_infos[3].module = miss_shader.handle(); |
| stage_create_infos[3].pName = "main"; |
| |
| stage_create_infos[4] = vku::InitStructHelper(); |
| stage_create_infos[4].stage = VK_SHADER_STAGE_INTERSECTION_BIT_NV; |
| stage_create_infos[4].module = intr_shader.handle(); |
| stage_create_infos[4].pName = "main"; |
| |
| stage_create_infos[5] = vku::InitStructHelper(); |
| stage_create_infos[5].stage = VK_SHADER_STAGE_CALLABLE_BIT_NV; |
| stage_create_infos[5].module = call_shader.handle(); |
| stage_create_infos[5].pName = "main"; |
| |
| VkRayTracingShaderGroupCreateInfoNV group_create_infos[4] = {}; |
| group_create_infos[0] = vku::InitStructHelper(); |
| group_create_infos[0].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV; |
| group_create_infos[0].generalShader = 0; // rgen |
| group_create_infos[0].closestHitShader = VK_SHADER_UNUSED_NV; |
| group_create_infos[0].anyHitShader = VK_SHADER_UNUSED_NV; |
| group_create_infos[0].intersectionShader = VK_SHADER_UNUSED_NV; |
| |
| group_create_infos[1] = vku::InitStructHelper(); |
| group_create_infos[1].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV; |
| group_create_infos[1].generalShader = 3; // miss |
| group_create_infos[1].closestHitShader = VK_SHADER_UNUSED_NV; |
| group_create_infos[1].anyHitShader = VK_SHADER_UNUSED_NV; |
| group_create_infos[1].intersectionShader = VK_SHADER_UNUSED_NV; |
| |
| group_create_infos[2] = vku::InitStructHelper(); |
| group_create_infos[2].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV; |
| group_create_infos[2].generalShader = VK_SHADER_UNUSED_NV; |
| group_create_infos[2].closestHitShader = 2; |
| group_create_infos[2].anyHitShader = 1; |
| group_create_infos[2].intersectionShader = 4; |
| |
| group_create_infos[3] = vku::InitStructHelper(); |
| group_create_infos[3].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV; |
| group_create_infos[3].generalShader = 5; // call |
| group_create_infos[3].closestHitShader = VK_SHADER_UNUSED_NV; |
| group_create_infos[3].anyHitShader = VK_SHADER_UNUSED_NV; |
| group_create_infos[3].intersectionShader = VK_SHADER_UNUSED_NV; |
| |
| VkRayTracingPipelineCreateInfoNV pipeline_ci = vku::InitStructHelper(); |
| pipeline_ci.stageCount = 6; |
| pipeline_ci.pStages = stage_create_infos; |
| pipeline_ci.groupCount = 4; |
| pipeline_ci.pGroups = group_create_infos; |
| pipeline_ci.maxRecursionDepth = 2; |
| pipeline_ci.layout = test.variable_length ? pipeline_layout_variable.handle() : pipeline_layout.handle(); |
| |
| VkPipeline pipeline = VK_NULL_HANDLE; |
| ASSERT_EQ(VK_SUCCESS, vkCreateRayTracingPipelinesNV(m_device->handle(), VK_NULL_HANDLE, 1, &pipeline_ci, nullptr, &pipeline)); |
| |
| std::vector<uint8_t> shader_binding_table_data; |
| shader_binding_table_data.resize(static_cast<std::size_t>(shader_binding_table_buffer_size), 0); |
| ASSERT_EQ(VK_SUCCESS, vkGetRayTracingShaderGroupHandlesNV(m_device->handle(), pipeline, 0, 4, |
| static_cast<std::size_t>(shader_binding_table_buffer_size), |
| shader_binding_table_data.data())); |
| |
| uint8_t *mapped_shader_binding_table_data = (uint8_t *)shader_binding_table_buffer.memory().map(); |
| std::memcpy(mapped_shader_binding_table_data, shader_binding_table_data.data(), shader_binding_table_data.size()); |
| shader_binding_table_buffer.memory().unmap(); |
| |
| ray_tracing_command_buffer.begin(); |
| |
| vk::CmdBindPipeline(ray_tracing_command_buffer.handle(), VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, pipeline); |
| |
| if (gpu_assisted) { |
| vk::CmdBindDescriptorSets(ray_tracing_command_buffer.handle(), VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, |
| test.variable_length ? pipeline_layout_variable.handle() : pipeline_layout.handle(), 0, 1, |
| test.variable_length ? &ds_variable.set_ : &ds.set_, 0, nullptr); |
| } else { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-None-08600"); |
| } |
| |
| if (gpu_assisted) { |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdTraceRaysNV-callableShaderBindingOffset-02462"); |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdTraceRaysNV-missShaderBindingOffset-02458"); |
| // Need these values to pass mapped storage buffer checks |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupHandleSize * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupHandleSize * 1ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupHandleSize * 2ull, |
| ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupHandleSize * 3ull, ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/1, /*height=*/1, /*depth=*/1); |
| } else { |
| // offset shall be multiple of shaderGroupBaseAlignment and stride of shaderGroupHandleSize |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 1ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment * 2ull, |
| ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 3ull, ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/1, /*height=*/1, /*depth=*/1); |
| } |
| |
| ray_tracing_command_buffer.end(); |
| // Update the index of the texture that the shaders should read |
| uint32_t *mapped_storage_buffer_data = (uint32_t *)storage_buffer.memory().map(); |
| mapped_storage_buffer_data[0] = test.rgen_index; |
| mapped_storage_buffer_data[1] = test.ahit_index; |
| mapped_storage_buffer_data[2] = test.chit_index; |
| mapped_storage_buffer_data[3] = test.miss_index; |
| mapped_storage_buffer_data[4] = test.intr_index; |
| mapped_storage_buffer_data[5] = test.call_index; |
| mapped_storage_buffer_data[6] = 0; |
| mapped_storage_buffer_data[7] = 0; |
| mapped_storage_buffer_data[8] = 0; |
| mapped_storage_buffer_data[9] = 0; |
| mapped_storage_buffer_data[10] = 0; |
| mapped_storage_buffer_data[11] = 0; |
| storage_buffer.memory().unmap(); |
| |
| vk::QueueSubmit(ray_tracing_queue, 1, &submit_info, VK_NULL_HANDLE); |
| vk::QueueWaitIdle(ray_tracing_queue); |
| m_errorMonitor->VerifyFound(); |
| |
| if (gpu_assisted) { |
| mapped_storage_buffer_data = (uint32_t *)storage_buffer.memory().map(); |
| ASSERT_TRUE(mapped_storage_buffer_data[6] == 1); |
| ASSERT_TRUE(mapped_storage_buffer_data[7] == 2); |
| ASSERT_TRUE(mapped_storage_buffer_data[8] == 3); |
| ASSERT_TRUE(mapped_storage_buffer_data[9] == 4); |
| ASSERT_TRUE(mapped_storage_buffer_data[10] == 5); |
| ASSERT_TRUE(mapped_storage_buffer_data[11] == 6); |
| storage_buffer.memory().unmap(); |
| } else { |
| ray_tracing_command_buffer.begin(); |
| vk::CmdBindPipeline(ray_tracing_command_buffer.handle(), VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, pipeline); |
| vk::CmdBindDescriptorSets(ray_tracing_command_buffer.handle(), VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, |
| test.variable_length ? pipeline_layout_variable.handle() : pipeline_layout.handle(), 0, 1, |
| test.variable_length ? &ds_variable.set_ : &ds.set_, 0, nullptr); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-callableShaderBindingOffset-02462"); |
| VkDeviceSize stride_align = ray_tracing_properties.shaderGroupHandleSize; |
| VkDeviceSize invalid_max_stride = ray_tracing_properties.maxShaderGroupStride + |
| (stride_align - (ray_tracing_properties.maxShaderGroupStride % |
| stride_align)); // should be less than maxShaderGroupStride |
| VkDeviceSize invalid_stride = |
| ray_tracing_properties.shaderGroupHandleSize >> 1; // should be multiple of shaderGroupHandleSize |
| VkDeviceSize invalid_offset = |
| ray_tracing_properties.shaderGroupBaseAlignment >> 1; // should be multiple of shaderGroupBaseAlignment |
| |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 1ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment * 2ull, |
| ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(), invalid_offset, |
| ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/1, /*height=*/1, /*depth=*/1); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-callableShaderBindingStride-02465"); |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 1ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment * 2ull, |
| ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment, invalid_stride, |
| /*width=*/1, /*height=*/1, /*depth=*/1); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-callableShaderBindingStride-02468"); |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 1ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment * 2ull, |
| ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment, invalid_max_stride, |
| /*width=*/1, /*height=*/1, /*depth=*/1); |
| m_errorMonitor->VerifyFound(); |
| |
| // hit shader |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-hitShaderBindingOffset-02460"); |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 1ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), invalid_offset, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment, |
| ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/1, /*height=*/1, /*depth=*/1); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-hitShaderBindingStride-02464"); |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 1ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment * 2ull, |
| invalid_stride, shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment, |
| ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/1, /*height=*/1, /*depth=*/1); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-hitShaderBindingStride-02467"); |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 1ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment * 2ull, |
| invalid_max_stride, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment, ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/1, /*height=*/1, /*depth=*/1); |
| m_errorMonitor->VerifyFound(); |
| |
| // miss shader |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-missShaderBindingOffset-02458"); |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| invalid_offset, ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 2ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment, |
| ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/1, /*height=*/1, /*depth=*/1); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-missShaderBindingStride-02463"); |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 1ull, invalid_stride, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment * 2ull, |
| ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment, ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/1, /*height=*/1, /*depth=*/1); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-missShaderBindingStride-02466"); |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 1ull, invalid_max_stride, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment * 2ull, |
| ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment, ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/1, /*height=*/1, /*depth=*/1); |
| m_errorMonitor->VerifyFound(); |
| |
| // raygenshader |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-raygenShaderBindingOffset-02456"); |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), invalid_offset, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment * 1ull, |
| ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 2ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment, |
| ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/1, /*height=*/1, /*depth=*/1); |
| |
| m_errorMonitor->VerifyFound(); |
| const auto &limits = m_device->phy().limits_; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-width-02469"); |
| uint32_t invalid_width = limits.maxComputeWorkGroupCount[0] + 1; |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 1ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment * 2ull, |
| ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment, ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/invalid_width, /*height=*/1, /*depth=*/1); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-height-02470"); |
| uint32_t invalid_height = limits.maxComputeWorkGroupCount[1] + 1; |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 1ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment * 2ull, |
| ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment, ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/1, /*height=*/invalid_height, /*depth=*/1); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysNV-depth-02471"); |
| uint32_t invalid_depth = limits.maxComputeWorkGroupCount[2] + 1; |
| vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 0ull, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment * 1ull, ray_tracing_properties.shaderGroupHandleSize, |
| shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupBaseAlignment * 2ull, |
| ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(), |
| ray_tracing_properties.shaderGroupBaseAlignment, ray_tracing_properties.shaderGroupHandleSize, |
| /*width=*/1, /*height=*/1, /*depth=*/invalid_depth); |
| m_errorMonitor->VerifyFound(); |
| |
| ray_tracing_command_buffer.end(); |
| } |
| vk::DestroyPipeline(m_device->handle(), pipeline, nullptr); |
| } |
| } |
| |
| TEST_F(NegativeRayTracing, BarrierAccessAccelerationStructure) { |
| TEST_DESCRIPTION("Test barrier with access ACCELERATION_STRUCTURE bit."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()) |
| VkPhysicalDeviceSynchronization2FeaturesKHR sync2_features = vku::InitStructHelper(); |
| GetPhysicalDeviceFeatures2(sync2_features); |
| RETURN_IF_SKIP(InitState(nullptr, &sync2_features, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); |
| |
| VkMemoryBarrier2 mem_barrier = vku::InitStructHelper(); |
| mem_barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT; |
| mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; |
| |
| VkDependencyInfo dependency_info = vku::InitStructHelper(); |
| dependency_info.memoryBarrierCount = 1; |
| dependency_info.pMemoryBarriers = &mem_barrier; |
| |
| m_commandBuffer->begin(); |
| |
| mem_barrier.srcAccessMask = VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkMemoryBarrier2-srcAccessMask-03927"); |
| vk::CmdPipelineBarrier2KHR(m_commandBuffer->handle(), &dependency_info); |
| |
| mem_barrier.srcAccessMask = VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkMemoryBarrier2-srcAccessMask-03928"); |
| vk::CmdPipelineBarrier2KHR(m_commandBuffer->handle(), &dependency_info); |
| |
| mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR; |
| |
| mem_barrier.dstAccessMask = VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkMemoryBarrier2-dstAccessMask-03927"); |
| vk::CmdPipelineBarrier2KHR(m_commandBuffer->handle(), &dependency_info); |
| |
| mem_barrier.dstAccessMask = VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkMemoryBarrier2-dstAccessMask-03928"); |
| vk::CmdPipelineBarrier2KHR(m_commandBuffer->handle(), &dependency_info); |
| |
| m_commandBuffer->end(); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracing, BarrierSync2AccessAccelerationStructureRayQueryDisabled) { |
| TEST_DESCRIPTION( |
| "Test sync2 barrier with ACCELERATION_STRUCTURE_READ memory access." |
| "Ray query feature is not enabled."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()) |
| VkPhysicalDeviceSynchronization2FeaturesKHR sync2_features = vku::InitStructHelper(); |
| GetPhysicalDeviceFeatures2(sync2_features); |
| RETURN_IF_SKIP(InitState(nullptr, &sync2_features, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); |
| |
| VkMemoryBarrier2 mem_barrier = vku::InitStructHelper(); |
| mem_barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT; |
| mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; |
| |
| vkt::Buffer buffer(*m_device, 32); |
| |
| VkBufferMemoryBarrier2 buffer_barrier = vku::InitStructHelper(); |
| buffer_barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT; |
| buffer_barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; |
| buffer_barrier.buffer = buffer.handle(); |
| buffer_barrier.size = 32; |
| |
| VkImageObj image(m_device); |
| image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); |
| ASSERT_TRUE(image.initialized()); |
| |
| VkImageMemoryBarrier2 image_barrier = vku::InitStructHelper(); |
| image_barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT; |
| image_barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; |
| image_barrier.image = image.handle(); |
| image_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; |
| |
| VkDependencyInfo dependency_info = vku::InitStructHelper(); |
| dependency_info.memoryBarrierCount = 1; |
| dependency_info.pMemoryBarriers = &mem_barrier; |
| dependency_info.bufferMemoryBarrierCount = 1; |
| dependency_info.pBufferMemoryBarriers = &buffer_barrier; |
| dependency_info.imageMemoryBarrierCount = 1; |
| dependency_info.pImageMemoryBarriers = &image_barrier; |
| |
| m_commandBuffer->begin(); |
| |
| mem_barrier.srcAccessMask = VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| mem_barrier.srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; |
| buffer_barrier.srcAccessMask = VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| buffer_barrier.srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; |
| image_barrier.srcAccessMask = VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| image_barrier.srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; |
| mem_barrier.dstAccessMask = VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| mem_barrier.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; |
| buffer_barrier.dstAccessMask = VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| buffer_barrier.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; |
| image_barrier.dstAccessMask = VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| image_barrier.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkMemoryBarrier2-srcAccessMask-06256"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBufferMemoryBarrier2-srcAccessMask-06256"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkImageMemoryBarrier2-srcAccessMask-06256"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkMemoryBarrier2-dstAccessMask-06256"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBufferMemoryBarrier2-dstAccessMask-06256"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkImageMemoryBarrier2-dstAccessMask-06256"); |
| vk::CmdPipelineBarrier2KHR(m_commandBuffer->handle(), &dependency_info); |
| |
| m_commandBuffer->end(); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracing, BarrierSync1AccessAccelerationStructureRayQueryDisabled) { |
| TEST_DESCRIPTION( |
| "Test sync1 barrier with ACCELERATION_STRUCTURE_READ memory access." |
| "Ray query feature is not enabled."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()) |
| RETURN_IF_SKIP(InitState()) |
| |
| VkMemoryBarrier memory_barrier = vku::InitStructHelper(); |
| memory_barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| memory_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| |
| vkt::Buffer buffer(*m_device, 32); |
| VkBufferMemoryBarrier buffer_barrier = vku::InitStructHelper(); |
| buffer_barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| buffer_barrier.buffer = buffer.handle(); |
| buffer_barrier.size = VK_WHOLE_SIZE; |
| |
| VkImageObj image(m_device); |
| image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); |
| ASSERT_TRUE(image.initialized()); |
| VkImageMemoryBarrier image_barrier = vku::InitStructHelper(); |
| image_barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| image_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| image_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| image_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; |
| image_barrier.image = image.handle(); |
| image_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; |
| |
| m_commandBuffer->begin(); |
| |
| // memory barrier |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdPipelineBarrier-srcAccessMask-06257"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdPipelineBarrier-dstAccessMask-06257"); |
| // buffer barrier |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdPipelineBarrier-srcAccessMask-06257"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdPipelineBarrier-dstAccessMask-06257"); |
| // image barrier |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdPipelineBarrier-srcAccessMask-06257"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdPipelineBarrier-dstAccessMask-06257"); |
| |
| vk::CmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, |
| VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, 0, 1, &memory_barrier, 1, &buffer_barrier, 1, &image_barrier); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracing, EventSync1AccessAccelerationStructureRayQueryDisabled) { |
| TEST_DESCRIPTION( |
| "Test sync1 event wait with ACCELERATION_STRUCTURE_READ memory access." |
| "Ray query feature is not enabled."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()) |
| RETURN_IF_SKIP(InitState()) |
| |
| const vkt::Event event(*m_device); |
| |
| VkMemoryBarrier memory_barrier = vku::InitStructHelper(); |
| memory_barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| memory_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| |
| vkt::Buffer buffer(*m_device, 32); |
| VkBufferMemoryBarrier buffer_barrier = vku::InitStructHelper(); |
| buffer_barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| buffer_barrier.buffer = buffer.handle(); |
| buffer_barrier.size = VK_WHOLE_SIZE; |
| |
| VkImageObj image(m_device); |
| image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0); |
| ASSERT_TRUE(image.initialized()); |
| VkImageMemoryBarrier image_barrier = vku::InitStructHelper(); |
| image_barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| image_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; |
| image_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| image_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; |
| image_barrier.image = image.handle(); |
| image_barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; |
| |
| m_commandBuffer->begin(); |
| |
| // memory |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdWaitEvents-srcAccessMask-06257"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdWaitEvents-dstAccessMask-06257"); |
| // buffer |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdWaitEvents-srcAccessMask-06257"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdWaitEvents-dstAccessMask-06257"); |
| // image |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdWaitEvents-srcAccessMask-06257"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdWaitEvents-dstAccessMask-06257"); |
| |
| m_commandBuffer->WaitEvents(1, &event.handle(), VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, |
| 1, &memory_barrier, 1, &buffer_barrier, 1, &image_barrier); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracing, DescriptorBindingUpdateAfterBindWithAccelerationStructure) { |
| TEST_DESCRIPTION("Validate acceleration structure descriptor writing."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_3_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, false)) |
| RETURN_IF_SKIP(InitState()) |
| |
| VkDescriptorSetLayoutBinding binding = {}; |
| binding.binding = 0; |
| binding.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; |
| binding.descriptorCount = 1; |
| binding.stageFlags = VK_SHADER_STAGE_ALL; |
| binding.pImmutableSamplers = nullptr; |
| |
| VkDescriptorBindingFlags flags = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT; |
| |
| VkDescriptorSetLayoutBindingFlagsCreateInfoEXT flags_create_info = vku::InitStructHelper(); |
| flags_create_info.bindingCount = 1; |
| flags_create_info.pBindingFlags = &flags; |
| |
| VkDescriptorSetLayoutCreateInfo create_info = vku::InitStructHelper(&flags_create_info); |
| create_info.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; |
| create_info.bindingCount = 1; |
| create_info.pBindings = &binding; |
| |
| VkDescriptorSetLayout setLayout; |
| m_errorMonitor->SetDesiredFailureMsg( |
| kErrorBit, "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingAccelerationStructureUpdateAfterBind-03570"); |
| vk::CreateDescriptorSetLayout(device(), &create_info, nullptr, &setLayout); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracing, AccelerationStructureBindings) { |
| TEST_DESCRIPTION("Use more bindings with a descriptorType of VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR than allowed"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()) |
| |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR accel_struct_features = vku::InitStructHelper(); |
| VkPhysicalDeviceRayTracingPipelineFeaturesKHR ray_tracing_pipeline_features = vku::InitStructHelper(&accel_struct_features); |
| GetPhysicalDeviceFeatures2(ray_tracing_pipeline_features); |
| |
| VkPhysicalDeviceAccelerationStructurePropertiesKHR accel_struct_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(accel_struct_props); |
| |
| RETURN_IF_SKIP(InitState(nullptr, &ray_tracing_pipeline_features)); |
| |
| // Create one descriptor set layout holding (maxPerStageDescriptorAccelerationStructures + 1) bindings |
| // for the same shader stage |
| { |
| const uint32_t max_accel_structs = accel_struct_props.maxPerStageDescriptorAccelerationStructures; |
| if (max_accel_structs > 4096) { |
| printf( |
| "Testing VUID-VkPipelineLayoutCreateInfo-descriptorType-03571 requires a small maximum number of per stage " |
| "descriptor update after bind for acceleration structures, " |
| "skipping test\n"); |
| } else if (max_accel_structs < 1) { |
| printf( |
| "Testing VUID-VkPipelineLayoutCreateInfo-descriptorType-03571 requires " |
| "maxPerStageDescriptorAccelerationStructures >= 1, skipping test\n"); |
| } else { |
| std::vector<VkDescriptorSetLayoutBinding> dslb_vec = {}; |
| dslb_vec.reserve(max_accel_structs); |
| |
| for (uint32_t i = 0; i < max_accel_structs + 1; ++i) { |
| VkDescriptorSetLayoutBinding dslb = {}; |
| dslb.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; |
| dslb.descriptorCount = 1; |
| dslb.stageFlags = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; |
| dslb.binding = i; |
| dslb_vec.push_back(dslb); |
| } |
| |
| VkDescriptorSetLayoutCreateInfo ds_layout_ci = vku::InitStructHelper(); |
| ds_layout_ci.bindingCount = dslb_vec.size(); |
| ds_layout_ci.pBindings = dslb_vec.data(); |
| |
| vkt::DescriptorSetLayout ds_layout(*m_device, ds_layout_ci); |
| ASSERT_TRUE(ds_layout.initialized()); |
| |
| VkPipelineLayoutCreateInfo pipeline_layout_ci = vku::InitStructHelper(); |
| pipeline_layout_ci.setLayoutCount = 1; |
| pipeline_layout_ci.pSetLayouts = &ds_layout.handle(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkPipelineLayoutCreateInfo-descriptorType-03571"); |
| m_errorMonitor->SetAllowedFailureMsg("VUID-VkPipelineLayoutCreateInfo-descriptorType-03572"); |
| m_errorMonitor->SetAllowedFailureMsg("VUID-VkPipelineLayoutCreateInfo-descriptorType-03573"); |
| m_errorMonitor->SetAllowedFailureMsg("VUID-VkPipelineLayoutCreateInfo-descriptorType-03574"); |
| vkt::PipelineLayout pipeline_layout(*m_device, pipeline_layout_ci); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // Create one descriptor set layout with flag VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT holding |
| // (maxPerStageDescriptorUpdateAfterBindAccelerationStructures + 1) bindings for the same shader stage |
| { |
| const uint32_t max_accel_structs = accel_struct_props.maxPerStageDescriptorUpdateAfterBindAccelerationStructures; |
| if (max_accel_structs > 4096) { |
| printf( |
| "Testing VUID-VkPipelineLayoutCreateInfo-descriptorType-03572 requires a small maximum number of per stage " |
| "descriptor update after bind for acceleration structures, " |
| "skipping test\n"); |
| } else if (max_accel_structs < 1) { |
| printf( |
| "Testing VUID-VkPipelineLayoutCreateInfo-descriptorType-03572 requires " |
| "maxPerStageDescriptorUpdateAfterBindAccelerationStructures >= 1, skipping test\n"); |
| } else { |
| std::vector<VkDescriptorSetLayoutBinding> dslb_vec = {}; |
| dslb_vec.reserve(max_accel_structs); |
| |
| for (uint32_t i = 0; i < max_accel_structs + 1; ++i) { |
| VkDescriptorSetLayoutBinding dslb = {}; |
| dslb.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; |
| dslb.descriptorCount = 1; |
| dslb.stageFlags = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; |
| dslb.binding = i; |
| dslb_vec.push_back(dslb); |
| } |
| |
| VkDescriptorSetLayoutCreateInfo ds_layout_ci = vku::InitStructHelper(); |
| ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT; |
| ds_layout_ci.bindingCount = dslb_vec.size(); |
| ds_layout_ci.pBindings = dslb_vec.data(); |
| |
| vkt::DescriptorSetLayout ds_layout(*m_device, ds_layout_ci); |
| ASSERT_TRUE(ds_layout.initialized()); |
| |
| VkPipelineLayoutCreateInfo pipeline_layout_ci = vku::InitStructHelper(); |
| pipeline_layout_ci.setLayoutCount = 1; |
| pipeline_layout_ci.pSetLayouts = &ds_layout.handle(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkPipelineLayoutCreateInfo-descriptorType-03572"); |
| m_errorMonitor->SetAllowedFailureMsg("VUID-VkPipelineLayoutCreateInfo-descriptorType-03574"); |
| vkt::PipelineLayout pipeline_layout(*m_device, pipeline_layout_ci); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // Create one descriptor set layout holding (maxDescriptorSetAccelerationStructures + 1) bindings |
| // in total for two different shader stage |
| { |
| const uint32_t max_accel_structs = accel_struct_props.maxDescriptorSetAccelerationStructures; |
| if (max_accel_structs > 4096) { |
| printf( |
| "Testing VUID-VkPipelineLayoutCreateInfo-descriptorType-03573 requires a small maximum number of per stage " |
| "descriptor update after bind for acceleration structures, " |
| "skipping test\n"); |
| } else if (max_accel_structs < 1) { |
| printf( |
| "Testing VUID-VkPipelineLayoutCreateInfo-descriptorType-03573 requires " |
| "maxDescriptorSetAccelerationStructures >= 1, skipping test\n"); |
| } else { |
| std::vector<VkDescriptorSetLayoutBinding> dslb_vec = {}; |
| dslb_vec.reserve(max_accel_structs); |
| |
| for (uint32_t i = 0; i < max_accel_structs + 1; ++i) { |
| VkDescriptorSetLayoutBinding dslb = {}; |
| dslb.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; |
| dslb.descriptorCount = 1; |
| dslb.stageFlags = (i % 2) ? VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR : VK_SHADER_STAGE_CALLABLE_BIT_KHR; |
| dslb.binding = i; |
| dslb_vec.push_back(dslb); |
| } |
| |
| VkDescriptorSetLayoutCreateInfo ds_layout_ci = vku::InitStructHelper(); |
| ds_layout_ci.bindingCount = dslb_vec.size(); |
| ds_layout_ci.pBindings = dslb_vec.data(); |
| |
| vkt::DescriptorSetLayout ds_layout(*m_device, ds_layout_ci); |
| ASSERT_TRUE(ds_layout.initialized()); |
| |
| VkPipelineLayoutCreateInfo pipeline_layout_ci = vku::InitStructHelper(); |
| pipeline_layout_ci.setLayoutCount = 1; |
| pipeline_layout_ci.pSetLayouts = &ds_layout.handle(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkPipelineLayoutCreateInfo-descriptorType-03573"); |
| m_errorMonitor->SetAllowedFailureMsg("VUID-VkPipelineLayoutCreateInfo-descriptorType-03571"); |
| m_errorMonitor->SetAllowedFailureMsg("VUID-VkPipelineLayoutCreateInfo-descriptorType-03572"); |
| m_errorMonitor->SetAllowedFailureMsg("VUID-VkPipelineLayoutCreateInfo-descriptorType-03574"); |
| vkt::PipelineLayout pipeline_layout(*m_device, pipeline_layout_ci); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // Create one descriptor set layout with flag VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT holding |
| // (maxDescriptorSetUpdateAfterBindAccelerationStructures + 1) bindings in total for two different shader stage |
| { |
| const uint32_t max_accel_structs = accel_struct_props.maxDescriptorSetUpdateAfterBindAccelerationStructures; |
| if (max_accel_structs > 4096) { |
| printf( |
| "Testing VUID-VkPipelineLayoutCreateInfo-descriptorType-03574 requires a small maximum number of per stage " |
| "descriptor update after bind for acceleration structures, " |
| "skipping test\n"); |
| } else if (max_accel_structs < 1) { |
| printf( |
| "Testing VUID-VkPipelineLayoutCreateInfo-descriptorType-03574 requires " |
| "maxDescriptorSetUpdateAfterBindAccelerationStructures >= 1, skipping test\n"); |
| } else { |
| std::vector<VkDescriptorSetLayoutBinding> dslb_vec = {}; |
| dslb_vec.reserve(max_accel_structs); |
| |
| for (uint32_t i = 0; i < max_accel_structs + 1; ++i) { |
| VkDescriptorSetLayoutBinding dslb = {}; |
| dslb.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; |
| dslb.descriptorCount = 1; |
| dslb.stageFlags = (i % 2) ? VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR : VK_SHADER_STAGE_CALLABLE_BIT_KHR; |
| dslb.binding = i; |
| dslb_vec.push_back(dslb); |
| } |
| |
| VkDescriptorSetLayoutCreateInfo ds_layout_ci = vku::InitStructHelper(); |
| ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT; |
| ds_layout_ci.bindingCount = dslb_vec.size(); |
| ds_layout_ci.pBindings = dslb_vec.data(); |
| |
| vkt::DescriptorSetLayout ds_layout(*m_device, ds_layout_ci); |
| ASSERT_TRUE(ds_layout.initialized()); |
| |
| VkPipelineLayoutCreateInfo pipeline_layout_ci = vku::InitStructHelper(); |
| pipeline_layout_ci.setLayoutCount = 1; |
| pipeline_layout_ci.pSetLayouts = &ds_layout.handle(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkPipelineLayoutCreateInfo-descriptorType-03574"); |
| m_errorMonitor->SetAllowedFailureMsg("VUID-VkPipelineLayoutCreateInfo-descriptorType-03572"); |
| vkt::PipelineLayout pipeline_layout(*m_device, pipeline_layout_ci); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| } |
| |
| TEST_F(NegativeRayTracing, BeginQueryQueryPoolType) { |
| TEST_DESCRIPTION("Test CmdBeginQuery with invalid queryPool queryType"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddOptionalExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| AddOptionalExtensions(VK_NV_RAY_TRACING_EXTENSION_NAME); |
| AddOptionalExtensions(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME); |
| AddOptionalExtensions(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()) |
| |
| const bool khr_acceleration_structure = IsExtensionsEnabled(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| const bool nv_ray_tracing = IsExtensionsEnabled(VK_NV_RAY_TRACING_EXTENSION_NAME); |
| const bool ext_transform_feedback = IsExtensionsEnabled(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME); |
| const bool rt_maintenance_1 = IsExtensionsEnabled(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME); |
| |
| if (!khr_acceleration_structure && !nv_ray_tracing) { |
| GTEST_SKIP() << "Extensions " << VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME << " and " << VK_NV_RAY_TRACING_EXTENSION_NAME |
| << " are not supported."; |
| } |
| RETURN_IF_SKIP(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); |
| |
| if (khr_acceleration_structure) { |
| auto cmd_begin_query = [this, ext_transform_feedback](VkQueryType query_type, auto vuid_begin_query, |
| auto vuid_begin_query_indexed) { |
| VkQueryPoolCreateInfo query_pool_ci = vku::InitStructHelper(); |
| query_pool_ci.queryCount = 1; |
| |
| query_pool_ci.queryType = query_type; |
| vkt::QueryPool query_pool(*m_device, query_pool_ci); |
| ASSERT_TRUE(query_pool.initialized()); |
| |
| m_commandBuffer->begin(); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, vuid_begin_query); |
| vk::CmdBeginQuery(m_commandBuffer->handle(), query_pool.handle(), 0, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| if (ext_transform_feedback) { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, vuid_begin_query_indexed); |
| vk::CmdBeginQueryIndexedEXT(m_commandBuffer->handle(), query_pool.handle(), 0, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| } |
| m_commandBuffer->end(); |
| }; |
| |
| cmd_begin_query(VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, "VUID-vkCmdBeginQuery-queryType-04728", |
| "VUID-vkCmdBeginQueryIndexedEXT-queryType-04728"); |
| cmd_begin_query(VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, "VUID-vkCmdBeginQuery-queryType-04728", |
| "VUID-vkCmdBeginQueryIndexedEXT-queryType-04728"); |
| |
| if (rt_maintenance_1) { |
| cmd_begin_query(VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR, "VUID-vkCmdBeginQuery-queryType-06741", |
| "VUID-vkCmdBeginQueryIndexedEXT-queryType-06741"); |
| cmd_begin_query(VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR, |
| "VUID-vkCmdBeginQuery-queryType-06741", "VUID-vkCmdBeginQueryIndexedEXT-queryType-06741"); |
| } |
| } |
| if (nv_ray_tracing) { |
| VkQueryPoolCreateInfo query_pool_ci = vku::InitStructHelper(); |
| query_pool_ci.queryCount = 1; |
| query_pool_ci.queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV; |
| vkt::QueryPool query_pool(*m_device, query_pool_ci); |
| ASSERT_TRUE(query_pool.initialized()); |
| |
| m_commandBuffer->begin(); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBeginQuery-queryType-04729"); |
| vk::CmdBeginQuery(m_commandBuffer->handle(), query_pool.handle(), 0, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| if (ext_transform_feedback) { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBeginQueryIndexedEXT-queryType-04729"); |
| vk::CmdBeginQueryIndexedEXT(m_commandBuffer->handle(), query_pool.handle(), 0, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| } |
| m_commandBuffer->end(); |
| } |
| } |
| |
| TEST_F(NegativeRayTracing, CopyUnboundAccelerationStructure) { |
| TEST_DESCRIPTION("Test CmdCopyQueryPoolResults with unsupported query type"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| |
| AddRequiredExtensions(VK_KHR_MAINTENANCE3_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true)) |
| |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR as_features = vku::InitStructHelper(); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(&as_features); |
| GetPhysicalDeviceFeatures2(bda_features); |
| RETURN_IF_SKIP(InitState(nullptr, &bda_features)); |
| |
| auto blas_no_mem = vkt::as::blueprint::AccelStructSimpleOnDeviceBottomLevel(4096); |
| blas_no_mem->SetDeviceBufferInitNoMem(true); |
| blas_no_mem->Build(*m_device); |
| |
| auto valid_blas = vkt::as::blueprint::AccelStructSimpleOnDeviceBottomLevel(4096); |
| valid_blas->Build(*m_device); |
| |
| VkCopyAccelerationStructureInfoKHR copy_info = vku::InitStructHelper(); |
| copy_info.src = blas_no_mem->handle(); |
| copy_info.dst = valid_blas->handle(); |
| copy_info.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; |
| |
| m_commandBuffer->begin(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkCopyAccelerationStructureInfoKHR-buffer-03718"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureKHR-buffer-03737"); |
| vk::CmdCopyAccelerationStructureKHR(m_commandBuffer->handle(), ©_info); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_info.src = valid_blas->handle(); |
| copy_info.dst = blas_no_mem->handle(); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkCopyAccelerationStructureInfoKHR-buffer-03719"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureKHR-buffer-03738"); |
| vk::CmdCopyAccelerationStructureKHR(m_commandBuffer->handle(), ©_info); |
| m_errorMonitor->VerifyFound(); |
| |
| m_commandBuffer->end(); |
| } |
| |
| TEST_F(NegativeRayTracing, CmdCopyUnboundAccelerationStructure) { |
| TEST_DESCRIPTION("Test CmdCopyAccelerationStructureKHR with buffers not bound to memory"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()) |
| VkPhysicalDeviceBufferDeviceAddressFeatures bda_features = vku::InitStructHelper(); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR accel_features = vku::InitStructHelper(&bda_features); |
| auto features2 = GetPhysicalDeviceFeatures2(accel_features); |
| |
| if (accel_features.accelerationStructureHostCommands == VK_FALSE) { |
| GTEST_SKIP() << "accelerationStructureHostCommands feature is not supported"; |
| } |
| |
| RETURN_IF_SKIP(InitState(nullptr, &features2, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); |
| |
| // Init a non host visible buffer |
| vkt::Buffer buffer; |
| VkBufferCreateInfo buffer_ci = vku::InitStructHelper(); |
| buffer_ci.size = 4096; |
| buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; |
| buffer.init_no_mem(*m_device, buffer_ci); |
| VkMemoryRequirements memory_requirements = buffer.memory_requirements(); |
| VkMemoryAllocateInfo memory_alloc = vku::InitStructHelper(); |
| memory_alloc.allocationSize = memory_requirements.size; |
| ASSERT_TRUE( |
| m_device->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_alloc, 0, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); |
| vkt::DeviceMemory device_memory(*m_device, memory_alloc); |
| ASSERT_TRUE(device_memory.initialized()); |
| vk::BindBufferMemory(m_device->handle(), buffer.handle(), device_memory.handle(), 0); |
| |
| auto blas = vkt::as::blueprint::AccelStructSimpleOnDeviceBottomLevel(4096); |
| blas->SetDeviceBuffer(std::move(buffer)); |
| blas->Build(*m_device); |
| |
| auto blas_no_mem = vkt::as::blueprint::AccelStructSimpleOnDeviceBottomLevel(4096); |
| blas_no_mem->SetDeviceBufferInitNoMem(true); |
| blas_no_mem->Build(*m_device); |
| |
| auto blas_host_mem = vkt::as::blueprint::AccelStructSimpleOnDeviceBottomLevel(4096); |
| blas_host_mem->SetDeviceBufferMemoryPropertyFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); |
| blas_host_mem->Build(*m_device); |
| |
| VkCopyAccelerationStructureInfoKHR copy_info = vku::InitStructHelper(); |
| copy_info.src = blas_no_mem->handle(); |
| copy_info.dst = blas->handle(); |
| copy_info.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; |
| |
| m_commandBuffer->begin(); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkCopyAccelerationStructureInfoKHR-buffer-03718"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureKHR-buffer-03737"); |
| vk::CmdCopyAccelerationStructureKHR(m_commandBuffer->handle(), ©_info); |
| m_errorMonitor->VerifyFound(); |
| m_commandBuffer->end(); |
| |
| copy_info.src = blas->handle(); |
| copy_info.dst = blas_no_mem->handle(); |
| |
| m_commandBuffer->begin(); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkCopyAccelerationStructureInfoKHR-buffer-03719"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureKHR-buffer-03738"); |
| vk::CmdCopyAccelerationStructureKHR(m_commandBuffer->handle(), ©_info); |
| m_errorMonitor->VerifyFound(); |
| m_commandBuffer->end(); |
| |
| copy_info.src = blas->handle(); |
| copy_info.dst = blas_host_mem->handle(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCopyAccelerationStructureKHR-buffer-03727"); |
| vk::CopyAccelerationStructureKHR(device(), VK_NULL_HANDLE, ©_info); |
| m_errorMonitor->VerifyFound(); |
| |
| copy_info.src = blas_host_mem->handle(); |
| copy_info.dst = blas->handle(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCopyAccelerationStructureKHR-buffer-03728"); |
| vk::CopyAccelerationStructureKHR(device(), VK_NULL_HANDLE, ©_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracing, CmdCopyMemoryToAccelerationStructureKHR) { |
| TEST_DESCRIPTION("Validate CmdCopyMemoryToAccelerationStructureKHR with dst buffer not bound to memory"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| VkPhysicalDeviceRayTracingPipelineFeaturesKHR ray_tracing_features = vku::InitStructHelper(); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR accel_features = vku::InitStructHelper(&ray_tracing_features); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(&accel_features); |
| VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(&bda_features); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true, &features2)) |
| if (IsPlatformMockICD()) { |
| GTEST_SKIP() << "Test not supported by MockICD"; |
| } |
| |
| RETURN_IF_SKIP(InitState(nullptr, &features2)) |
| |
| VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper(); |
| alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; |
| vkt::Buffer src_buffer(*m_device, 4096, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, |
| VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &alloc_flags); |
| |
| VkBufferCreateInfo buffer_ci = vku::InitStructHelper(); |
| buffer_ci.size = 1024; |
| buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; |
| vkt::Buffer dst_buffer; |
| dst_buffer.init_no_mem(*m_device, buffer_ci); |
| |
| auto blas = vkt::as::blueprint::AccelStructSimpleOnDeviceBottomLevel(0); |
| blas->SetDeviceBuffer(std::move(dst_buffer)); |
| blas->Build(*m_device); |
| |
| VkCopyMemoryToAccelerationStructureInfoKHR copy_info = vku::InitStructHelper(); |
| copy_info.src.deviceAddress = src_buffer.address(); |
| copy_info.dst = blas->handle(); |
| copy_info.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR; |
| |
| // Acceleration structure buffer is not bound to memory |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyMemoryToAccelerationStructureKHR-buffer-03745"); |
| m_commandBuffer->begin(); |
| vk::CmdCopyMemoryToAccelerationStructureKHR(m_commandBuffer->handle(), ©_info); |
| m_commandBuffer->end(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracing, BuildAccelerationStructureKHR) { |
| TEST_DESCRIPTION("Validate buffers used in vkBuildAccelerationStructureKHR"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()) |
| |
| if (IsPlatformMockICD()) { |
| GTEST_SKIP() << "Test not supported by MockICD"; |
| } |
| |
| VkPhysicalDeviceRayTracingPipelineFeaturesKHR ray_tracing_features = vku::InitStructHelper(); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR acc_structure_features = vku::InitStructHelper(&ray_tracing_features); |
| auto features2 = GetPhysicalDeviceFeatures2(acc_structure_features); |
| if (acc_structure_features.accelerationStructureHostCommands == VK_FALSE) { |
| GTEST_SKIP() << "accelerationStructureHostCommands feature not supported"; |
| } |
| |
| RETURN_IF_SKIP(InitState(nullptr, &features2)) |
| |
| // Init a non host visible buffer |
| vkt::Buffer non_host_visible_buffer; |
| VkBufferCreateInfo buffer_ci = vku::InitStructHelper(); |
| buffer_ci.size = 4096; |
| buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; |
| non_host_visible_buffer.init_no_mem(*m_device, buffer_ci); |
| VkMemoryRequirements memory_requirements = non_host_visible_buffer.memory_requirements(); |
| VkMemoryAllocateInfo memory_alloc = vku::InitStructHelper(); |
| memory_alloc.allocationSize = memory_requirements.size; |
| ASSERT_TRUE( |
| m_device->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_alloc, 0, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); |
| vkt::DeviceMemory device_memory(*m_device, memory_alloc); |
| ASSERT_TRUE(device_memory.initialized()); |
| vk::BindBufferMemory(m_device->handle(), non_host_visible_buffer.handle(), device_memory.handle(), 0); |
| |
| vkt::Buffer host_buffer(*m_device, 4096, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); |
| |
| auto bot_level_as = vkt::as::blueprint::BuildGeometryInfoSimpleOnHostBottomLevel(*m_device); |
| bot_level_as.GetDstAS()->SetDeviceBuffer(std::move(non_host_visible_buffer)); |
| |
| // .dstAccelerationStructure buffer is not bound to host visible memory |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkBuildAccelerationStructuresKHR-pInfos-03722"); |
| bot_level_as.BuildHost(instance(), *m_device); |
| m_errorMonitor->VerifyFound(); |
| |
| auto host_cached_blas = vkt::as::blueprint::BuildGeometryInfoSimpleOnHostBottomLevel(*m_device); |
| |
| host_cached_blas.SetMode(VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR); |
| host_cached_blas.SetSrcAS(vkt::as::blueprint::AccelStructSimpleOnHostBottomLevel(4096)); |
| host_cached_blas.GetDstAS()->SetDeviceBufferMemoryPropertyFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); |
| |
| // .mode is UPDATE and .srcAccelerationStructure buffer is not bound to host visible memory |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkBuildAccelerationStructuresKHR-pInfos-03723"); |
| host_cached_blas.BuildHost(instance(), *m_device); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracing, WriteAccelerationStructureMemory) { |
| TEST_DESCRIPTION("Test memory in vkWriteAccelerationStructuresPropertiesKHR is host visible"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()) |
| |
| VkPhysicalDeviceRayQueryFeaturesKHR ray_query_features = vku::InitStructHelper(); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR as_features = vku::InitStructHelper(&ray_query_features); |
| GetPhysicalDeviceFeatures2(as_features); |
| |
| if (as_features.accelerationStructureHostCommands == VK_FALSE) { |
| GTEST_SKIP() << "accelerationStructureHostCommands feature is not supported"; |
| } |
| |
| RETURN_IF_SKIP(InitState(nullptr, &as_features)); |
| |
| // Init a non host visible buffer |
| vkt::Buffer non_host_visible_buffer; |
| VkBufferCreateInfo buffer_ci = vku::InitStructHelper(); |
| buffer_ci.size = 4096; |
| buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; |
| non_host_visible_buffer.init_no_mem(*m_device, buffer_ci); |
| VkMemoryRequirements memory_requirements = non_host_visible_buffer.memory_requirements(); |
| VkMemoryAllocateInfo memory_alloc = vku::InitStructHelper(); |
| memory_alloc.allocationSize = memory_requirements.size; |
| ASSERT_TRUE( |
| m_device->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_alloc, 0, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); |
| vkt::DeviceMemory device_memory(*m_device, memory_alloc); |
| ASSERT_TRUE(device_memory.initialized()); |
| vk::BindBufferMemory(m_device->handle(), non_host_visible_buffer.handle(), device_memory.handle(), 0); |
| |
| auto build_geometry_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnHostBottomLevel(*m_device); |
| build_geometry_info.GetDstAS()->SetDeviceBuffer(std::move(non_host_visible_buffer)); |
| |
| // .dstAccelerationStructure buffer is not bound to host visible memory |
| m_errorMonitor->SetAllowedFailureMsg("VUID-vkBuildAccelerationStructuresKHR-pInfos-03722"); |
| build_geometry_info.SetFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR); |
| build_geometry_info.BuildHost(instance(), *m_device); |
| m_errorMonitor->VerifyFound(); |
| |
| std::vector<uint32_t> data(4096); |
| // .dstAccelerationStructure buffer is not bound to host visible memory |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkWriteAccelerationStructuresPropertiesKHR-buffer-03733"); |
| vk::WriteAccelerationStructuresPropertiesKHR(device(), 1, &build_geometry_info.GetDstAS()->handle(), |
| VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, data.size(), data.data(), |
| data.size()); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracing, CopyMemoryToAsBuffer) { |
| TEST_DESCRIPTION("Test invalid buffer used in vkCopyMemoryToAccelerationStructureKHR."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()) |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR accel_features = vku::InitStructHelper(); |
| auto features2 = GetPhysicalDeviceFeatures2(accel_features); |
| if (accel_features.accelerationStructureHostCommands == VK_FALSE) { |
| GTEST_SKIP() << "accelerationStructureHostCommands feature is not supported"; |
| } |
| |
| RETURN_IF_SKIP(InitState(nullptr, &features2)) |
| |
| // Init a non host visible buffer |
| vkt::Buffer non_host_visible_buffer; |
| VkBufferCreateInfo buffer_ci = vku::InitStructHelper(); |
| buffer_ci.size = 4096; |
| buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; |
| non_host_visible_buffer.init_no_mem(*m_device, buffer_ci); |
| VkMemoryRequirements memory_requirements = non_host_visible_buffer.memory_requirements(); |
| VkMemoryAllocateInfo memory_alloc = vku::InitStructHelper(); |
| memory_alloc.allocationSize = memory_requirements.size; |
| ASSERT_TRUE( |
| m_device->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_alloc, 0, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); |
| vkt::DeviceMemory device_memory(*m_device, memory_alloc); |
| ASSERT_TRUE(device_memory.initialized()); |
| vk::BindBufferMemory(m_device->handle(), non_host_visible_buffer.handle(), device_memory.handle(), 0); |
| |
| auto blas = vkt::as::blueprint::AccelStructSimpleOnHostBottomLevel(buffer_ci.size); |
| blas->SetDeviceBuffer(std::move(non_host_visible_buffer)); |
| blas->Build(*m_device); |
| |
| uint8_t output[4096]; |
| VkDeviceOrHostAddressConstKHR output_data; |
| output_data.hostAddress = reinterpret_cast<void *>(output); |
| |
| VkCopyMemoryToAccelerationStructureInfoKHR info = vku::InitStructHelper(); |
| info.dst = blas->handle(); |
| info.src = output_data; |
| info.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR; |
| |
| // .dstAccelerationStructure buffer is not bound to host visible memory |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCopyMemoryToAccelerationStructureKHR-buffer-03730"); |
| vk::CopyMemoryToAccelerationStructureKHR(device(), VK_NULL_HANDLE, &info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracing, ArrayOOBRayTracingShaders) { |
| TEST_DESCRIPTION( |
| "Core validation: Verify detection of out-of-bounds descriptor array indexing and use of uninitialized descriptors for " |
| "ray tracing shaders."); |
| |
| OOBRayTracingShadersTestBody(false); |
| } |
| |
| TEST_F(NegativeRayTracing, CreateAccelerationStructureKHR) { |
| TEST_DESCRIPTION("Validate acceleration structure creation."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| VkPhysicalDeviceRayTracingPipelineFeaturesKHR ray_tracing_features = vku::InitStructHelper(); |
| VkPhysicalDeviceRayQueryFeaturesKHR ray_query_features = vku::InitStructHelper(&ray_tracing_features); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR acc_struct_features = vku::InitStructHelper(&ray_query_features); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(&acc_struct_features); |
| VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(&bda_features); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true, &features2)) |
| RETURN_IF_SKIP(InitState(nullptr, &features2)) |
| |
| VkAccelerationStructureKHR as; |
| VkAccelerationStructureCreateInfoKHR as_create_info = vku::InitStructHelper(); |
| VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper(); |
| alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; |
| vkt::Buffer buffer(*m_device, 4096, |
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, |
| VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &alloc_flags); |
| as_create_info.buffer = buffer.handle(); |
| as_create_info.createFlags = 0; |
| as_create_info.offset = 0; |
| as_create_info.size = 0; |
| as_create_info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; |
| as_create_info.deviceAddress = 0; |
| |
| VkBufferDeviceAddressInfo device_address_info = {VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, NULL, buffer.handle()}; |
| VkDeviceAddress device_address = vk::GetBufferDeviceAddressKHR(device(), &device_address_info); |
| // invalid buffer; |
| { |
| vkt::Buffer invalid_buffer(*m_device, 4096, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, |
| VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); |
| VkAccelerationStructureCreateInfoKHR invalid_as_create_info = as_create_info; |
| invalid_as_create_info.buffer = invalid_buffer.handle(); |
| m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, |
| "VUID-VkAccelerationStructureCreateInfoKHR-buffer-03614"); |
| vk::CreateAccelerationStructureKHR(device(), &invalid_as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // invalid deviceAddress and flag; |
| { |
| VkAccelerationStructureCreateInfoKHR invalid_as_create_info = as_create_info; |
| invalid_as_create_info.deviceAddress = device_address; |
| m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, |
| "VUID-VkAccelerationStructureCreateInfoKHR-deviceAddress-03612"); |
| vk::CreateAccelerationStructureKHR(device(), &invalid_as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| |
| invalid_as_create_info.deviceAddress = 0; |
| invalid_as_create_info.createFlags = VK_ACCELERATION_STRUCTURE_CREATE_FLAG_BITS_MAX_ENUM_KHR; |
| m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, |
| "VUID-VkAccelerationStructureCreateInfoKHR-createFlags-parameter"); |
| vk::CreateAccelerationStructureKHR(device(), &invalid_as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // invalid size and offset; |
| { |
| VkAccelerationStructureCreateInfoKHR invalid_as_create_info = as_create_info; |
| invalid_as_create_info.size = 4097; // buffer size is 4096 |
| m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, |
| "VUID-VkAccelerationStructureCreateInfoKHR-offset-03616"); |
| vk::CreateAccelerationStructureKHR(device(), &invalid_as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // invalid sType; |
| { |
| VkAccelerationStructureCreateInfoKHR invalid_as_create_info = as_create_info; |
| invalid_as_create_info.sType = VK_STRUCTURE_TYPE_MAX_ENUM; |
| m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, |
| "VUID-VkAccelerationStructureCreateInfoKHR-sType-sType"); |
| vk::CreateAccelerationStructureKHR(device(), &invalid_as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // invalid type; |
| { |
| VkAccelerationStructureCreateInfoKHR invalid_as_create_info = as_create_info; |
| invalid_as_create_info.type = VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR; |
| m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, |
| "VUID-VkAccelerationStructureCreateInfoKHR-type-parameter"); |
| vk::CreateAccelerationStructureKHR(device(), &invalid_as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeRayTracing, CreateAccelerationStructureKHRReplayFeature) { |
| TEST_DESCRIPTION("Validate acceleration structure creation replay feature."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR acc_struct_features = vku::InitStructHelper(); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(&acc_struct_features); |
| VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(&bda_features); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true, &features2)) |
| |
| acc_struct_features.accelerationStructureCaptureReplay = VK_FALSE; |
| RETURN_IF_SKIP(InitState(nullptr, &features2)) |
| |
| VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper(); |
| alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; |
| vkt::Buffer buffer(*m_device, 4096, |
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, |
| VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &alloc_flags); |
| |
| VkBufferDeviceAddressInfo device_address_info = vku::InitStructHelper(); |
| device_address_info.buffer = buffer.handle(); |
| VkDeviceAddress device_address = vk::GetBufferDeviceAddressKHR(device(), &device_address_info); |
| |
| VkAccelerationStructureCreateInfoKHR as_create_info = vku::InitStructHelper(); |
| as_create_info.buffer = buffer.handle(); |
| as_create_info.createFlags = VK_ACCELERATION_STRUCTURE_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR; |
| as_create_info.offset = 0; |
| as_create_info.size = 0; |
| as_create_info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; |
| as_create_info.deviceAddress = device_address; |
| |
| VkAccelerationStructureKHR as; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureCreateInfoKHR-createFlags-03613"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCreateAccelerationStructureKHR-deviceAddress-03488"); |
| vk::CreateAccelerationStructureKHR(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracing, CmdTraceRaysKHR) { |
| TEST_DESCRIPTION("Validate vkCmdTraceRaysKHR."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(); |
| bda_features.bufferDeviceAddress = VK_TRUE; |
| VkPhysicalDeviceRayTracingPipelineFeaturesKHR ray_tracing_features = vku::InitStructHelper(&bda_features); |
| VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(&ray_tracing_features); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true, &features2)) |
| if (IsPlatformMockICD()) { |
| GTEST_SKIP() << "Test not supported by MockICD"; |
| } |
| RETURN_IF_SKIP(InitState(nullptr, &features2)) |
| |
| // Create ray tracing pipeline |
| VkPipeline raytracing_pipeline = VK_NULL_HANDLE; |
| { |
| const vkt::PipelineLayout empty_pipeline_layout(*m_device, {}); |
| VkShaderObj rgen_shader(this, kRayTracingMinimalGlsl, VK_SHADER_STAGE_RAYGEN_BIT_KHR, SPV_ENV_VULKAN_1_2); |
| VkShaderObj chit_shader(this, kRayTracingMinimalGlsl, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, SPV_ENV_VULKAN_1_2); |
| |
| const vkt::PipelineLayout pipeline_layout(*m_device, {}); |
| |
| std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages; |
| shader_stages[0] = vku::InitStructHelper(); |
| shader_stages[0].stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; |
| shader_stages[0].module = chit_shader.handle(); |
| shader_stages[0].pName = "main"; |
| |
| shader_stages[1] = vku::InitStructHelper(); |
| shader_stages[1].stage = VK_SHADER_STAGE_RAYGEN_BIT_KHR; |
| shader_stages[1].module = rgen_shader.handle(); |
| shader_stages[1].pName = "main"; |
| |
| std::array<VkRayTracingShaderGroupCreateInfoKHR, 1> shader_groups; |
| shader_groups[0] = vku::InitStructHelper(); |
| shader_groups[0].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; |
| shader_groups[0].generalShader = 1; |
| shader_groups[0].closestHitShader = VK_SHADER_UNUSED_KHR; |
| shader_groups[0].anyHitShader = VK_SHADER_UNUSED_KHR; |
| shader_groups[0].intersectionShader = VK_SHADER_UNUSED_KHR; |
| |
| VkRayTracingPipelineCreateInfoKHR raytracing_pipeline_ci = vku::InitStructHelper(); |
| raytracing_pipeline_ci.flags = 0; |
| raytracing_pipeline_ci.stageCount = static_cast<uint32_t>(shader_stages.size()); |
| raytracing_pipeline_ci.pStages = shader_stages.data(); |
| raytracing_pipeline_ci.pGroups = shader_groups.data(); |
| raytracing_pipeline_ci.groupCount = shader_groups.size(); |
| raytracing_pipeline_ci.layout = pipeline_layout.handle(); |
| |
| const VkResult result = vk::CreateRayTracingPipelinesKHR(m_device->handle(), VK_NULL_HANDLE, VK_NULL_HANDLE, 1, |
| &raytracing_pipeline_ci, nullptr, &raytracing_pipeline); |
| ASSERT_EQ(VK_SUCCESS, result); |
| } |
| |
| vkt::Buffer buffer; |
| VkBufferCreateInfo buffer_ci = vku::InitStructHelper(); |
| buffer_ci.usage = |
| VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR; |
| buffer_ci.size = 4096; |
| buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| buffer.init_no_mem(*m_device, buffer_ci); |
| |
| VkMemoryRequirements mem_reqs; |
| vk::GetBufferMemoryRequirements(device(), buffer.handle(), &mem_reqs); |
| |
| VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper(); |
| alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(&alloc_flags); |
| alloc_info.allocationSize = 4096; |
| vkt::DeviceMemory mem(*m_device, alloc_info); |
| vk::BindBufferMemory(device(), buffer.handle(), mem.handle(), 0); |
| |
| VkPhysicalDeviceRayTracingPipelinePropertiesKHR ray_tracing_properties = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(ray_tracing_properties); |
| |
| const VkDeviceAddress device_address = buffer.address(); |
| |
| VkStridedDeviceAddressRegionKHR stridebufregion = {}; |
| stridebufregion.deviceAddress = device_address; |
| stridebufregion.stride = ray_tracing_properties.shaderGroupHandleAlignment; |
| stridebufregion.size = stridebufregion.stride; |
| |
| m_commandBuffer->begin(); |
| |
| // Invalid stride multiplier |
| { |
| VkStridedDeviceAddressRegionKHR invalid_stride = stridebufregion; |
| invalid_stride.stride = (stridebufregion.size + 1) % stridebufregion.size; |
| if (invalid_stride.stride > 0) { |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdTraceRaysKHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysKHR-stride-03694"); |
| vk::CmdTraceRaysKHR(m_commandBuffer->handle(), &stridebufregion, &stridebufregion, &stridebufregion, &invalid_stride, |
| 100, 100, 1); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdTraceRaysKHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysKHR-stride-03690"); |
| vk::CmdTraceRaysKHR(m_commandBuffer->handle(), &stridebufregion, &stridebufregion, &invalid_stride, &stridebufregion, |
| 100, 100, 1); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdTraceRaysKHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysKHR-stride-03686"); |
| vk::CmdTraceRaysKHR(m_commandBuffer->handle(), &stridebufregion, &invalid_stride, &stridebufregion, &stridebufregion, |
| 100, 100, 1); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| // Invalid stride, greater than maxShaderGroupStride |
| { |
| VkStridedDeviceAddressRegionKHR invalid_stride = stridebufregion; |
| uint32_t align = ray_tracing_properties.shaderGroupHandleSize; |
| invalid_stride.stride = static_cast<VkDeviceSize>(ray_tracing_properties.maxShaderGroupStride) + |
| (align - (ray_tracing_properties.maxShaderGroupStride % align)); |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdTraceRaysKHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysKHR-stride-04041"); |
| vk::CmdTraceRaysKHR(m_commandBuffer->handle(), &stridebufregion, &stridebufregion, &stridebufregion, &invalid_stride, 100, |
| 100, 1); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdTraceRaysKHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysKHR-stride-04035"); |
| vk::CmdTraceRaysKHR(m_commandBuffer->handle(), &stridebufregion, &stridebufregion, &invalid_stride, &stridebufregion, 100, |
| 100, 1); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdTraceRaysKHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysKHR-stride-04029"); |
| vk::CmdTraceRaysKHR(m_commandBuffer->handle(), &stridebufregion, &invalid_stride, &stridebufregion, &stridebufregion, 100, |
| 100, 1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, raytracing_pipeline); |
| |
| // buffer is missing flag VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR |
| vkt::Buffer buffer_missing_flag; |
| buffer_ci.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| buffer_missing_flag.init_no_mem(*m_device, buffer_ci); |
| vk::BindBufferMemory(device(), buffer_missing_flag.handle(), mem.handle(), 0); |
| const VkDeviceAddress device_address_missing_flag = buffer_missing_flag.address(); |
| |
| // buffer is missing flag VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR |
| { |
| VkStridedDeviceAddressRegionKHR invalid_stride = stridebufregion; |
| // This address is the same as the one from the first (valid) buffer, so no validation error |
| invalid_stride.deviceAddress = device_address_missing_flag; |
| vk::CmdTraceRaysKHR(m_commandBuffer->handle(), &invalid_stride, &stridebufregion, &stridebufregion, &stridebufregion, 100, |
| 100, 1); |
| } |
| |
| // pRayGenShaderBindingTable address range and stride are invalid |
| { |
| VkStridedDeviceAddressRegionKHR invalid_stride = stridebufregion; |
| invalid_stride.stride = 8128; |
| invalid_stride.size = 8128; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysKHR-pRayGenShaderBindingTable-03681"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkStridedDeviceAddressRegionKHR-size-04631"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkStridedDeviceAddressRegionKHR-size-04632"); |
| vk::CmdTraceRaysKHR(m_commandBuffer->handle(), &invalid_stride, &stridebufregion, &stridebufregion, &stridebufregion, 100, |
| 100, 1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // pMissShaderBindingTable->deviceAddress == 0 |
| { |
| VkStridedDeviceAddressRegionKHR invalid_stride = stridebufregion; |
| invalid_stride.deviceAddress = 0; |
| vk::CmdTraceRaysKHR(m_commandBuffer->handle(), &stridebufregion, &invalid_stride, &stridebufregion, &stridebufregion, 100, |
| 100, 1); |
| m_errorMonitor->VerifyFound(); |
| } |
| // pHitShaderBindingTable->deviceAddress == 0 |
| { |
| VkStridedDeviceAddressRegionKHR invalid_stride = stridebufregion; |
| invalid_stride.deviceAddress = 0; |
| vk::CmdTraceRaysKHR(m_commandBuffer->handle(), &stridebufregion, &stridebufregion, &invalid_stride, &stridebufregion, 100, |
| 100, 1); |
| } |
| // pCallableShaderBindingTable->deviceAddress == 0 |
| { |
| VkStridedDeviceAddressRegionKHR invalid_stride = stridebufregion; |
| invalid_stride.deviceAddress = 0; |
| vk::CmdTraceRaysKHR(m_commandBuffer->handle(), &stridebufregion, &stridebufregion, &stridebufregion, &invalid_stride, 100, |
| 100, 1); |
| } |
| |
| m_commandBuffer->end(); |
| |
| vk::DestroyPipeline(device(), raytracing_pipeline, nullptr); |
| } |
| |
| TEST_F(NegativeRayTracing, CmdTraceRaysIndirectKHR) { |
| TEST_DESCRIPTION("Validate vkCmdTraceRaysIndirectKHR."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| VkPhysicalDeviceRayTracingPipelineFeaturesKHR ray_tracing_features = vku::InitStructHelper(); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(&ray_tracing_features); |
| VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(&bda_features); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true, &features2)) |
| |
| if (ray_tracing_features.rayTracingPipelineTraceRaysIndirect == VK_FALSE) { |
| GTEST_SKIP() << "rayTracingIndirectTraceRays not supported"; |
| } |
| RETURN_IF_SKIP(InitState(nullptr, &features2)) |
| |
| VkBufferCreateInfo buf_info = vku::InitStructHelper(); |
| buf_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| buf_info.size = 4096; |
| buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper(); |
| allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT; |
| vkt::Buffer buffer(*m_device, buf_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocate_flag_info); |
| |
| VkPhysicalDeviceRayTracingPipelinePropertiesKHR ray_tracing_properties = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(ray_tracing_properties); |
| |
| const VkDeviceAddress device_address = buffer.address(); |
| |
| VkStridedDeviceAddressRegionKHR stridebufregion = {}; |
| stridebufregion.deviceAddress = device_address; |
| stridebufregion.stride = ray_tracing_properties.shaderGroupHandleAlignment; |
| stridebufregion.size = stridebufregion.stride; |
| |
| m_commandBuffer->begin(); |
| // Invalid stride multiplier |
| { |
| VkStridedDeviceAddressRegionKHR invalid_stride = stridebufregion; |
| invalid_stride.stride = (stridebufregion.size + 1) % stridebufregion.size; |
| if (invalid_stride.stride > 0) { |
| // TODO - Create minimal ray tracing pipeline helper - remove all extra `08606` |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirectKHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirectKHR-stride-03694"); |
| vk::CmdTraceRaysIndirectKHR(m_commandBuffer->handle(), &stridebufregion, &stridebufregion, &stridebufregion, |
| &invalid_stride, device_address); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirectKHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirectKHR-stride-03690"); |
| vk::CmdTraceRaysIndirectKHR(m_commandBuffer->handle(), &stridebufregion, &stridebufregion, &invalid_stride, |
| &stridebufregion, device_address); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirectKHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirectKHR-stride-03686"); |
| vk::CmdTraceRaysIndirectKHR(m_commandBuffer->handle(), &stridebufregion, &invalid_stride, &stridebufregion, |
| &stridebufregion, device_address); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| // Invalid stride, greater than maxShaderGroupStride |
| // Given the invalid stride computation, stride is likely to also be misaligned, so allow above errors |
| { |
| VkStridedDeviceAddressRegionKHR invalid_stride = stridebufregion; |
| if (ray_tracing_properties.maxShaderGroupStride == |
| std::numeric_limits<decltype(ray_tracing_properties.maxShaderGroupStride)>::max()) { |
| printf("ray_tracing_properties.maxShaderGroupStride has maximum possible value, skipping related tests\n"); |
| } else { |
| invalid_stride.stride = ray_tracing_properties.maxShaderGroupStride + 1; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirectKHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirectKHR-stride-04041"); |
| m_errorMonitor->SetAllowedFailureMsg("VUID-vkCmdTraceRaysIndirectKHR-stride-03694"); |
| vk::CmdTraceRaysIndirectKHR(m_commandBuffer->handle(), &stridebufregion, &stridebufregion, &stridebufregion, |
| &invalid_stride, device_address); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirectKHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirectKHR-stride-04035"); |
| m_errorMonitor->SetAllowedFailureMsg("VUID-vkCmdTraceRaysIndirectKHR-stride-03690"); |
| vk::CmdTraceRaysIndirectKHR(m_commandBuffer->handle(), &stridebufregion, &stridebufregion, &invalid_stride, |
| &stridebufregion, device_address); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirectKHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirectKHR-stride-04029"); |
| m_errorMonitor->SetAllowedFailureMsg("VUID-vkCmdTraceRaysIndirectKHR-stride-03686"); |
| vk::CmdTraceRaysIndirectKHR(m_commandBuffer->handle(), &stridebufregion, &invalid_stride, &stridebufregion, |
| &stridebufregion, device_address); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| m_commandBuffer->end(); |
| } |
| |
| TEST_F(NegativeRayTracing, CmdTraceRaysIndirect2KHRFeatureDisabled) { |
| TEST_DESCRIPTION("Validate vkCmdTraceRaysIndirect2KHR."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME); |
| // VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR maintenance1_features = vku::InitStructHelper(); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(); |
| VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(&bda_features); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true, &features2)) |
| RETURN_IF_SKIP(InitState(nullptr, &features2)) |
| |
| VkBufferCreateInfo buffer_info = vku::InitStructHelper(); |
| buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| buffer_info.size = 4096; |
| buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper(); |
| allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT; |
| vkt::Buffer buffer(*m_device, buffer_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocate_flag_info); |
| |
| const VkDeviceAddress device_address = buffer.address(); |
| |
| m_commandBuffer->begin(); |
| // No VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR was in the device create info pNext chain |
| { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirect2KHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, |
| "VUID-vkCmdTraceRaysIndirect2KHR-rayTracingPipelineTraceRaysIndirect2-03637"); |
| vk::CmdTraceRaysIndirect2KHR(m_commandBuffer->handle(), device_address); |
| m_errorMonitor->VerifyFound(); |
| } |
| m_commandBuffer->end(); |
| } |
| |
| TEST_F(NegativeRayTracing, CmdTraceRaysIndirect2KHRAddress) { |
| TEST_DESCRIPTION("Validate vkCmdTraceRaysIndirect2KHR."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME); |
| VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR maintenance1_features = vku::InitStructHelper(); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(&maintenance1_features); |
| VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(&bda_features); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true, &features2)) |
| if (maintenance1_features.rayTracingPipelineTraceRaysIndirect2 == VK_FALSE) { |
| GTEST_SKIP() << "rayTracingPipelineTraceRaysIndirect2 not supported"; |
| } |
| |
| RETURN_IF_SKIP(InitState(nullptr, &features2)) |
| |
| VkBufferCreateInfo buffer_info = vku::InitStructHelper(); |
| buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| buffer_info.size = 4096; |
| buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper(); |
| allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT; |
| vkt::Buffer buffer(*m_device, buffer_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocate_flag_info); |
| |
| const VkDeviceAddress device_address = buffer.address(); |
| |
| m_commandBuffer->begin(); |
| // indirectDeviceAddress is not a multiple of 4 |
| { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirect2KHR-None-08606"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdTraceRaysIndirect2KHR-indirectDeviceAddress-03634"); |
| vk::CmdTraceRaysIndirect2KHR(m_commandBuffer->handle(), device_address + 1); |
| m_errorMonitor->VerifyFound(); |
| } |
| m_commandBuffer->end(); |
| } |
| |
| TEST_F(NegativeRayTracing, AccelerationStructureVersionInfoKHR) { |
| TEST_DESCRIPTION("Validate VkAccelerationStructureVersionInfoKHR."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true)) |
| |
| VkPhysicalDeviceRayTracingPipelineFeaturesKHR ray_tracing_features = vku::InitStructHelper(); |
| GetPhysicalDeviceFeatures2(ray_tracing_features); |
| if (ray_tracing_features.rayTracingPipeline == VK_FALSE) { |
| GTEST_SKIP() << "rayTracing not supported"; |
| } |
| RETURN_IF_SKIP(InitState(nullptr, &ray_tracing_features)); |
| |
| VkAccelerationStructureVersionInfoKHR valid_version = vku::InitStructHelper(); |
| VkAccelerationStructureCompatibilityKHR compatablity; |
| uint8_t mode[] = {VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR, VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR}; |
| valid_version.pVersionData = mode; |
| { |
| VkAccelerationStructureVersionInfoKHR invalid_version = valid_version; |
| invalid_version.sType = VK_STRUCTURE_TYPE_MAX_ENUM; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureVersionInfoKHR-sType-sType"); |
| vk::GetDeviceAccelerationStructureCompatibilityKHR(device(), &invalid_version, &compatablity); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| { |
| VkAccelerationStructureVersionInfoKHR invalid_version = valid_version; |
| invalid_version.pVersionData = NULL; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureVersionInfoKHR-pVersionData-parameter"); |
| vk::GetDeviceAccelerationStructureCompatibilityKHR(device(), &invalid_version, &compatablity); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeRayTracing, CmdBuildAccelerationStructuresKHR) { |
| TEST_DESCRIPTION("Validate acceleration structure building."); |
| |
| AddOptionalExtensions(VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR accel_features = vku::InitStructHelper(); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(&accel_features); |
| VkPhysicalDeviceRayQueryFeaturesKHR ray_query_features = vku::InitStructHelper(&bda_features); |
| ray_query_features.rayQuery = VK_TRUE; |
| accel_features.accelerationStructureIndirectBuild = VK_TRUE; |
| accel_features.accelerationStructureHostCommands = VK_TRUE; |
| bda_features.bufferDeviceAddress = VK_TRUE; |
| |
| VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(&ray_query_features); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true, &features2)) |
| RETURN_IF_SKIP(InitState(nullptr, &features2, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); |
| |
| const bool index_type_uint8 = IsExtensionsEnabled(VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME); |
| |
| VkPhysicalDeviceAccelerationStructurePropertiesKHR acc_struct_properties = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(acc_struct_properties); |
| |
| // Command buffer not in recording mode |
| { |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-commandBuffer-recording"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // dstAccelerationStructure == VK_NULL_HANDLE |
| { |
| // Command buffer build |
| { |
| auto build_info_null_dst = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info_null_dst.SetDstAS(vkt::as::blueprint::AccelStructNull()); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, |
| "VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03800"); |
| build_info_null_dst.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Command buffer indirect build |
| if (accel_features.accelerationStructureIndirectBuild == VK_TRUE) { |
| auto build_info_null_dst = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info_null_dst.SetDstAS(vkt::as::blueprint::AccelStructNull()); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, |
| "VUID-vkCmdBuildAccelerationStructuresIndirectKHR-dstAccelerationStructure-03800"); |
| build_info_null_dst.BuildCmdBufferIndirect(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Host build |
| if (accel_features.accelerationStructureHostCommands == VK_TRUE) { |
| auto build_info_null_dst = vkt::as::blueprint::BuildGeometryInfoSimpleOnHostBottomLevel(*m_device); |
| build_info_null_dst.SetDstAS(vkt::as::blueprint::AccelStructNull()); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkBuildAccelerationStructuresKHR-dstAccelerationStructure-03800"); |
| build_info_null_dst.BuildHost(instance(), *m_device); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // Positive build tests |
| { |
| m_commandBuffer->begin(); |
| auto build_info_ppGeometries = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info_ppGeometries.BuildCmdBuffer(*m_device, m_commandBuffer->handle(), true); |
| m_commandBuffer->end(); |
| } |
| |
| { |
| m_commandBuffer->begin(); |
| auto build_info_pGeometries = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info_pGeometries.BuildCmdBuffer(*m_device, m_commandBuffer->handle(), false); |
| m_commandBuffer->end(); |
| } |
| |
| m_commandBuffer->begin(); |
| |
| // Invalid info count |
| { |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.SetInfoCount(0); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-infoCount-arraylength"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-infoCount-arraylength"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Invalid pInfos |
| { |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.SetNullInfos(true); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-pInfos-parameter"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Invalid ppBuildRangeInfos |
| { |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.SetNullBuildRangeInfos(true); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-ppBuildRangeInfos-parameter"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // must be called outside renderpass |
| { |
| InitRenderTarget(); |
| m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-renderpass"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_commandBuffer->EndRenderPass(); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid flags |
| { |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.SetFlags(VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_KHR); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureBuildGeometryInfoKHR-flags-parameter"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureBuildGeometryInfoKHR-flags-parameter"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Invalid dst buffer |
| { |
| auto buffer_ci = |
| vkt::Buffer::create_info(4096, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | |
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR); |
| vkt::Buffer invalid_buffer; |
| invalid_buffer.init_no_mem(*m_device, buffer_ci); |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.GetDstAS()->SetDeviceBuffer(std::move(invalid_buffer)); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-pInfos-03707"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid sType |
| { |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.GetInfo().sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureBuildGeometryInfoKHR-sType-sType"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureBuildGeometryInfoKHR-sType-sType"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid Type |
| { |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.SetType(VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03654"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03654"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| |
| build_info.SetType(VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-parameter"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-parameter"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Total number of triangles in all geometries superior to VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxPrimitiveCount |
| { |
| constexpr auto primitive_count = vvl::kU32Max; |
| // Check that primitive count is indeed superior to limit |
| if (primitive_count > acc_struct_properties.maxPrimitiveCount) { |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.GetGeometries()[0].SetPrimitiveCount(primitive_count); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03795"); |
| build_info.GetSizeInfo(m_device->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| // Total number of AABBs in all geometries superior to VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxPrimitiveCount |
| { |
| constexpr auto primitive_count = vvl::kU32Max; |
| // Check that primitive count is indeed superior to limit |
| if (primitive_count > acc_struct_properties.maxPrimitiveCount) { |
| auto build_info = |
| vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device, vkt::as::GeometryKHR::Type::AABB); |
| build_info.GetGeometries()[0].SetPrimitiveCount(primitive_count); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03794"); |
| build_info.GetSizeInfo(m_device->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| // Invalid stride in pGeometry.geometry.aabbs (not a multiple of 8) |
| { |
| auto build_info = |
| vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device, vkt::as::GeometryKHR::Type::AABB); |
| build_info.GetGeometries()[0].SetStride(1); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureGeometryAabbsDataKHR-stride-03545"); |
| build_info.GetSizeInfo(m_device->handle(), false); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid stride in ppGeometry.geometry.aabbs (not a multiple of 8) |
| { |
| auto build_info = |
| vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device, vkt::as::GeometryKHR::Type::AABB); |
| build_info.GetGeometries()[0].SetStride(1); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureGeometryAabbsDataKHR-stride-03545"); |
| build_info.GetSizeInfo(m_device->handle(), true); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid stride in pGeometry.geometry.aabbs (superior to UINT32_MAX) |
| { |
| auto build_info = |
| vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device, vkt::as::GeometryKHR::Type::AABB); |
| build_info.GetGeometries()[0].SetStride(8ull * vvl::kU32Max); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureGeometryAabbsDataKHR-stride-03820"); |
| build_info.GetSizeInfo(m_device->handle(), false); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid stride in ppGeometry.geometry.aabbs (superior to UINT32_MAX) |
| { |
| auto build_info = |
| vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device, vkt::as::GeometryKHR::Type::AABB); |
| build_info.GetGeometries()[0].SetStride(8ull * vvl::kU32Max); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureGeometryAabbsDataKHR-stride-03820"); |
| build_info.GetSizeInfo(m_device->handle(), true); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid vertex stride |
| { |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.GetGeometries()[0].SetStride(VkDeviceSize(vvl::kU32Max) + 1); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureGeometryTrianglesDataKHR-vertexStride-03819"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureGeometryTrianglesDataKHR-vertexStride-03819"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid index type |
| if (index_type_uint8) { |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.GetGeometries()[0].SetTrianglesIndexType(VK_INDEX_TYPE_UINT8_EXT); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureGeometryTrianglesDataKHR-indexType-03798"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureGeometryTrianglesDataKHR-indexType-03798"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| // ppGeometries and pGeometries both valid pointer |
| { |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| std::vector<VkAccelerationStructureGeometryKHR> geometries; |
| for (const auto &geometry : build_info.GetGeometries()) { |
| geometries.emplace_back(geometry.GetVkObj()); |
| } |
| build_info.GetInfo().pGeometries = geometries.data(); // .ppGeometries is set in .BuildCmdBuffer() |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureBuildGeometryInfoKHR-pGeometries-03788"); |
| // computed scratch buffer size will be 0 since vkGetAccelerationStructureBuildSizesKHR fails |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-pInfos-03802"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Buffer is missing VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR usage flag |
| { |
| VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper(); |
| alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; |
| vkt::Buffer bad_usage_buffer(*m_device, 1024, |
| VK_BUFFER_USAGE_RAY_TRACING_BIT_NV | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &alloc_flags); |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.GetGeometries()[0].SetTrianglesDeviceVertexBuffer(std::move(bad_usage_buffer), 3); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-geometry-03673"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Scratch data buffer is missing VK_BUFFER_USAGE_STORAGE_BUFFER_BIT usage flag |
| { |
| VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper(); |
| alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; |
| auto bad_scratch = std::make_shared<vkt::Buffer>(*m_device, 4096, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, |
| VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &alloc_flags); |
| |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.SetScratchBuffer(std::move(bad_scratch)); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-pInfos-03674"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Scratch data buffer is 0 |
| { |
| VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper(); |
| alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; |
| // no VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT => scratch address will be set to 0 |
| auto bad_scratch = std::make_shared<vkt::Buffer>(*m_device, 4096, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, |
| VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &alloc_flags); |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.SetScratchBuffer(std::move(bad_scratch)); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-pInfos-03802"); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| m_commandBuffer->end(); |
| } |
| |
| // https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/6040 |
| TEST_F(NegativeRayTracing, DISABLED_AccelerationStructuresOverlappingMemory) { |
| TEST_DESCRIPTION( |
| "Validate acceleration structure building when source/destination acceleration structures and scratch buffers overlap."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR accel_features = vku::InitStructHelper(); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(&accel_features); |
| VkPhysicalDeviceRayQueryFeaturesKHR ray_query_features = vku::InitStructHelper(&bda_features); |
| accel_features.accelerationStructure = VK_TRUE; |
| bda_features.bufferDeviceAddress = VK_TRUE; |
| ray_query_features.rayQuery = VK_TRUE; |
| |
| VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(&ray_query_features); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true, &features2)) |
| RETURN_IF_SKIP(InitState(nullptr, &features2, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); |
| |
| constexpr size_t build_info_count = 3; |
| |
| // All buffers used to back source/destination acceleration struct and scratch will be bound to this memory chunk |
| VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper(); |
| alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(&alloc_flags); |
| alloc_info.allocationSize = 8192; |
| vkt::DeviceMemory buffer_memory(*m_device, alloc_info); |
| |
| // Test overlapping scratch buffers |
| { |
| VkBufferCreateInfo scratch_buffer_ci = vku::InitStructHelper(); |
| scratch_buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| scratch_buffer_ci.size = 4096; |
| scratch_buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | |
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| |
| std::vector<std::shared_ptr<vkt::Buffer>> scratch_buffers(build_info_count); |
| std::vector<vkt::as::BuildGeometryInfoKHR> build_infos; |
| for (auto &scratch_buffer : scratch_buffers) { |
| scratch_buffer = std::make_shared<vkt::Buffer>(); |
| scratch_buffer->init_no_mem(*m_device, scratch_buffer_ci); |
| vk::BindBufferMemory(m_device->device(), scratch_buffer->handle(), buffer_memory.handle(), 0); |
| |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.SetScratchBuffer(std::move(scratch_buffer)); |
| build_infos.emplace_back(std::move(build_info)); |
| } |
| |
| // Since all the scratch buffers are bound to the same memory, 03704 will be triggered for each pair of elements in |
| // `build_infos` |
| for (size_t i = 0; i < binom<size_t>(build_info_count, 2); ++i) { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03704"); |
| } |
| m_commandBuffer->begin(); |
| vkt::as::BuildAccelerationStructuresKHR(*m_device, m_commandBuffer->handle(), build_infos); |
| m_commandBuffer->end(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Test overlapping destination acceleration structures |
| { |
| VkBufferCreateInfo dst_blas_buffer_ci = vku::InitStructHelper(); |
| dst_blas_buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| dst_blas_buffer_ci.size = 4096; |
| dst_blas_buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | |
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | |
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| std::vector<vkt::Buffer> dst_blas_buffers(build_info_count); |
| std::vector<vkt::as::BuildGeometryInfoKHR> build_infos; |
| for (auto &dst_blas_buffer : dst_blas_buffers) { |
| dst_blas_buffer.init_no_mem(*m_device, dst_blas_buffer_ci); |
| vk::BindBufferMemory(m_device->device(), dst_blas_buffer.handle(), buffer_memory.handle(), 0); |
| |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.GetDstAS()->SetDeviceBuffer(std::move(dst_blas_buffer)); |
| build_infos.emplace_back(std::move(build_info)); |
| } |
| |
| // Since all the destination acceleration structures are bound to the same memory, 03702 will be triggered for each pair of |
| // elements in `build_infos` |
| for (size_t i = 0; i < binom<size_t>(build_info_count, 2); ++i) { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, |
| "VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03702"); |
| } |
| m_commandBuffer->begin(); |
| vkt::as::BuildAccelerationStructuresKHR(*m_device, m_commandBuffer->handle(), build_infos); |
| m_commandBuffer->end(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Test overlapping destination acceleration structure and scratch buffer |
| { |
| VkBufferCreateInfo dst_blas_buffer_ci = vku::InitStructHelper(); |
| dst_blas_buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| dst_blas_buffer_ci.size = 4096; |
| dst_blas_buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | |
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | |
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| VkBufferCreateInfo scratch_buffer_ci = vku::InitStructHelper(); |
| scratch_buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| scratch_buffer_ci.size = 4096; |
| scratch_buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | |
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| |
| std::vector<vkt::Buffer> dst_blas_buffers(build_info_count); |
| std::vector<std::shared_ptr<vkt::Buffer>> scratch_buffers(build_info_count); |
| std::vector<vkt::as::BuildGeometryInfoKHR> build_infos; |
| for (size_t i = 0; i < build_info_count; ++i) { |
| dst_blas_buffers[i].init_no_mem(*m_device, dst_blas_buffer_ci); |
| vk::BindBufferMemory(m_device->device(), dst_blas_buffers[i].handle(), buffer_memory.handle(), 0); |
| scratch_buffers[i] = std::make_shared<vkt::Buffer>(); |
| scratch_buffers[i]->init_no_mem(*m_device, scratch_buffer_ci); |
| vk::BindBufferMemory(m_device->device(), scratch_buffers[i]->handle(), buffer_memory.handle(), 0); |
| |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.GetDstAS()->SetDeviceBuffer(std::move(dst_blas_buffers[i])); |
| build_info.GetDstAS()->SetSize(4096); |
| build_info.SetScratchBuffer(std::move(scratch_buffers[i])); |
| build_infos.emplace_back(std::move(build_info)); |
| } |
| |
| // Since all the destination acceleration structures and scratch buffers are bound to the same memory, 03702, 03703 and |
| // 03704 will be triggered for each pair of elements in `build_infos`. 03703 will also be triggered for individual elements. |
| for (size_t i = 0; i < binom<size_t>(build_info_count, 2); ++i) { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, |
| "VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03702"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, |
| "VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03703"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03704"); |
| } |
| for (size_t i = 0; i < build_info_count; ++i) { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, |
| "VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03703"); |
| } |
| m_commandBuffer->begin(); |
| vkt::as::BuildAccelerationStructuresKHR(*m_device, m_commandBuffer->handle(), build_infos); |
| m_commandBuffer->end(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Test overlapping source acceleration structure and destination acceleration structures |
| { |
| VkBufferCreateInfo blas_buffer_ci = vku::InitStructHelper(); |
| blas_buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| blas_buffer_ci.size = 4096; |
| blas_buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | |
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| std::vector<vkt::Buffer> src_blas_buffers(build_info_count); |
| std::vector<vkt::Buffer> dst_blas_buffers(build_info_count); |
| std::vector<vkt::as::BuildGeometryInfoKHR> build_infos; |
| for (size_t i = 0; i < build_info_count; ++i) { |
| src_blas_buffers[i].init_no_mem(*m_device, blas_buffer_ci); |
| vk::BindBufferMemory(m_device->device(), src_blas_buffers[i].handle(), buffer_memory.handle(), 0); |
| |
| dst_blas_buffers[i].init_no_mem(*m_device, blas_buffer_ci); |
| vk::BindBufferMemory(m_device->device(), dst_blas_buffers[i].handle(), buffer_memory.handle(), 0); |
| |
| // 1st step: build destination acceleration struct |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.GetDstAS()->SetDeviceBuffer(std::move(src_blas_buffers[i])); |
| build_info.GetDstAS()->SetSize(4096); |
| build_info.AddFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR); |
| m_commandBuffer->begin(); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_commandBuffer->end(); |
| |
| // Possible 2nd step: insert memory barrier on acceleration structure buffer |
| // => no need here since 2nd build call will not be executed by the driver |
| |
| // 3rd step: set destination acceleration struct as source, create new destination acceleration struct with its |
| // underlying buffer bound to the same memory as the source acceleration struct, and build using update mode to trigger |
| // 03701 |
| build_info.SetSrcAS(build_info.GetDstAS()); |
| build_info.SetMode(VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR); |
| build_info.SetDstAS(vkt::as::blueprint::AccelStructSimpleOnDeviceBottomLevel(4096)); |
| build_info.GetDstAS()->SetDeviceBuffer(std::move(dst_blas_buffers[i])); |
| build_infos.emplace_back(std::move(build_info)); |
| } |
| |
| // Since all the source and destination acceleration structures are bound to the same memory, 03701 and 03702 will be |
| // triggered for each pair of elements in `build_infos` |
| for (size_t i = 0; i < binom<size_t>(build_info_count, 2); ++i) { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, |
| "VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03701"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, |
| "VUID-vkCmdBuildAccelerationStructuresKHR-dstAccelerationStructure-03702"); |
| } |
| m_commandBuffer->begin(); |
| vkt::as::BuildAccelerationStructuresKHR(*m_device, m_commandBuffer->handle(), build_infos); |
| m_commandBuffer->end(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Test overlapping source acceleration structure and scratch buffer |
| { |
| VkBufferCreateInfo blas_buffer_ci = vku::InitStructHelper(); |
| blas_buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| blas_buffer_ci.size = 4096; |
| blas_buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | |
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| VkBufferCreateInfo scratch_buffer_ci = vku::InitStructHelper(); |
| scratch_buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| scratch_buffer_ci.size = 4096; |
| scratch_buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | |
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| |
| std::vector<vkt::Buffer> src_blas_buffers(build_info_count); |
| std::vector<std::shared_ptr<vkt::Buffer>> scratch_buffers(build_info_count); |
| std::vector<vkt::as::BuildGeometryInfoKHR> build_infos; |
| for (size_t i = 0; i < build_info_count; ++i) { |
| src_blas_buffers[i].init_no_mem(*m_device, blas_buffer_ci); |
| vk::BindBufferMemory(m_device->device(), src_blas_buffers[i].handle(), buffer_memory.handle(), 0); |
| |
| scratch_buffers[i] = std::make_shared<vkt::Buffer>(); |
| scratch_buffers[i]->init_no_mem(*m_device, scratch_buffer_ci); |
| vk::BindBufferMemory(m_device->device(), scratch_buffers[i]->handle(), buffer_memory.handle(), 0); |
| |
| // 1st step: build destination acceleration struct |
| auto build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_info.GetDstAS()->SetDeviceBuffer(std::move(src_blas_buffers[i])); |
| build_info.GetDstAS()->SetSize(4096); // Do this to ensure dst accel struct buffer and scratch do overlap |
| build_info.AddFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR); |
| m_commandBuffer->begin(); |
| build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_commandBuffer->end(); |
| |
| // Possible 2nd step: insert memory barrier on acceleration structure buffer |
| // => no need here since 2nd build call will not be executed by the driver |
| |
| // 3rd step: set destination acceleration struct as source, create new destination acceleration struct, |
| // bound scratch buffer to the same memory as the source acceleration struct, and build using update mode to trigger |
| // 03705 |
| build_info.SetSrcAS(build_info.GetDstAS()); |
| build_info.SetMode(VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR); |
| build_info.SetDstAS(vkt::as::blueprint::AccelStructSimpleOnDeviceBottomLevel(4096)); |
| build_info.SetScratchBuffer(std::move(scratch_buffers[i])); |
| build_infos.emplace_back(std::move(build_info)); |
| } |
| |
| // Since all the source and destination acceleration structures are bound to the same memory, 03701 and 03702 will be |
| // triggered for each pair of elements in `build_infos`. 03705 will also be triggered for individual elements. |
| for (size_t i = 0; i < binom<size_t>(build_info_count, 2); ++i) { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03704"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03705"); |
| } |
| for (size_t i = 0; i < build_info_count; ++i) { |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-scratchData-03705"); |
| } |
| |
| m_commandBuffer->begin(); |
| vkt::as::BuildAccelerationStructuresKHR(*m_device, m_commandBuffer->handle(), build_infos); |
| m_commandBuffer->end(); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeRayTracing, ObjInUseCmdBuildAccelerationStructureKHR) { |
| TEST_DESCRIPTION("Validate acceleration structure building tracks the objects used."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| VkPhysicalDeviceRayTracingPipelineFeaturesKHR ray_tracing_features = vku::InitStructHelper(); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR accel_features = vku::InitStructHelper(&ray_tracing_features); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(&accel_features); |
| VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(&bda_features); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true, &features2)) |
| RETURN_IF_SKIP(InitState(nullptr, &features2)) |
| |
| vkt::as::BuildGeometryInfoKHR build_geometry_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| m_commandBuffer->begin(); |
| build_geometry_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_commandBuffer->end(); |
| |
| VkSubmitInfo submit_info = vku::InitStructHelper(); |
| submit_info.commandBufferCount = 1; |
| submit_info.pCommandBuffers = &m_commandBuffer->handle(); |
| vk::QueueSubmit(m_default_queue, 1, &submit_info, VK_NULL_HANDLE); |
| |
| // This test used to destroy buffers used for building the acceleration structure, |
| // to see if there life span was correctly tracked. |
| // Following issue 6461, buffers associated to a device address are not tracked anymore, as it is impossible |
| // to track the "correct" one: there is not a 1 to 1 mapping between a buffer and a device address. |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkDestroyAccelerationStructureKHR-accelerationStructure-02442"); |
| vk::DestroyAccelerationStructureKHR(m_device->handle(), build_geometry_info.GetDstAS()->handle(), nullptr); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::QueueWaitIdle(m_default_queue); |
| } |
| |
| TEST_F(NegativeRayTracing, CmdCopyAccelerationStructureToMemoryKHR) { |
| TEST_DESCRIPTION("Validate CmdCopyAccelerationStructureToMemoryKHR."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true)) |
| |
| VkPhysicalDeviceRayTracingPipelineFeaturesKHR ray_tracing_features = vku::InitStructHelper(); |
| VkPhysicalDeviceRayQueryFeaturesKHR ray_query_features = vku::InitStructHelper(&ray_tracing_features); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR acc_struct_features = vku::InitStructHelper(&ray_query_features); |
| GetPhysicalDeviceFeatures2(acc_struct_features); |
| RETURN_IF_SKIP(InitState(nullptr, &acc_struct_features)); |
| |
| constexpr VkDeviceSize buffer_size = 4096; |
| VkBufferCreateInfo buffer_ci = vku::InitStructHelper(); |
| buffer_ci.size = buffer_size; |
| buffer_ci.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR; |
| buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| vkt::Buffer buffer; |
| buffer.init_no_mem(*m_device, buffer_ci); |
| |
| VkAccelerationStructureCreateInfoKHR as_create_info = vku::InitStructHelper(); |
| as_create_info.pNext = NULL; |
| as_create_info.buffer = buffer.handle(); |
| as_create_info.createFlags = 0; |
| as_create_info.offset = 0; |
| as_create_info.size = 0; |
| as_create_info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; |
| as_create_info.deviceAddress = 0; |
| |
| VkAccelerationStructureKHR as; |
| vk::CreateAccelerationStructureKHR(device(), &as_create_info, nullptr, &as); |
| |
| constexpr intptr_t alignment_padding = 256 - 1; |
| int8_t output[buffer_size + alignment_padding]; |
| VkDeviceOrHostAddressKHR output_data; |
| output_data.hostAddress = reinterpret_cast<void *>(((intptr_t)output + alignment_padding) & ~alignment_padding); |
| VkCopyAccelerationStructureToMemoryInfoKHR copy_info = vku::InitStructHelper(); |
| copy_info.src = as; |
| copy_info.dst = output_data; |
| copy_info.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR; |
| vkt::CommandBuffer cb(m_device, m_commandPool); |
| cb.begin(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureToMemoryKHR-None-03559"); |
| vk::CmdCopyAccelerationStructureToMemoryKHR(cb.handle(), ©_info); |
| m_errorMonitor->VerifyFound(); |
| |
| cb.end(); |
| |
| vk::DestroyAccelerationStructureKHR(device(), as, nullptr); |
| } |
| |
| TEST_F(NegativeRayTracing, UpdateAccelerationStructureKHR) { |
| TEST_DESCRIPTION("Test for updating an acceleration structure without a srcAccelerationStructure"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true)) |
| |
| VkPhysicalDeviceRayTracingPipelineFeaturesKHR ray_tracing_features = vku::InitStructHelper(); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_address_features = vku::InitStructHelper(&ray_tracing_features); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR acc_structure_features = vku::InitStructHelper(&buffer_address_features); |
| GetPhysicalDeviceFeatures2(acc_structure_features); |
| RETURN_IF_SKIP(InitState(nullptr, &acc_structure_features)); |
| |
| m_commandBuffer->begin(); |
| |
| vkt::as::BuildGeometryInfoKHR build_geometry_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| build_geometry_info.SetMode(VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR); |
| // computed scratch buffer size is empty, so scratch buffer address can be 0 and invalid |
| m_errorMonitor->SetUnexpectedError("VUID-vkCmdBuildAccelerationStructuresKHR-pInfos-03802"); |
| // Update acceleration structure, with .srcAccelerationStructure == VK_NULL_HANDLE |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-pInfos-04630"); |
| build_geometry_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_errorMonitor->VerifyFound(); |
| |
| m_commandBuffer->end(); |
| } |
| |
| TEST_F(NegativeRayTracing, BuffersAndBufferDeviceAddressesMapping) { |
| TEST_DESCRIPTION( |
| "Test that buffers and buffer device addresses mapping is correctly handled." |
| "Bound multiple buffers to the same memory so that they have the same buffer device address." |
| "Some buffers are valid for use in vkCmdBuildAccelerationStructuresKHR, others are not." |
| "Using buffer device addresses obtained from invalid buffers will result in a valid call to " |
| "vkCmdBuildAccelerationStructuresKHR," |
| "because for this call to be valid, at least one buffer retrieved from the buffer device addresses must be valid." |
| "Valid and invalid buffers having the same address, the call is valid." |
| "Removing those valid buffers should cause calls to vkCmdBuildAccelerationStructuresKHR to be invalid," |
| "as long as valid buffers are correctly removed from the internal buffer device addresses to buffers mapping."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR accel_features = vku::InitStructHelper(); |
| VkPhysicalDeviceRayTracingPipelineFeaturesKHR ray_tracing_features = vku::InitStructHelper(&accel_features); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_addr_features = vku::InitStructHelper(&ray_tracing_features); |
| VkPhysicalDeviceFeatures2KHR features2 = vku::InitStructHelper(&buffer_addr_features); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, true, &features2)) |
| RETURN_IF_SKIP(InitState(nullptr, &features2, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); |
| |
| // Allocate common buffer memory |
| VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper(); |
| alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(&alloc_flags); |
| alloc_info.allocationSize = 4096; |
| vkt::DeviceMemory buffer_memory(*m_device, alloc_info); |
| |
| // Create buffers, with correct and incorrect usage |
| constexpr size_t N = 3; |
| std::array<std::unique_ptr<vkt::as::BuildGeometryInfoKHR>, N> build_geometry_info_vec{}; |
| const VkBufferUsageFlags good_buffer_usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | |
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | |
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| const VkBufferUsageFlags bad_buffer_usage = |
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; |
| |
| VkBufferCreateInfo buffer_ci = vku::InitStructHelper(); |
| buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| buffer_ci.size = 4096; |
| buffer_ci.usage = good_buffer_usage; |
| for (size_t i = 0; i < N; ++i) { |
| if (i > 0) { |
| buffer_ci.usage = bad_buffer_usage; |
| } |
| |
| vkt::Buffer vbo; |
| vbo.init_no_mem(*m_device, buffer_ci); |
| vk::BindBufferMemory(device(), vbo.handle(), buffer_memory.handle(), 0); |
| |
| vkt::Buffer ibo; |
| ibo.init_no_mem(*m_device, buffer_ci); |
| vk::BindBufferMemory(device(), ibo.handle(), buffer_memory.handle(), 0); |
| |
| // Those calls to vkGetBufferDeviceAddressKHR will internally record vbo and ibo device addresses |
| { |
| const VkDeviceAddress vbo_address = vbo.address(); |
| const VkDeviceAddress ibo_address = ibo.address(); |
| if (vbo_address != ibo_address) { |
| GTEST_SKIP() |
| << "Bounding two buffers to the same memory location does not result in identical buffer device addresses"; |
| } |
| } |
| build_geometry_info_vec[i] = std::make_unique<vkt::as::BuildGeometryInfoKHR>( |
| vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device)); |
| build_geometry_info_vec[i]->GetGeometries()[0].SetTrianglesDeviceVertexBuffer(std::move(vbo), 2); |
| build_geometry_info_vec[i]->GetGeometries()[0].SetTrianglesDeviceIndexBuffer(std::move(ibo)); |
| } |
| |
| // The first series of calls to vkCmdBuildAccelerationStructuresKHR should succeed, |
| // since the first vbo and ibo do have the VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR flag. |
| // After deleting the valid vbo and ibo, calls are expected to fail. |
| |
| for (size_t i = 0; i < N; ++i) { |
| m_commandBuffer->begin(); |
| build_geometry_info_vec[i]->BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_commandBuffer->end(); |
| } |
| |
| for (size_t i = 0; i < N; ++i) { |
| m_commandBuffer->begin(); |
| if (i > 0) { |
| // for vbo |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-geometry-03673"); |
| // for ibo |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructuresKHR-geometry-03673"); |
| } |
| build_geometry_info_vec[i]->VkCmdBuildAccelerationStructuresKHR(*m_device, m_commandBuffer->handle()); |
| if (i > 0) { |
| m_errorMonitor->VerifyFound(); |
| } |
| m_commandBuffer->end(); |
| |
| build_geometry_info_vec[i] = nullptr; |
| } |
| } |
| |
| TEST_F(NegativeRayTracing, WriteAccelerationStructuresProperties) { |
| TEST_DESCRIPTION("Test queryType validation in vkCmdWriteAccelerationStructuresPropertiesKHR"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_RAY_QUERY_EXTENSION_NAME); |
| AddOptionalExtensions(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME); |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR accel_features = vku::InitStructHelper(); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(&accel_features); |
| VkPhysicalDeviceRayQueryFeaturesKHR ray_query_features = vku::InitStructHelper(&bda_features); |
| RETURN_IF_SKIP(InitFramework()) |
| |
| GetPhysicalDeviceFeatures2(ray_query_features); |
| RETURN_IF_SKIP(InitState(nullptr, &ray_query_features, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); |
| const bool rt_maintenance_1 = IsExtensionsEnabled(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME); |
| // On host query with invalid query type |
| if (accel_features.accelerationStructureHostCommands == VK_TRUE) { |
| vkt::as::BuildGeometryInfoKHR as_build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| as_build_info.GetDstAS()->SetDeviceBufferMemoryPropertyFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); |
| as_build_info.SetFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR); |
| |
| VkQueryPoolCreateInfo query_pool_ci = vku::InitStructHelper(); |
| query_pool_ci.queryCount = 1; |
| |
| query_pool_ci.queryType = VK_QUERY_TYPE_OCCLUSION; |
| vkt::QueryPool query_pool(*m_device, query_pool_ci); |
| ASSERT_TRUE(query_pool.initialized()); |
| |
| m_commandBuffer->begin(); |
| as_build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_commandBuffer->end(); |
| |
| constexpr size_t stride = 1; |
| constexpr size_t data_size = sizeof(uint32_t) * stride; |
| uint8_t data[data_size]; |
| // Incorrect query type |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkWriteAccelerationStructuresPropertiesKHR-queryType-06742"); |
| vk::WriteAccelerationStructuresPropertiesKHR(m_device->handle(), 1, &as_build_info.GetDstAS()->handle(), |
| VK_QUERY_TYPE_OCCLUSION, data_size, data, stride); |
| m_errorMonitor->VerifyFound(); |
| |
| // query types not known without extension |
| if (rt_maintenance_1) { |
| // queryType is VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR, but stride is not a multiple of the size of VkDeviceSize |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkWriteAccelerationStructuresPropertiesKHR-queryType-06731"); |
| vk::WriteAccelerationStructuresPropertiesKHR(m_device->handle(), 1, &as_build_info.GetDstAS()->handle(), |
| VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR, data_size, data, stride); |
| m_errorMonitor->VerifyFound(); |
| |
| // queryType is VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR, but stride is not a |
| // multiple of the size of VkDeviceSize |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkWriteAccelerationStructuresPropertiesKHR-queryType-06733"); |
| vk::WriteAccelerationStructuresPropertiesKHR( |
| m_device->handle(), 1, &as_build_info.GetDstAS()->handle(), |
| VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR, data_size, data, stride); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // On device query with invalid query type |
| { |
| vkt::as::BuildGeometryInfoKHR as_build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| as_build_info.SetFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR); |
| |
| VkQueryPoolCreateInfo query_pool_ci = vku::InitStructHelper(); |
| query_pool_ci.queryCount = 1; |
| |
| query_pool_ci.queryType = VK_QUERY_TYPE_OCCLUSION; |
| vkt::QueryPool query_pool(*m_device, query_pool_ci); |
| ASSERT_TRUE(query_pool.initialized()); |
| |
| m_commandBuffer->begin(); |
| |
| as_build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| // Incorrect query type |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-queryType-06742"); |
| vk::CmdWriteAccelerationStructuresPropertiesKHR(m_commandBuffer->handle(), 1, &as_build_info.GetDstAS()->handle(), |
| VK_QUERY_TYPE_OCCLUSION, query_pool.handle(), 0); |
| m_errorMonitor->VerifyFound(); |
| m_commandBuffer->end(); |
| } |
| } |
| |
| TEST_F(NegativeRayTracing, WriteAccelerationStructuresPropertiesMaintenance1) { |
| TEST_DESCRIPTION("Test queryType validation in vkCmdWriteAccelerationStructuresPropertiesKHR"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_RAY_QUERY_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME); |
| |
| VkPhysicalDeviceAccelerationStructureFeaturesKHR accel_features = vku::InitStructHelper(); |
| VkPhysicalDeviceBufferDeviceAddressFeaturesKHR bda_features = vku::InitStructHelper(&accel_features); |
| VkPhysicalDeviceRayQueryFeaturesKHR ray_query_features = vku::InitStructHelper(&bda_features); |
| VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR ray_tracing_maintenance1 = vku::InitStructHelper(&ray_query_features); |
| |
| RETURN_IF_SKIP(InitFramework()) |
| |
| GetPhysicalDeviceFeatures2(ray_tracing_maintenance1); |
| RETURN_IF_SKIP(InitState(nullptr, &ray_tracing_maintenance1, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); |
| |
| // On host query with invalid query type |
| if (accel_features.accelerationStructureHostCommands == VK_TRUE) { |
| vkt::as::BuildGeometryInfoKHR blas_build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas_build_info.GetDstAS()->SetDeviceBufferMemoryPropertyFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); |
| blas_build_info.SetFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR); |
| |
| VkQueryPoolCreateInfo query_pool_ci = vku::InitStructHelper(); |
| query_pool_ci.queryCount = 1; |
| |
| query_pool_ci.queryType = VK_QUERY_TYPE_OCCLUSION; |
| vkt::QueryPool query_pool(*m_device, query_pool_ci); |
| ASSERT_TRUE(query_pool.initialized()); |
| |
| m_commandBuffer->begin(); |
| blas_build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_commandBuffer->end(); |
| |
| constexpr size_t stride = sizeof(VkDeviceSize); |
| constexpr size_t data_size = sizeof(VkDeviceSize) * stride; |
| uint8_t data[data_size]; |
| // Incorrect query type |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkWriteAccelerationStructuresPropertiesKHR-queryType-06742"); |
| vk::WriteAccelerationStructuresPropertiesKHR(m_device->handle(), 1, &blas_build_info.GetDstAS()->handle(), |
| VK_QUERY_TYPE_OCCLUSION, data_size, data, stride); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // On host query type with missing BLAS flag |
| if (accel_features.accelerationStructureHostCommands == VK_TRUE) { |
| vkt::as::BuildGeometryInfoKHR blas_build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas_build_info.GetDstAS()->SetDeviceBufferMemoryPropertyFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); |
| // missing flag |
| // blas_build_info.SetFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR); |
| |
| VkQueryPoolCreateInfo query_pool_ci = vku::InitStructHelper(); |
| query_pool_ci.queryCount = 1; |
| |
| query_pool_ci.queryType = VK_QUERY_TYPE_OCCLUSION; |
| vkt::QueryPool query_pool(*m_device, query_pool_ci); |
| ASSERT_TRUE(query_pool.initialized()); |
| |
| m_commandBuffer->begin(); |
| blas_build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_commandBuffer->end(); |
| |
| constexpr size_t stride = sizeof(VkDeviceSize); |
| constexpr size_t data_size = sizeof(VkDeviceSize) * stride; |
| uint8_t data[data_size]; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, |
| "VUID-vkWriteAccelerationStructuresPropertiesKHR-accelerationStructures-03431"); |
| vk::WriteAccelerationStructuresPropertiesKHR(m_device->handle(), 1, &blas_build_info.GetDstAS()->handle(), |
| VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, data_size, data, |
| stride); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // On host query type with invalid stride |
| if (accel_features.accelerationStructureHostCommands == VK_TRUE) { |
| vkt::as::BuildGeometryInfoKHR blas_build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas_build_info.GetDstAS()->SetDeviceBufferMemoryPropertyFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); |
| blas_build_info.SetFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR); |
| |
| VkQueryPoolCreateInfo query_pool_ci = vku::InitStructHelper(); |
| query_pool_ci.queryCount = 1; |
| |
| query_pool_ci.queryType = VK_QUERY_TYPE_OCCLUSION; |
| vkt::QueryPool query_pool(*m_device, query_pool_ci); |
| ASSERT_TRUE(query_pool.initialized()); |
| |
| m_commandBuffer->begin(); |
| blas_build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| m_commandBuffer->end(); |
| |
| constexpr size_t stride = 1; |
| constexpr size_t data_size = sizeof(VkDeviceSize) * stride; |
| uint8_t data[data_size]; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkWriteAccelerationStructuresPropertiesKHR-queryType-03448"); |
| vk::WriteAccelerationStructuresPropertiesKHR(m_device->handle(), 1, &blas_build_info.GetDstAS()->handle(), |
| VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, data_size, data, |
| stride); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkWriteAccelerationStructuresPropertiesKHR-queryType-03450"); |
| vk::WriteAccelerationStructuresPropertiesKHR(m_device->handle(), 1, &blas_build_info.GetDstAS()->handle(), |
| VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, data_size, data, |
| stride); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // On device query with invalid query type |
| { |
| vkt::as::BuildGeometryInfoKHR blas_build_info = vkt::as::blueprint::BuildGeometryInfoSimpleOnDeviceBottomLevel(*m_device); |
| blas_build_info.SetFlags(VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR); |
| |
| VkQueryPoolCreateInfo query_pool_ci = vku::InitStructHelper(); |
| query_pool_ci.queryCount = 1; |
| |
| query_pool_ci.queryType = VK_QUERY_TYPE_OCCLUSION; |
| vkt::QueryPool query_pool(*m_device, query_pool_ci); |
| ASSERT_TRUE(query_pool.initialized()); |
| |
| m_commandBuffer->begin(); |
| |
| blas_build_info.BuildCmdBuffer(*m_device, m_commandBuffer->handle()); |
| // Incorrect query type |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-queryType-06742"); |
| vk::CmdWriteAccelerationStructuresPropertiesKHR(m_commandBuffer->handle(), 1, &blas_build_info.GetDstAS()->handle(), |
| VK_QUERY_TYPE_OCCLUSION, query_pool.handle(), 0); |
| m_errorMonitor->VerifyFound(); |
| |
| m_commandBuffer->end(); |
| } |
| } |
| |
| TEST_F(NegativeRayTracingNV, AccelerationStructureBindings) { |
| TEST_DESCRIPTION("Use more bindings with a descriptorType of VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV than allowed"); |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, false)) |
| |
| VkPhysicalDeviceRayTracingPropertiesNV ray_tracing_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(ray_tracing_props); |
| |
| RETURN_IF_SKIP(InitState()) |
| |
| uint32_t maxBlocks = ray_tracing_props.maxDescriptorSetAccelerationStructures; |
| if (maxBlocks > 4096) { |
| GTEST_SKIP() << "Too large of a maximum number of descriptor set acceleration structures, skipping tests"; |
| } |
| if (maxBlocks < 1) { |
| GTEST_SKIP() << "Test requires maxDescriptorSetAccelerationStructures >= 1"; |
| } |
| |
| std::vector<VkDescriptorSetLayoutBinding> dslb_vec = {}; |
| VkDescriptorSetLayoutBinding dslb = {}; |
| dslb.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV; |
| dslb.descriptorCount = 1; |
| dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; |
| |
| for (uint32_t i = 0; i <= maxBlocks; ++i) { |
| dslb.binding = i; |
| dslb_vec.push_back(dslb); |
| } |
| |
| VkDescriptorSetLayoutCreateInfo ds_layout_ci = vku::InitStructHelper(); |
| ds_layout_ci.bindingCount = dslb_vec.size(); |
| ds_layout_ci.pBindings = dslb_vec.data(); |
| |
| vkt::DescriptorSetLayout ds_layout(*m_device, ds_layout_ci); |
| ASSERT_TRUE(ds_layout.initialized()); |
| |
| VkPipelineLayoutCreateInfo pipeline_layout_ci = vku::InitStructHelper(); |
| pipeline_layout_ci.setLayoutCount = 1; |
| pipeline_layout_ci.pSetLayouts = &ds_layout.handle(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkPipelineLayoutCreateInfo-descriptorType-02381"); |
| vkt::PipelineLayout pipeline_layout(*m_device, pipeline_layout_ci); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracingNV, ValidateGeometry) { |
| TEST_DESCRIPTION("Validate acceleration structure geometries."); |
| |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, false)) |
| RETURN_IF_SKIP(InitState()) |
| |
| vkt::Buffer vbo; |
| vbo.init(*m_device, 1024, VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); |
| |
| vkt::Buffer ibo; |
| ibo.init(*m_device, 1024, VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); |
| |
| vkt::Buffer tbo; |
| tbo.init(*m_device, 1024, VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); |
| |
| vkt::Buffer aabbbo; |
| aabbbo.init(*m_device, 1024, VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); |
| |
| VkBufferCreateInfo unbound_buffer_ci = vku::InitStructHelper(); |
| unbound_buffer_ci.size = 1024; |
| unbound_buffer_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV; |
| vkt::Buffer unbound_buffer; |
| unbound_buffer.init_no_mem(*m_device, unbound_buffer_ci); |
| |
| constexpr std::array vertices = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f}; |
| constexpr std::array<uint32_t, 3> indicies = {0, 1, 2}; |
| constexpr std::array aabbs = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f}; |
| constexpr std::array transforms = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; |
| |
| uint8_t *mapped_vbo_buffer_data = (uint8_t *)vbo.memory().map(); |
| std::memcpy(mapped_vbo_buffer_data, (uint8_t *)vertices.data(), sizeof(float) * vertices.size()); |
| vbo.memory().unmap(); |
| |
| uint8_t *mapped_ibo_buffer_data = (uint8_t *)ibo.memory().map(); |
| std::memcpy(mapped_ibo_buffer_data, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size()); |
| ibo.memory().unmap(); |
| |
| uint8_t *mapped_tbo_buffer_data = (uint8_t *)tbo.memory().map(); |
| std::memcpy(mapped_tbo_buffer_data, (uint8_t *)transforms.data(), sizeof(float) * transforms.size()); |
| tbo.memory().unmap(); |
| |
| uint8_t *mapped_aabbbo_buffer_data = (uint8_t *)aabbbo.memory().map(); |
| std::memcpy(mapped_aabbbo_buffer_data, (uint8_t *)aabbs.data(), sizeof(float) * aabbs.size()); |
| aabbbo.memory().unmap(); |
| |
| VkGeometryNV valid_geometry_triangles = vku::InitStructHelper(); |
| valid_geometry_triangles.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV; |
| valid_geometry_triangles.geometry.triangles = vku::InitStructHelper(); |
| valid_geometry_triangles.geometry.triangles.vertexData = vbo.handle(); |
| valid_geometry_triangles.geometry.triangles.vertexOffset = 0; |
| valid_geometry_triangles.geometry.triangles.vertexCount = 3; |
| valid_geometry_triangles.geometry.triangles.vertexStride = 12; |
| valid_geometry_triangles.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; |
| valid_geometry_triangles.geometry.triangles.indexData = ibo.handle(); |
| valid_geometry_triangles.geometry.triangles.indexOffset = 0; |
| valid_geometry_triangles.geometry.triangles.indexCount = 3; |
| valid_geometry_triangles.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; |
| valid_geometry_triangles.geometry.triangles.transformData = tbo.handle(); |
| valid_geometry_triangles.geometry.triangles.transformOffset = 0; |
| valid_geometry_triangles.geometry.aabbs = vku::InitStructHelper(); |
| |
| VkGeometryNV valid_geometry_aabbs = vku::InitStructHelper(); |
| valid_geometry_aabbs.geometryType = VK_GEOMETRY_TYPE_AABBS_NV; |
| valid_geometry_aabbs.geometry.triangles = vku::InitStructHelper(); |
| valid_geometry_aabbs.geometry.aabbs = vku::InitStructHelper(); |
| valid_geometry_aabbs.geometry.aabbs.aabbData = aabbbo.handle(); |
| valid_geometry_aabbs.geometry.aabbs.numAABBs = 1; |
| valid_geometry_aabbs.geometry.aabbs.offset = 0; |
| valid_geometry_aabbs.geometry.aabbs.stride = 24; |
| |
| const auto GetCreateInfo = [](const VkGeometryNV &geometry) { |
| VkAccelerationStructureCreateInfoNV as_create_info = vku::InitStructHelper(); |
| as_create_info.info = vku::InitStructHelper(); |
| as_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV; |
| as_create_info.info.instanceCount = 0; |
| as_create_info.info.geometryCount = 1; |
| as_create_info.info.pGeometries = &geometry; |
| return as_create_info; |
| }; |
| |
| VkAccelerationStructureNV as; |
| |
| // Invalid vertex format. |
| { |
| VkGeometryNV geometry = valid_geometry_triangles; |
| geometry.geometry.triangles.vertexFormat = VK_FORMAT_R64_UINT; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryTrianglesNV-vertexFormat-02430"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid vertex offset - not multiple of component size. |
| { |
| VkGeometryNV geometry = valid_geometry_triangles; |
| geometry.geometry.triangles.vertexOffset = 1; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryTrianglesNV-vertexOffset-02429"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid vertex offset - bigger than buffer. |
| { |
| VkGeometryNV geometry = valid_geometry_triangles; |
| geometry.geometry.triangles.vertexOffset = 12 * 1024; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryTrianglesNV-vertexOffset-02428"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid vertex buffer - no such buffer. |
| { |
| VkGeometryNV geometry = valid_geometry_triangles; |
| geometry.geometry.triangles.vertexData = VkBuffer(123456789); |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryTrianglesNV-vertexData-parameter"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| #if 0 |
| // XXX Subtest disabled because this is the wrong VUID. |
| // No VUIDs currently exist to require memory is bound (spec bug). |
| // Invalid vertex buffer - no memory bound. |
| { |
| VkGeometryNV geometry = valid_geometry_triangles; |
| geometry.geometry.triangles.vertexData = unbound_buffer.handle(); |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryTrianglesNV-vertexOffset-02428"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| #endif |
| |
| // Invalid index offset - not multiple of index size. |
| { |
| VkGeometryNV geometry = valid_geometry_triangles; |
| geometry.geometry.triangles.indexOffset = 1; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryTrianglesNV-indexOffset-02432"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid index offset - bigger than buffer. |
| { |
| VkGeometryNV geometry = valid_geometry_triangles; |
| geometry.geometry.triangles.indexOffset = 2048; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryTrianglesNV-indexOffset-02431"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid index count - must be 0 if type is VK_INDEX_TYPE_NONE_NV. |
| { |
| VkGeometryNV geometry = valid_geometry_triangles; |
| geometry.geometry.triangles.indexType = VK_INDEX_TYPE_NONE_NV; |
| geometry.geometry.triangles.indexData = VK_NULL_HANDLE; |
| geometry.geometry.triangles.indexCount = 1; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryTrianglesNV-indexCount-02436"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid index data - must be VK_NULL_HANDLE if type is VK_INDEX_TYPE_NONE_NV. |
| { |
| VkGeometryNV geometry = valid_geometry_triangles; |
| geometry.geometry.triangles.indexType = VK_INDEX_TYPE_NONE_NV; |
| geometry.geometry.triangles.indexData = ibo.handle(); |
| geometry.geometry.triangles.indexCount = 0; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryTrianglesNV-indexData-02434"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Invalid transform offset - not multiple of 16. |
| { |
| VkGeometryNV geometry = valid_geometry_triangles; |
| geometry.geometry.triangles.transformOffset = 1; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryTrianglesNV-transformOffset-02438"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid transform offset - bigger than buffer. |
| { |
| VkGeometryNV geometry = valid_geometry_triangles; |
| geometry.geometry.triangles.transformOffset = 2048; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryTrianglesNV-transformOffset-02437"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Invalid aabb offset - not multiple of 8. |
| { |
| VkGeometryNV geometry = valid_geometry_aabbs; |
| geometry.geometry.aabbs.offset = 1; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryAABBNV-offset-02440"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid aabb offset - bigger than buffer. |
| { |
| VkGeometryNV geometry = valid_geometry_aabbs; |
| geometry.geometry.aabbs.offset = 8 * 1024; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryAABBNV-offset-02439"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Invalid aabb stride - not multiple of 8. |
| { |
| VkGeometryNV geometry = valid_geometry_aabbs; |
| geometry.geometry.aabbs.stride = 1; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryAABBNV-stride-02441"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // geometryType must be VK_GEOMETRY_TYPE_TRIANGLES_NV or VK_GEOMETRY_TYPE_AABBS_NV |
| { |
| VkGeometryNV geometry = valid_geometry_aabbs; |
| geometry.geometry.aabbs.stride = 1; |
| geometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = GetCreateInfo(geometry); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkGeometryNV-geometryType-03503"); |
| m_errorMonitor->SetUnexpectedError("VUID-VkGeometryNV-geometryType-parameter"); |
| vk::CreateAccelerationStructureNV(device(), &as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeRayTracingNV, ValidateCreateAccelerationStructure) { |
| TEST_DESCRIPTION("Validate acceleration structure creation."); |
| |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, false)) |
| RETURN_IF_SKIP(InitState()) |
| |
| vkt::Buffer vbo; |
| vkt::Buffer ibo; |
| VkGeometryNV geometry; |
| nv::rt::GetSimpleGeometryForAccelerationStructureTests(*m_device, &vbo, &ibo, &geometry); |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = vku::InitStructHelper(); |
| as_create_info.info = vku::InitStructHelper(); |
| |
| VkAccelerationStructureNV as = VK_NULL_HANDLE; |
| |
| // Top level can not have geometry |
| { |
| VkAccelerationStructureCreateInfoNV bad_top_level_create_info = as_create_info; |
| bad_top_level_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV; |
| bad_top_level_create_info.info.instanceCount = 0; |
| bad_top_level_create_info.info.geometryCount = 1; |
| bad_top_level_create_info.info.pGeometries = &geometry; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureInfoNV-type-02425"); |
| vk::CreateAccelerationStructureNV(device(), &bad_top_level_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Bot level can not have instances |
| { |
| VkAccelerationStructureCreateInfoNV bad_bot_level_create_info = as_create_info; |
| bad_bot_level_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV; |
| bad_bot_level_create_info.info.instanceCount = 1; |
| bad_bot_level_create_info.info.geometryCount = 0; |
| bad_bot_level_create_info.info.pGeometries = nullptr; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureInfoNV-type-02426"); |
| vk::CreateAccelerationStructureNV(device(), &bad_bot_level_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Type must not be VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR |
| { |
| VkAccelerationStructureCreateInfoNV bad_bot_level_create_info = as_create_info; |
| bad_bot_level_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR; |
| bad_bot_level_create_info.info.instanceCount = 0; |
| bad_bot_level_create_info.info.geometryCount = 0; |
| bad_bot_level_create_info.info.pGeometries = nullptr; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureInfoNV-type-04623"); |
| vk::CreateAccelerationStructureNV(device(), &bad_bot_level_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Can not prefer both fast trace and fast build |
| { |
| VkAccelerationStructureCreateInfoNV bad_flags_level_create_info = as_create_info; |
| bad_flags_level_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV; |
| bad_flags_level_create_info.info.instanceCount = 0; |
| bad_flags_level_create_info.info.geometryCount = 1; |
| bad_flags_level_create_info.info.pGeometries = &geometry; |
| bad_flags_level_create_info.info.flags = |
| VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV | VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureInfoNV-flags-02592"); |
| vk::CreateAccelerationStructureNV(device(), &bad_flags_level_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Can not have geometry or instance for compacting |
| { |
| VkAccelerationStructureCreateInfoNV bad_compacting_as_create_info = as_create_info; |
| bad_compacting_as_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV; |
| bad_compacting_as_create_info.info.instanceCount = 0; |
| bad_compacting_as_create_info.info.geometryCount = 1; |
| bad_compacting_as_create_info.info.pGeometries = &geometry; |
| bad_compacting_as_create_info.info.flags = 0; |
| bad_compacting_as_create_info.compactedSize = 1024; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureCreateInfoNV-compactedSize-02421"); |
| vk::CreateAccelerationStructureNV(device(), &bad_compacting_as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Can not mix different geometry types into single bottom level acceleration structure |
| { |
| VkGeometryNV aabb_geometry = vku::InitStructHelper(); |
| aabb_geometry.geometryType = VK_GEOMETRY_TYPE_AABBS_NV; |
| aabb_geometry.geometry.triangles = vku::InitStructHelper(); |
| aabb_geometry.geometry.aabbs = vku::InitStructHelper(); |
| // Buffer contents do not matter for this test. |
| aabb_geometry.geometry.aabbs.aabbData = geometry.geometry.triangles.vertexData; |
| aabb_geometry.geometry.aabbs.numAABBs = 1; |
| aabb_geometry.geometry.aabbs.offset = 0; |
| aabb_geometry.geometry.aabbs.stride = 24; |
| |
| std::vector<VkGeometryNV> geometries = {geometry, aabb_geometry}; |
| |
| VkAccelerationStructureCreateInfoNV mix_geometry_types_as_create_info = as_create_info; |
| mix_geometry_types_as_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV; |
| mix_geometry_types_as_create_info.info.instanceCount = 0; |
| mix_geometry_types_as_create_info.info.geometryCount = static_cast<uint32_t>(geometries.size()); |
| mix_geometry_types_as_create_info.info.pGeometries = geometries.data(); |
| mix_geometry_types_as_create_info.info.flags = 0; |
| |
| m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkAccelerationStructureInfoNV-type-02786"); |
| vk::CreateAccelerationStructureNV(device(), &mix_geometry_types_as_create_info, nullptr, &as); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeRayTracingNV, ValidateBindAccelerationStructure) { |
| TEST_DESCRIPTION("Validate acceleration structure binding."); |
| |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, false)) |
| RETURN_IF_SKIP(InitState()) |
| |
| vkt::Buffer vbo; |
| vkt::Buffer ibo; |
| VkGeometryNV geometry; |
| nv::rt::GetSimpleGeometryForAccelerationStructureTests(*m_device, &vbo, &ibo, &geometry); |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = vku::InitStructHelper(); |
| as_create_info.info = vku::InitStructHelper(); |
| as_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV; |
| as_create_info.info.geometryCount = 1; |
| as_create_info.info.pGeometries = &geometry; |
| as_create_info.info.instanceCount = 0; |
| |
| vkt::AccelerationStructure as(*m_device, as_create_info, false); |
| |
| VkMemoryRequirements as_memory_requirements = as.memory_requirements().memoryRequirements; |
| |
| VkBindAccelerationStructureMemoryInfoNV as_bind_info = vku::InitStructHelper(); |
| as_bind_info.accelerationStructure = as.handle(); |
| |
| VkMemoryAllocateInfo as_memory_alloc = vku::InitStructHelper(); |
| as_memory_alloc.allocationSize = as_memory_requirements.size; |
| ASSERT_TRUE(m_device->phy().set_memory_type(as_memory_requirements.memoryTypeBits, &as_memory_alloc, 0)); |
| |
| // Can not bind already freed memory |
| { |
| VkDeviceMemory as_memory_freed = VK_NULL_HANDLE; |
| ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &as_memory_alloc, NULL, &as_memory_freed)); |
| vk::FreeMemory(device(), as_memory_freed, NULL); |
| |
| VkBindAccelerationStructureMemoryInfoNV as_bind_info_freed = as_bind_info; |
| as_bind_info_freed.memory = as_memory_freed; |
| as_bind_info_freed.memoryOffset = 0; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindAccelerationStructureMemoryInfoNV-memory-parameter"); |
| vk::BindAccelerationStructureMemoryNV(device(), 1, &as_bind_info_freed); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Can not bind with bad alignment |
| if (as_memory_requirements.alignment > 1) { |
| VkMemoryAllocateInfo as_memory_alloc_bad_alignment = as_memory_alloc; |
| as_memory_alloc_bad_alignment.allocationSize += 1; |
| |
| VkDeviceMemory as_memory_bad_alignment = VK_NULL_HANDLE; |
| ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &as_memory_alloc_bad_alignment, NULL, &as_memory_bad_alignment)); |
| |
| VkBindAccelerationStructureMemoryInfoNV as_bind_info_bad_alignment = as_bind_info; |
| as_bind_info_bad_alignment.memory = as_memory_bad_alignment; |
| as_bind_info_bad_alignment.memoryOffset = 1; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindAccelerationStructureMemoryInfoNV-memoryOffset-03623"); |
| vk::BindAccelerationStructureMemoryNV(device(), 1, &as_bind_info_bad_alignment); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::FreeMemory(device(), as_memory_bad_alignment, NULL); |
| } |
| |
| // Can not bind with offset outside the allocation |
| { |
| VkDeviceMemory as_memory_bad_offset = VK_NULL_HANDLE; |
| ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &as_memory_alloc, NULL, &as_memory_bad_offset)); |
| |
| VkBindAccelerationStructureMemoryInfoNV as_bind_info_bad_offset = as_bind_info; |
| as_bind_info_bad_offset.memory = as_memory_bad_offset; |
| as_bind_info_bad_offset.memoryOffset = |
| (as_memory_alloc.allocationSize + as_memory_requirements.alignment) & ~(as_memory_requirements.alignment - 1); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindAccelerationStructureMemoryInfoNV-memoryOffset-03621"); |
| vk::BindAccelerationStructureMemoryNV(device(), 1, &as_bind_info_bad_offset); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::FreeMemory(device(), as_memory_bad_offset, NULL); |
| } |
| |
| // Can not bind with offset that doesn't leave enough size |
| { |
| VkDeviceSize offset = (as_memory_requirements.size - 1) & ~(as_memory_requirements.alignment - 1); |
| if (offset > 0 && (as_memory_requirements.size < (as_memory_alloc.allocationSize - as_memory_requirements.alignment))) { |
| VkDeviceMemory as_memory_bad_offset = VK_NULL_HANDLE; |
| ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &as_memory_alloc, NULL, &as_memory_bad_offset)); |
| |
| VkBindAccelerationStructureMemoryInfoNV as_bind_info_bad_offset = as_bind_info; |
| as_bind_info_bad_offset.memory = as_memory_bad_offset; |
| as_bind_info_bad_offset.memoryOffset = offset; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindAccelerationStructureMemoryInfoNV-size-03624"); |
| vk::BindAccelerationStructureMemoryNV(device(), 1, &as_bind_info_bad_offset); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::FreeMemory(device(), as_memory_bad_offset, NULL); |
| } |
| } |
| |
| // Can not bind with memory that has unsupported memory type |
| { |
| VkPhysicalDeviceMemoryProperties memory_properties = {}; |
| vk::GetPhysicalDeviceMemoryProperties(m_device->phy().handle(), &memory_properties); |
| |
| uint32_t supported_memory_type_bits = as_memory_requirements.memoryTypeBits; |
| uint32_t unsupported_mem_type_bits = ((1 << memory_properties.memoryTypeCount) - 1) & ~supported_memory_type_bits; |
| if (unsupported_mem_type_bits != 0) { |
| VkMemoryAllocateInfo as_memory_alloc_bad_type = as_memory_alloc; |
| ASSERT_TRUE(m_device->phy().set_memory_type(unsupported_mem_type_bits, &as_memory_alloc_bad_type, 0)); |
| |
| VkDeviceMemory as_memory_bad_type = VK_NULL_HANDLE; |
| ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &as_memory_alloc_bad_type, NULL, &as_memory_bad_type)); |
| |
| VkBindAccelerationStructureMemoryInfoNV as_bind_info_bad_type = as_bind_info; |
| as_bind_info_bad_type.memory = as_memory_bad_type; |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindAccelerationStructureMemoryInfoNV-memory-03622"); |
| vk::BindAccelerationStructureMemoryNV(device(), 1, &as_bind_info_bad_type); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::FreeMemory(device(), as_memory_bad_type, NULL); |
| } |
| } |
| |
| // Can not bind memory twice |
| { |
| vkt::AccelerationStructure as_twice(*m_device, as_create_info, false); |
| |
| VkDeviceMemory as_memory_twice_1 = VK_NULL_HANDLE; |
| VkDeviceMemory as_memory_twice_2 = VK_NULL_HANDLE; |
| ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &as_memory_alloc, NULL, &as_memory_twice_1)); |
| ASSERT_EQ(VK_SUCCESS, vk::AllocateMemory(device(), &as_memory_alloc, NULL, &as_memory_twice_2)); |
| VkBindAccelerationStructureMemoryInfoNV as_bind_info_twice_1 = as_bind_info; |
| VkBindAccelerationStructureMemoryInfoNV as_bind_info_twice_2 = as_bind_info; |
| as_bind_info_twice_1.accelerationStructure = as_twice.handle(); |
| as_bind_info_twice_2.accelerationStructure = as_twice.handle(); |
| as_bind_info_twice_1.memory = as_memory_twice_1; |
| as_bind_info_twice_2.memory = as_memory_twice_2; |
| |
| ASSERT_EQ(VK_SUCCESS, vk::BindAccelerationStructureMemoryNV(device(), 1, &as_bind_info_twice_1)); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkBindAccelerationStructureMemoryInfoNV-accelerationStructure-03620"); |
| vk::BindAccelerationStructureMemoryNV(device(), 1, &as_bind_info_twice_2); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::FreeMemory(device(), as_memory_twice_1, NULL); |
| vk::FreeMemory(device(), as_memory_twice_2, NULL); |
| } |
| } |
| |
| TEST_F(NegativeRayTracingNV, ValidateWriteDescriptorSetAccelerationStructure) { |
| TEST_DESCRIPTION("Validate acceleration structure descriptor writing."); |
| |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, false)) |
| RETURN_IF_SKIP(InitState()) |
| |
| OneOffDescriptorSet ds(m_device, |
| { |
| {0, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV, 1, VK_SHADER_STAGE_RAYGEN_BIT_NV, nullptr}, |
| }); |
| |
| VkWriteDescriptorSet descriptor_write = vku::InitStructHelper(); |
| descriptor_write.dstSet = ds.set_; |
| descriptor_write.dstBinding = 0; |
| descriptor_write.descriptorCount = 1; |
| descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV; |
| |
| VkWriteDescriptorSetAccelerationStructureNV acc = vku::InitStructHelper(); |
| acc.accelerationStructureCount = 1; |
| VkAccelerationStructureCreateInfoNV top_level_as_create_info = vku::InitStructHelper(); |
| top_level_as_create_info.info = vku::InitStructHelper(); |
| top_level_as_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV; |
| top_level_as_create_info.info.instanceCount = 1; |
| top_level_as_create_info.info.geometryCount = 0; |
| |
| vkt::AccelerationStructure top_level_as(*m_device, top_level_as_create_info); |
| |
| acc.pAccelerationStructures = &top_level_as.handle(); |
| descriptor_write.pNext = &acc; |
| vk::UpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL); |
| } |
| |
| TEST_F(NegativeRayTracingNV, ValidateCmdBuildAccelerationStructure) { |
| TEST_DESCRIPTION("Validate acceleration structure building."); |
| |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, false)) |
| RETURN_IF_SKIP(InitState()) |
| |
| vkt::Buffer vbo; |
| vkt::Buffer ibo; |
| VkGeometryNV geometry; |
| nv::rt::GetSimpleGeometryForAccelerationStructureTests(*m_device, &vbo, &ibo, &geometry); |
| |
| VkAccelerationStructureCreateInfoNV bot_level_as_create_info = vku::InitStructHelper(); |
| bot_level_as_create_info.info = vku::InitStructHelper(); |
| bot_level_as_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV; |
| bot_level_as_create_info.info.instanceCount = 0; |
| bot_level_as_create_info.info.geometryCount = 1; |
| bot_level_as_create_info.info.pGeometries = &geometry; |
| |
| vkt::AccelerationStructure bot_level_as(*m_device, bot_level_as_create_info); |
| |
| const vkt::Buffer bot_level_as_scratch = bot_level_as.create_scratch_buffer(*m_device); |
| |
| // Command buffer must be in recording state |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructureNV-commandBuffer-recording"); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &bot_level_as_create_info.info, VK_NULL_HANDLE, 0, VK_FALSE, |
| bot_level_as.handle(), VK_NULL_HANDLE, bot_level_as_scratch.handle(), 0); |
| m_errorMonitor->VerifyFound(); |
| |
| m_commandBuffer->begin(); |
| |
| // Incompatible type |
| VkAccelerationStructureInfoNV as_build_info_with_incompatible_type = bot_level_as_create_info.info; |
| as_build_info_with_incompatible_type.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV; |
| as_build_info_with_incompatible_type.instanceCount = 1; |
| as_build_info_with_incompatible_type.geometryCount = 0; |
| |
| // This is duplicated since it triggers one error for different types and one error for lower instance count - the |
| // build info is incompatible but still needs to be valid to get past the stateless checks. |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructureNV-dst-02488"); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructureNV-dst-02488"); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &as_build_info_with_incompatible_type, VK_NULL_HANDLE, 0, |
| VK_FALSE, bot_level_as.handle(), VK_NULL_HANDLE, bot_level_as_scratch.handle(), 0); |
| m_errorMonitor->VerifyFound(); |
| |
| // Incompatible flags |
| VkAccelerationStructureInfoNV as_build_info_with_incompatible_flags = bot_level_as_create_info.info; |
| as_build_info_with_incompatible_flags.flags = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructureNV-dst-02488"); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &as_build_info_with_incompatible_flags, VK_NULL_HANDLE, 0, |
| VK_FALSE, bot_level_as.handle(), VK_NULL_HANDLE, bot_level_as_scratch.handle(), 0); |
| m_errorMonitor->VerifyFound(); |
| |
| // Incompatible build size |
| VkGeometryNV geometry_with_more_vertices = geometry; |
| geometry_with_more_vertices.geometry.triangles.vertexCount += 1; |
| |
| VkAccelerationStructureInfoNV as_build_info_with_incompatible_geometry = bot_level_as_create_info.info; |
| as_build_info_with_incompatible_geometry.pGeometries = &geometry_with_more_vertices; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructureNV-dst-02488"); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &as_build_info_with_incompatible_geometry, VK_NULL_HANDLE, 0, |
| VK_FALSE, bot_level_as.handle(), VK_NULL_HANDLE, bot_level_as_scratch.handle(), 0); |
| m_errorMonitor->VerifyFound(); |
| |
| // Scratch buffer too small |
| VkBufferCreateInfo too_small_scratch_buffer_info = vku::InitStructHelper(); |
| too_small_scratch_buffer_info.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV; |
| too_small_scratch_buffer_info.size = 1; |
| vkt::Buffer too_small_scratch_buffer(*m_device, too_small_scratch_buffer_info); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructureNV-update-02491"); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &bot_level_as_create_info.info, VK_NULL_HANDLE, 0, VK_FALSE, |
| bot_level_as.handle(), VK_NULL_HANDLE, too_small_scratch_buffer.handle(), 0); |
| m_errorMonitor->VerifyFound(); |
| |
| // Scratch buffer with offset too small |
| VkDeviceSize scratch_buffer_offset = 5; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructureNV-update-02491"); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &bot_level_as_create_info.info, VK_NULL_HANDLE, 0, VK_FALSE, |
| bot_level_as.handle(), VK_NULL_HANDLE, bot_level_as_scratch.handle(), |
| scratch_buffer_offset); |
| m_errorMonitor->VerifyFound(); |
| |
| // Src must have been built before |
| vkt::AccelerationStructure bot_level_as_updated(*m_device, bot_level_as_create_info); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructureNV-update-02489"); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &bot_level_as_create_info.info, VK_NULL_HANDLE, 0, VK_TRUE, |
| bot_level_as_updated.handle(), VK_NULL_HANDLE, bot_level_as_scratch.handle(), 0); |
| m_errorMonitor->VerifyFound(); |
| |
| // Src must have been built before with the VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV flag |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &bot_level_as_create_info.info, VK_NULL_HANDLE, 0, VK_FALSE, |
| bot_level_as.handle(), VK_NULL_HANDLE, bot_level_as_scratch.handle(), 0); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructureNV-update-02490"); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &bot_level_as_create_info.info, VK_NULL_HANDLE, 0, VK_TRUE, |
| bot_level_as_updated.handle(), bot_level_as.handle(), bot_level_as_scratch.handle(), 0); |
| m_errorMonitor->VerifyFound(); |
| |
| // invalid scratch buffer (invalid usage) |
| VkBufferCreateInfo create_info = vku::InitStructHelper(); |
| create_info.usage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR; |
| const vkt::Buffer bot_level_as_invalid_scratch = bot_level_as.create_scratch_buffer(*m_device, &create_info); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureInfoNV-scratch-02781"); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &bot_level_as_create_info.info, VK_NULL_HANDLE, 0, VK_FALSE, |
| bot_level_as.handle(), VK_NULL_HANDLE, bot_level_as_invalid_scratch.handle(), 0); |
| m_errorMonitor->VerifyFound(); |
| |
| // invalid instance data. |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-VkAccelerationStructureInfoNV-instanceData-02782"); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &bot_level_as_create_info.info, |
| bot_level_as_invalid_scratch.handle(), 0, VK_FALSE, bot_level_as.handle(), VK_NULL_HANDLE, |
| bot_level_as_scratch.handle(), 0); |
| m_errorMonitor->VerifyFound(); |
| |
| // must be called outside renderpass |
| InitRenderTarget(); |
| m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdBuildAccelerationStructureNV-renderpass"); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &bot_level_as_create_info.info, VK_NULL_HANDLE, 0, VK_FALSE, |
| bot_level_as.handle(), VK_NULL_HANDLE, bot_level_as_scratch.handle(), 0); |
| m_commandBuffer->EndRenderPass(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeRayTracingNV, ObjInUseCmdBuildAccelerationStructure) { |
| TEST_DESCRIPTION("Validate acceleration structure building tracks the objects used."); |
| |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, false)) |
| RETURN_IF_SKIP(InitState()) |
| |
| vkt::Buffer vbo; |
| vkt::Buffer ibo; |
| VkGeometryNV geometry; |
| nv::rt::GetSimpleGeometryForAccelerationStructureTests(*m_device, &vbo, &ibo, &geometry); |
| |
| VkAccelerationStructureCreateInfoNV bot_level_as_create_info = vku::InitStructHelper(); |
| bot_level_as_create_info.info = vku::InitStructHelper(); |
| bot_level_as_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV; |
| bot_level_as_create_info.info.instanceCount = 0; |
| bot_level_as_create_info.info.geometryCount = 1; |
| bot_level_as_create_info.info.pGeometries = &geometry; |
| |
| vkt::AccelerationStructure bot_level_as(*m_device, bot_level_as_create_info); |
| |
| const vkt::Buffer bot_level_as_scratch = bot_level_as.create_scratch_buffer(*m_device); |
| |
| m_commandBuffer->begin(); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &bot_level_as_create_info.info, VK_NULL_HANDLE, 0, VK_FALSE, |
| bot_level_as.handle(), VK_NULL_HANDLE, bot_level_as_scratch.handle(), 0); |
| m_commandBuffer->end(); |
| |
| VkSubmitInfo submit_info = vku::InitStructHelper(); |
| submit_info.commandBufferCount = 1; |
| submit_info.pCommandBuffers = &m_commandBuffer->handle(); |
| vk::QueueSubmit(m_default_queue, 1, &submit_info, VK_NULL_HANDLE); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkDestroyBuffer-buffer-00922"); |
| vk::DestroyBuffer(device(), ibo.handle(), nullptr); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkDestroyBuffer-buffer-00922"); |
| vk::DestroyBuffer(device(), vbo.handle(), nullptr); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkDestroyBuffer-buffer-00922"); |
| vk::DestroyBuffer(device(), bot_level_as_scratch.handle(), nullptr); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkDestroyAccelerationStructureNV-accelerationStructure-03752"); |
| vk::DestroyAccelerationStructureNV(device(), bot_level_as.handle(), nullptr); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::QueueWaitIdle(m_default_queue); |
| } |
| |
| TEST_F(NegativeRayTracingNV, ValidateGetAccelerationStructureHandle) { |
| TEST_DESCRIPTION("Validate acceleration structure handle querying."); |
| |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, false)) |
| RETURN_IF_SKIP(InitState()) |
| |
| vkt::Buffer vbo; |
| vkt::Buffer ibo; |
| VkGeometryNV geometry; |
| nv::rt::GetSimpleGeometryForAccelerationStructureTests(*m_device, &vbo, &ibo, &geometry); |
| |
| VkAccelerationStructureCreateInfoNV bot_level_as_create_info = vku::InitStructHelper(); |
| bot_level_as_create_info.info = vku::InitStructHelper(); |
| bot_level_as_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV; |
| bot_level_as_create_info.info.instanceCount = 0; |
| bot_level_as_create_info.info.geometryCount = 1; |
| bot_level_as_create_info.info.pGeometries = &geometry; |
| |
| // Not enough space for the handle |
| { |
| vkt::AccelerationStructure bot_level_as(*m_device, bot_level_as_create_info); |
| |
| uint64_t handle = 0; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkGetAccelerationStructureHandleNV-dataSize-02240"); |
| vk::GetAccelerationStructureHandleNV(device(), bot_level_as.handle(), sizeof(uint8_t), &handle); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // No memory bound to acceleration structure |
| { |
| vkt::AccelerationStructure bot_level_as(*m_device, bot_level_as_create_info, /*init_memory=*/false); |
| |
| uint64_t handle = 0; |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkGetAccelerationStructureHandleNV-accelerationStructure-02787"); |
| vk::GetAccelerationStructureHandleNV(device(), bot_level_as.handle(), sizeof(uint64_t), &handle); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeRayTracingNV, ValidateCmdCopyAccelerationStructure) { |
| TEST_DESCRIPTION("Validate acceleration structure copying."); |
| |
| RETURN_IF_SKIP(InitFrameworkForRayTracingTest(this, false)) |
| RETURN_IF_SKIP(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)); |
| |
| vkt::Buffer vbo; |
| vkt::Buffer ibo; |
| VkGeometryNV geometry; |
| nv::rt::GetSimpleGeometryForAccelerationStructureTests(*m_device, &vbo, &ibo, &geometry); |
| |
| VkAccelerationStructureCreateInfoNV as_create_info = vku::InitStructHelper(); |
| as_create_info.info = vku::InitStructHelper(); |
| as_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV; |
| as_create_info.info.instanceCount = 0; |
| as_create_info.info.geometryCount = 1; |
| as_create_info.info.pGeometries = &geometry; |
| |
| vkt::AccelerationStructure src_as(*m_device, as_create_info); |
| vkt::AccelerationStructure dst_as(*m_device, as_create_info); |
| vkt::AccelerationStructure dst_as_without_mem(*m_device, as_create_info, false); |
| |
| VkAccelerationStructureCreateInfoNV bot_level_as_create_info = vku::InitStructHelper(); |
| bot_level_as_create_info.info = vku::InitStructHelper(); |
| bot_level_as_create_info.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV; |
| bot_level_as_create_info.info.instanceCount = 0; |
| bot_level_as_create_info.info.geometryCount = 1; |
| bot_level_as_create_info.info.pGeometries = &geometry; |
| |
| const vkt::Buffer bot_level_as_scratch = src_as.create_scratch_buffer(*m_device); |
| |
| m_commandBuffer->begin(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureNV-src-04963"); |
| vk::CmdCopyAccelerationStructureNV(m_commandBuffer->handle(), dst_as.handle(), src_as.handle(), |
| VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &bot_level_as_create_info.info, VK_NULL_HANDLE, 0, VK_FALSE, |
| src_as.handle(), VK_NULL_HANDLE, bot_level_as_scratch.handle(), 0); |
| m_commandBuffer->end(); |
| |
| VkSubmitInfo submit_info = vku::InitStructHelper(); |
| submit_info.commandBufferCount = 1u; |
| submit_info.pCommandBuffers = &m_commandBuffer->handle(); |
| |
| vk::QueueSubmit(m_default_queue, 1u, &submit_info, VK_NULL_HANDLE); |
| vk::QueueWaitIdle(m_default_queue); |
| |
| // Command buffer must be in recording state |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureNV-commandBuffer-recording"); |
| vk::CmdCopyAccelerationStructureNV(m_commandBuffer->handle(), dst_as.handle(), src_as.handle(), |
| VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV); |
| m_errorMonitor->VerifyFound(); |
| |
| m_commandBuffer->begin(); |
| |
| // Src must have been created with allow compaction flag |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureNV-src-03411"); |
| vk::CmdCopyAccelerationStructureNV(m_commandBuffer->handle(), dst_as.handle(), src_as.handle(), |
| VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV); |
| m_errorMonitor->VerifyFound(); |
| |
| // Dst must have been bound with memory |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureNV-dst-07792"); |
| vk::CmdCopyAccelerationStructureNV(m_commandBuffer->handle(), dst_as_without_mem.handle(), src_as.handle(), |
| VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV); |
| |
| m_errorMonitor->VerifyFound(); |
| |
| // mode must be VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR or VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureNV-mode-03410"); |
| vk::CmdCopyAccelerationStructureNV(m_commandBuffer->handle(), dst_as.handle(), src_as.handle(), |
| VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR); |
| m_errorMonitor->VerifyFound(); |
| |
| // mode must be a valid VkCopyAccelerationStructureModeKHR value |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureNV-mode-parameter"); |
| vk::CmdCopyAccelerationStructureNV(m_commandBuffer->handle(), dst_as.handle(), src_as.handle(), |
| VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR); |
| m_errorMonitor->VerifyFound(); |
| |
| // This command must only be called outside of a render pass instance |
| InitRenderTarget(); |
| m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureNV-renderpass"); |
| vk::CmdCopyAccelerationStructureNV(m_commandBuffer->handle(), dst_as.handle(), src_as.handle(), |
| VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV); |
| m_commandBuffer->EndRenderPass(); |
| m_errorMonitor->VerifyFound(); |
| |
| vkt::DeviceMemory host_memory; |
| host_memory.init(*m_device, vkt::DeviceMemory::get_resource_alloc_info( |
| *m_device, dst_as_without_mem.memory_requirements().memoryRequirements, |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); |
| |
| VkBindAccelerationStructureMemoryInfoNV bind_info = vku::InitStructHelper(); |
| bind_info.accelerationStructure = dst_as_without_mem.handle(); |
| bind_info.memory = host_memory.handle(); |
| vk::BindAccelerationStructureMemoryNV(*m_device, 1, &bind_info); |
| |
| uint64_t handle; |
| vk::GetAccelerationStructureHandleNV(*m_device, dst_as_without_mem.handle(), sizeof(uint64_t), &handle); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureNV-buffer-03719"); |
| vk::CmdCopyAccelerationStructureNV(m_commandBuffer->handle(), dst_as_without_mem.handle(), src_as.handle(), |
| VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkCmdCopyAccelerationStructureNV-buffer-03718"); |
| const vkt::Buffer bot_level_as_scratch2 = dst_as_without_mem.create_scratch_buffer(*m_device); |
| vk::CmdBuildAccelerationStructureNV(m_commandBuffer->handle(), &bot_level_as_create_info.info, VK_NULL_HANDLE, 0, VK_FALSE, |
| dst_as_without_mem.handle(), VK_NULL_HANDLE, bot_level_as_scratch.handle(), 0); |
| vk::CmdCopyAccelerationStructureNV(m_commandBuffer->handle(), src_as.handle(), dst_as_without_mem.handle(), |
| VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV); |
| m_errorMonitor->VerifyFound(); |
| } |