Skip to content

Commit

Permalink
tests: Spread rt::as namespace usage
Browse files Browse the repository at this point in the history
Simplify tests by using objects from the rt::as namespace,
replacing usage of AccelerationStructureKHR

Rename RayTracingAccelerationStructureReference to
RayTracingHostAccelerationStructureReference, because it tests host
acceleration structure creation

Add RayTracingHostAccelerationStructureReference to test on device
acceleration structure creation
  • Loading branch information
arno-lunarg committed Mar 17, 2023
1 parent aa7fb88 commit 8791578
Show file tree
Hide file tree
Showing 8 changed files with 722 additions and 562 deletions.
16 changes: 15 additions & 1 deletion layers/utils/vk_layer_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,12 @@ static inline dispatch_key get_dispatch_key(const void *object) { return (dispat
VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func);
VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func);

static inline bool IsPowerOfTwo(unsigned x) { return x && !(x & (x - 1)); }
template <typename T>
constexpr bool IsPowerOfTwo(T x) {
static_assert(std::numeric_limits<T>::is_integer, "Unsigned integer required.");
static_assert(!std::numeric_limits<T>::is_signed, "Unsigned integer required.");
return x && !(x & (x - 1));
}

// Returns the 0-based index of the MSB, like the x86 bit scan reverse (bsr) instruction
// Note: an input mask of 0 yields -1
Expand Down Expand Up @@ -185,6 +190,15 @@ static inline int u_ffs(int val) {
#endif
}

// Given p2 a power of two, returns smallest multiple of p2 greater than or equal to x
template <typename T>
constexpr T Align(T x, T p2) {
static_assert(std::numeric_limits<T>::is_integer, "Unsigned integer required.");
static_assert(!std::numeric_limits<T>::is_signed, "Unsigned integer required.");
assert(IsPowerOfTwo(p2));
return (x + p2 - 1) & ~(p2 - 1);
}

// Returns the 0-based index of the LSB. An input mask of 0 yields -1
static inline int LeastSignificantBit(uint32_t mask) { return u_ffs(static_cast<int>(mask)) - 1; }

Expand Down
3 changes: 2 additions & 1 deletion tests/device_profiles/max_profile.json
Original file line number Diff line number Diff line change
Expand Up @@ -1246,7 +1246,8 @@
"maxPerStageDescriptorAccelerationStructures": 2048,
"maxPerStageDescriptorUpdateAfterBindAccelerationStructures": 2048,
"maxDescriptorSetAccelerationStructures": 2048,
"maxDescriptorSetUpdateAfterBindAccelerationStructures": 2048
"maxDescriptorSetUpdateAfterBindAccelerationStructures": 2048,
"minAccelerationStructureScratchOffsetAlignment": 128
},
"VkPhysicalDeviceRayTracingPipelinePropertiesKHR": {
"maxRayDispatchInvocationCount": 1073741824,
Expand Down
423 changes: 362 additions & 61 deletions tests/framework/ray_tracing_objects.cpp

Large diffs are not rendered by default.

89 changes: 69 additions & 20 deletions tests/framework/ray_tracing_objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,26 @@ namespace as {
// When done with modifications, call the Build() method to build the internal Vulkan objects.
// Access them using relevant methods, eg: handle(), GetVkObj()...

// 3 types of geometry handled: Triangle, AABB and VkAccelerationStructureInstanceKHR (used in top level acceleration structures)
// Those objects can be managed on the device, using the ***Device*** methods,
// or on the host using the ***Host*** methods
class GeometryKHR {
public:
enum class Type { Triangle, AABB, _INTERNAL_UNSPECIFIED };
enum class Type { Triangle, AABB, Instance, _INTERNAL_UNSPECIFIED };
struct Triangles {
vk_testing::Buffer vertex_buffer;
vk_testing::Buffer index_buffer;
vk_testing::Buffer device_vertex_buffer;
std::unique_ptr<float[]> host_vertex_buffer;
vk_testing::Buffer device_index_buffer;
std::unique_ptr<uint32_t[]> host_index_buffer;
};
struct AABBs {
vk_testing::Buffer device_buffer;
std::unique_ptr<VkAabbPositionsKHR[]> host_buffer;
};
struct Instance {
// As of now, only manage one instance
std::unique_ptr<VkAccelerationStructureInstanceKHR> vk_instance{};
// Used to (eventually, no need for host instance) store on device instance
vk_testing::Buffer buffer;
};

Expand All @@ -51,15 +63,26 @@ class GeometryKHR {
GeometryKHR& operator=(GeometryKHR&&) = default;
GeometryKHR& operator=(const GeometryKHR&) = delete;

// Common methods for all types
GeometryKHR& SetType(Type type);
GeometryKHR& SetPrimitiveCount(uint32_t primitiveCount);
GeometryKHR& SetStride(VkDeviceSize stride);
GeometryKHR& SetTrianglesVertexBuffer(vk_testing::Buffer&& vertex_buffer, uint32_t max_vertex,
VkFormat vertex_format = VK_FORMAT_R32G32B32_SFLOAT,
VkDeviceSize stride = 3 * sizeof(float));
GeometryKHR& SetTrianglesIndexBuffer(vk_testing::Buffer&& index_buffer, VkIndexType index_type = VK_INDEX_TYPE_UINT32);
// Triangle
GeometryKHR& SetTrianglesDeviceVertexBuffer(vk_testing::Buffer&& vertex_buffer, uint32_t max_vertex,
VkFormat vertex_format = VK_FORMAT_R32G32B32_SFLOAT,
VkDeviceSize stride = 3 * sizeof(float));
GeometryKHR& SetTrianglesHostVertexBuffer(std::unique_ptr<float[]>&& vertex_buffer, uint32_t max_vertex,
VkDeviceSize stride = 3 * sizeof(float));
GeometryKHR& SetTrianglesDeviceIndexBuffer(vk_testing::Buffer&& index_buffer, VkIndexType index_type = VK_INDEX_TYPE_UINT32);
GeometryKHR& SetTrianglesHostIndexBuffer(std::unique_ptr<uint32_t[]>&& index_buffer);
GeometryKHR& SetTrianglesIndexType(VkIndexType index_type);
GeometryKHR& SetAABBsBuffer(vk_testing::Buffer&& buffer, VkDeviceSize stride = sizeof(VkAabbPositionsKHR));
// AABB
GeometryKHR& SetAABBsDeviceBuffer(vk_testing::Buffer&& buffer, VkDeviceSize stride = sizeof(VkAabbPositionsKHR));
GeometryKHR& SetAABBsHostBuffer(std::unique_ptr<VkAabbPositionsKHR[]>&& buffer,
VkDeviceSize stride = sizeof(VkAabbPositionsKHR));
// Instance
GeometryKHR& SetInstanceDeviceAccelStructRef(const vk_testing::Device& device, VkAccelerationStructureKHR bottom_level_as);
GeometryKHR& SetInstanceHostAccelStructRef(VkAccelerationStructureKHR bottom_level_as);

GeometryKHR& Build();

Expand All @@ -75,6 +98,7 @@ class GeometryKHR {
uint32_t primitiveCount_ = 0;
Triangles triangles_;
AABBs aabbs_;
Instance instance_;
};

class AccelerationStructureKHR : public vk_testing::internal::NonDispHandle<VkAccelerationStructureKHR> {
Expand All @@ -89,30 +113,33 @@ class AccelerationStructureKHR : public vk_testing::internal::NonDispHandle<VkAc
AccelerationStructureKHR& SetOffset(VkDeviceSize offset);
AccelerationStructureKHR& SetType(VkAccelerationStructureTypeKHR type);
AccelerationStructureKHR& SetFlags(VkAccelerationStructureCreateFlagsKHR flags);
AccelerationStructureKHR& SetBuffer(vk_testing::Buffer&& buffer);
AccelerationStructureKHR& SetBufferMemoryAllocateFlags(VkMemoryAllocateFlags memory_allocate_flags);
AccelerationStructureKHR& SetBufferMemoryPropertyFlags(VkMemoryAllocateFlags memory_property_flags_);
AccelerationStructureKHR& SetDeviceBuffer(vk_testing::Buffer&& buffer);
AccelerationStructureKHR& SetDeviceBufferMemoryAllocateFlags(VkMemoryAllocateFlags memory_allocate_flags);
AccelerationStructureKHR& SetDeviceBufferMemoryPropertyFlags(VkMemoryAllocateFlags memory_property_flags_);
AccelerationStructureKHR& SetDeviceBufferInitNoMem(bool buffer_init_no_mem);
// Set it to 0 to skip buffer initialization at Build() step
AccelerationStructureKHR& SetBufferUsageFlags(VkBufferUsageFlags usage_flags);

VkDeviceAddress GetBufferDeviceAddress() const;

// Null check is done in BuildGeometryInfoKHR::Build(). Object is build iff it is not null.
void SetNull(bool is_null) { is_null_ = is_null; }
bool IsNull() const { return is_null_; }
void Build(const vk_testing::Device& device);
bool IsBuilt() const { return initialized(); }
void Destroy();

const auto& GetBuffer() const { return buffer_; }
const auto& GetBuffer() const { return device_buffer_; }

private:
bool is_null_ = false;
uint32_t vk_api_version_;
VkAccelerationStructureCreateInfoKHR vk_info_;
vk_testing::Buffer buffer_;
vk_testing::Buffer device_buffer_;
VkMemoryAllocateFlags buffer_memory_allocate_flags_{};
VkMemoryPropertyFlags buffer_memory_property_flags_{};
VkBufferUsageFlags buffer_usage_flags_{};
bool buffer_init_no_mem_ = false;
};

class BuildGeometryInfoKHR {
Expand All @@ -132,14 +159,16 @@ class BuildGeometryInfoKHR {
BuildGeometryInfoKHR& SetSrcAS(std::shared_ptr<AccelerationStructureKHR> src_as);
BuildGeometryInfoKHR& SetDstAS(std::shared_ptr<AccelerationStructureKHR> dst_as);
BuildGeometryInfoKHR& SetScratchBuffer(vk_testing::Buffer&& scratch_buffer);
BuildGeometryInfoKHR& SetBottomLevelAS(std::shared_ptr<BuildGeometryInfoKHR> bottom_level_as);
BuildGeometryInfoKHR& SetInfoCount(uint32_t info_count);
BuildGeometryInfoKHR& SetNullInfos(bool use_null_infos);
BuildGeometryInfoKHR& SetNullBuildRangeInfos(bool use_null_build_range_infos);

// Those functions call Build() on internal resources (geometries, src and dst acceleration structures, scratch buffer),
// then one the build acceleration structure function.
void BuildCmdBuffer(const vk_testing::Device& device, VkCommandBuffer cmd_buffer, bool use_ppGeometries = true);
void BuildCmdBufferIndirect(const vk_testing::Device& device, VkCommandBuffer cmd_buffer);
void BuildCmdBuffer(VkInstance instance, const vk_testing::Device& device, VkCommandBuffer cmd_buffer,
bool use_ppGeometries = true);
void BuildCmdBufferIndirect(VkInstance instance, const vk_testing::Device& device, VkCommandBuffer cmd_buffer);
void BuildHost(VkInstance instance, const vk_testing::Device& device);
void VkCmdBuildAccelerationStructuresKHR(const vk_testing::Device& device, VkCommandBuffer cmd_buffer,
bool use_ppGeometries = true);
Expand All @@ -151,11 +180,12 @@ class BuildGeometryInfoKHR {
auto& GetGeometries() { return geometries_; }
auto& GetSrcAS() { return src_as_; }
auto& GetDstAS() { return dst_as_; }
const auto& GetScratchBuffer() const { return scratch_; }
auto& GetBottomLevelAS() { return bottom_level_as_; }
const auto& GetScratchBuffer() const { return device_scratch_; }
VkAccelerationStructureBuildSizesInfoKHR GetSizeInfo(VkDevice device, bool use_ppGeometries = true);

private:
void BuildCommon(const vk_testing::Device& device, bool use_ppGeometries = true);
void BuildCommon(VkInstance instance, const vk_testing::Device& device, bool is_on_device_build, bool use_ppGeometries = true);

uint32_t vk_api_version_;
uint32_t vk_info_count_ = 1;
Expand All @@ -164,7 +194,9 @@ class BuildGeometryInfoKHR {
VkAccelerationStructureBuildGeometryInfoKHR vk_info_;
std::vector<GeometryKHR> geometries_;
std::shared_ptr<AccelerationStructureKHR> src_as_, dst_as_;
vk_testing::Buffer scratch_;
vk_testing::Buffer device_scratch_;
std::unique_ptr<uint8_t[]> host_scratch_;
std::shared_ptr<BuildGeometryInfoKHR> bottom_level_as_;
};

// Helper functions providing simple, valid objects.
Expand All @@ -182,14 +214,31 @@ class BuildGeometryInfoKHR {
// m_commandBuffer->end();
// }
namespace blueprint {
GeometryKHR GeometrySimpleTriangleInfo(uint32_t vk_api_version, const vk_testing::Device& device);
GeometryKHR GeometrySimpleAABBInfo(uint32_t vk_api_version, const vk_testing::Device& device);
GeometryKHR GeometrySimpleOnDeviceTriangleInfo(uint32_t vk_api_version, const vk_testing::Device& device);
GeometryKHR GeometrySimpleOnHostTriangleInfo(uint32_t vk_api_version);
GeometryKHR GeometrySimpleOnDeviceAABBInfo(uint32_t vk_api_version, const vk_testing::Device& device);
GeometryKHR GeometrySimpleOnHostAABBInfo(uint32_t vk_api_version);
GeometryKHR GeometrySimpleDeviceInstance(uint32_t vk_api_version, const vk_testing::Device& device,
VkAccelerationStructureKHR device_instance);
GeometryKHR GeometrySimpleHostInstance(uint32_t vk_api_version, VkAccelerationStructureKHR host_instance);

std::shared_ptr<AccelerationStructureKHR> AccelStructNull(uint32_t vk_api_version);
std::shared_ptr<AccelerationStructureKHR> AccelStructSimpleOnDeviceBottomLevel(uint32_t vk_api_version, VkDeviceSize size);
std::shared_ptr<AccelerationStructureKHR> AccelStructSimpleOnHostBottomLevel(uint32_t vk_api_version, VkDeviceSize size);

BuildGeometryInfoKHR BuildGeometryInfoSimpleOnDeviceBottomLevel(uint32_t vk_api_version, const vk_testing::Device& device,
GeometryKHR::Type geometry_type = GeometryKHR::Type::Triangle);

BuildGeometryInfoKHR BuildGeometryInfoSimpleOnHostBottomLevel(uint32_t vk_api_version, const vk_testing::Device& device,
GeometryKHR::Type geometry_type = GeometryKHR::Type::Triangle);

// on_device_bottom_level_geometry must have been built previously, and on the device
BuildGeometryInfoKHR BuildGeometryInfoSimpleOnDeviceTopLevel(uint32_t vk_api_version, const vk_testing::Device& device,
std::shared_ptr<BuildGeometryInfoKHR> on_device_bottom_level_geometry);
// on_host_bottom_level_geometry must have been built previously, and on the host
BuildGeometryInfoKHR BuildGeometryInfoSimpleOnHostTopLevel(uint32_t vk_api_version, const vk_testing::Device& device,
std::shared_ptr<BuildGeometryInfoKHR> on_host_bottom_level_geometry);

} // namespace blueprint

} // namespace as
Expand Down
22 changes: 6 additions & 16 deletions tests/negative/descriptor_renderpass_framebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "utils/cast_utils.h"
#include "../framework/layer_validation_tests.h"
#include "../framework/ray_tracing_objects.h"

TEST_F(VkLayerTest, InvalidDescriptorPoolConsistency) {
TEST_DESCRIPTION("Allocate descriptor sets from one DS pool and attempt to delete them from another.");
Expand Down Expand Up @@ -12524,27 +12525,16 @@ TEST_F(VkLayerTest, DescriptorBufferNotEnabled) {
}

if (IsExtensionsEnabled(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME)) {
uint32_t qfi = 0;
auto buffCI = LvlInitStruct<VkBufferCreateInfo>();
buffCI.size = 4096;
buffCI.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR;
buffCI.queueFamilyIndexCount = 1;
buffCI.pQueueFamilyIndices = &qfi;

vk_testing::Buffer as_buffer(*m_device, buffCI, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 0U);

auto asci = LvlInitStruct<VkAccelerationStructureCreateInfoKHR>();
asci.createFlags = 0;
asci.buffer = as_buffer.handle();
vk_testing::AccelerationStructureKHR as(*m_device, asci);
auto as = rt::as::blueprint::AccelStructSimpleOnDeviceBottomLevel(DeviceValidationVersion(), 4096);
as->Build(*m_device);

uint8_t data[256];
auto vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT =
reinterpret_cast<PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT>(
vk::GetDeviceProcAddr(m_device->device(), "vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT"));
GetDeviceProcAddr<PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT>(
"vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT");

auto ascddi = LvlInitStruct<VkAccelerationStructureCaptureDescriptorDataInfoEXT>();
ascddi.accelerationStructure = as.handle();
ascddi.accelerationStructure = as->handle();

m_errorMonitor->SetDesiredFailureMsg(kErrorBit, "VUID-vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT-None-08088");
m_errorMonitor->SetDesiredFailureMsg(
Expand Down
Loading

0 comments on commit 8791578

Please sign in to comment.