• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _VKRAYTRACINGUTIL_HPP
2 #define _VKRAYTRACINGUTIL_HPP
3 /*-------------------------------------------------------------------------
4  * Vulkan CTS Framework
5  * --------------------
6  *
7  * Copyright (c) 2020 The Khronos Group Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Vulkan ray tracing utility.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vkDefs.hpp"
27 #include "vkRef.hpp"
28 #include "vkMemUtil.hpp"
29 #include "vkObjUtil.hpp"
30 #include "vkBufferWithMemory.hpp"
31 #include "vkBuilderUtil.hpp"
32 #include "vkPrograms.hpp"
33 
34 #include "deFloat16.h"
35 
36 #include "tcuVector.hpp"
37 #include "tcuVectorType.hpp"
38 #include "qpWatchDog.h"
39 
40 #include <vector>
41 #include <limits>
42 #include <stdexcept>
43 
44 namespace vk
45 {
46 
47 #ifndef CTS_USES_VULKANSC
48 
49 constexpr VkShaderStageFlags	SHADER_STAGE_ALL_RAY_TRACING	= VK_SHADER_STAGE_RAYGEN_BIT_KHR
50 																| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
51 																| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
52 																| VK_SHADER_STAGE_MISS_BIT_KHR
53 																| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
54 																| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
55 
56 const VkTransformMatrixKHR identityMatrix3x4 = { { { 1.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f, 0.0f } } };
57 
58 template<typename T>
makeVkSharedPtr(Move<T> move)59 inline de::SharedPtr<Move<T>> makeVkSharedPtr(Move<T> move)
60 {
61 	return de::SharedPtr<Move<T>>(new Move<T>(move));
62 }
63 
64 template<typename T>
makeVkSharedPtr(de::MovePtr<T> movePtr)65 inline de::SharedPtr<de::MovePtr<T> > makeVkSharedPtr(de::MovePtr<T> movePtr)
66 {
67 	return de::SharedPtr<de::MovePtr<T> >(new de::MovePtr<T>(movePtr));
68 }
69 
updateRayTracingGLSL(const std::string & str)70 inline std::string updateRayTracingGLSL (const std::string& str)
71 {
72 	return str;
73 }
74 
75 std::string getCommonRayGenerationShader (void);
76 
77 // Get lowercase version of the format name with no VK_FORMAT_ prefix.
78 std::string getFormatSimpleName (vk::VkFormat format);
79 
80 // Test whether given poin p belons to the triangle (p0, p1, p2)
81 bool pointInTriangle2D(const tcu::Vec3& p, const tcu::Vec3& p0, const tcu::Vec3& p1, const tcu::Vec3& p2);
82 
83 // Checks the given vertex buffer format is valid for acceleration structures.
84 // Note: VK_KHR_get_physical_device_properties2 and VK_KHR_acceleration_structure are supposed to be supported.
85 void checkAccelerationStructureVertexBufferFormat (const vk::InstanceInterface &vki, vk::VkPhysicalDevice physicalDevice, vk::VkFormat format);
86 
87 class RaytracedGeometryBase
88 {
89 public:
90 								RaytracedGeometryBase			()										= delete;
91 								RaytracedGeometryBase			(const RaytracedGeometryBase& geometry)	= delete;
92 								RaytracedGeometryBase			(VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType);
93 								virtual ~RaytracedGeometryBase	();
94 
getGeometryType(void) const95 	inline VkGeometryTypeKHR	getGeometryType					(void) const								{ return m_geometryType; }
isTrianglesType(void) const96 	inline bool					isTrianglesType					(void) const								{ return m_geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR; }
getVertexFormat(void) const97 	inline VkFormat				getVertexFormat					(void) const								{ return m_vertexFormat; }
getIndexType(void) const98 	inline VkIndexType			getIndexType					(void) const								{ return m_indexType; }
usesIndices(void) const99 	inline bool					usesIndices						(void) const								{ return m_indexType != VK_INDEX_TYPE_NONE_KHR; }
getGeometryFlags(void) const100 	inline VkGeometryFlagsKHR	getGeometryFlags				(void) const								{ return m_geometryFlags; }
setGeometryFlags(const VkGeometryFlagsKHR geometryFlags)101 	inline void					setGeometryFlags				(const VkGeometryFlagsKHR geometryFlags)	{ m_geometryFlags = geometryFlags; }
getOpacityMicromap(void)102 	inline VkAccelerationStructureTrianglesOpacityMicromapEXT&	getOpacityMicromap(void)					{ return m_opacityGeometryMicromap; }
getHasOpacityMicromap(void) const103 	inline bool					getHasOpacityMicromap			(void) const								{ return m_hasOpacityMicromap; }
setOpacityMicromap(const VkAccelerationStructureTrianglesOpacityMicromapEXT * opacityGeometryMicromap)104 	inline void					setOpacityMicromap				(const VkAccelerationStructureTrianglesOpacityMicromapEXT* opacityGeometryMicromap) { m_hasOpacityMicromap = true; m_opacityGeometryMicromap = *opacityGeometryMicromap; }
105 	virtual deUint32			getVertexCount					(void) const								= 0;
106 	virtual const deUint8*		getVertexPointer				(void) const								= 0;
107 	virtual VkDeviceSize		getVertexStride					(void) const								= 0;
108 	virtual VkDeviceSize		getAABBStride					(void) const								= 0;
109 	virtual size_t				getVertexByteSize				(void) const								= 0;
110 	virtual deUint32			getIndexCount					(void) const								= 0;
111 	virtual const deUint8*		getIndexPointer					(void) const								= 0;
112 	virtual VkDeviceSize		getIndexStride					(void) const								= 0;
113 	virtual size_t				getIndexByteSize				(void) const								= 0;
114 	virtual deUint32			getPrimitiveCount				(void) const								= 0;
115 	virtual void				addVertex						(const tcu::Vec3& vertex)					= 0;
116 	virtual void				addIndex						(const deUint32& index)						= 0;
117 private:
118 	VkGeometryTypeKHR			m_geometryType;
119 	VkFormat					m_vertexFormat;
120 	VkIndexType					m_indexType;
121 	VkGeometryFlagsKHR			m_geometryFlags;
122 	bool						m_hasOpacityMicromap;
123 	VkAccelerationStructureTrianglesOpacityMicromapEXT	m_opacityGeometryMicromap;
124 };
125 
126 template <typename T>
convertSatRte(float f)127 inline T convertSatRte (float f)
128 {
129 	// \note Doesn't work for 64-bit types
130 	DE_STATIC_ASSERT(sizeof(T) < sizeof(deUint64));
131 	DE_STATIC_ASSERT((-3 % 2 != 0) && (-4 % 2 == 0));
132 
133 	deInt64	minVal	= std::numeric_limits<T>::min();
134 	deInt64 maxVal	= std::numeric_limits<T>::max();
135 	float	q		= deFloatFrac(f);
136 	deInt64 intVal	= (deInt64)(f-q);
137 
138 	// Rounding.
139 	if (q == 0.5f)
140 	{
141 		if (intVal % 2 != 0)
142 			intVal++;
143 	}
144 	else if (q > 0.5f)
145 		intVal++;
146 	// else Don't add anything
147 
148 	// Saturate.
149 	intVal = de::max(minVal, de::min(maxVal, intVal));
150 
151 	return (T)intVal;
152 }
153 
154 // Converts float to signed integer with variable width.
155 // Source float is assumed to be in the [-1, 1] range.
156 template <typename T>
deFloat32ToSNorm(float src)157 inline T deFloat32ToSNorm (float src)
158 {
159 	DE_STATIC_ASSERT(std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed);
160 	const T range	= std::numeric_limits<T>::max();
161 	const T intVal	= convertSatRte<T>(src * static_cast<float>(range));
162 	return de::clamp<T>(intVal, -range, range);
163 }
164 
165 typedef tcu::Vector<deFloat16, 2>			Vec2_16;
166 typedef tcu::Vector<deFloat16, 3>			Vec3_16;
167 typedef tcu::Vector<deFloat16, 4>			Vec4_16;
168 typedef tcu::Vector<deInt16, 2>				Vec2_16SNorm;
169 typedef tcu::Vector<deInt16, 3>				Vec3_16SNorm;
170 typedef tcu::Vector<deInt16, 4>				Vec4_16SNorm;
171 typedef tcu::Vector<deInt8, 2>				Vec2_8SNorm;
172 typedef tcu::Vector<deInt8, 3>				Vec3_8SNorm;
173 typedef tcu::Vector<deInt8, 4>				Vec4_8SNorm;
174 
175 template<typename V>	VkFormat			vertexFormatFromType				();
vertexFormatFromType()176 template<>				inline VkFormat		vertexFormatFromType<tcu::Vec2>		()							{ return VK_FORMAT_R32G32_SFLOAT; }
vertexFormatFromType()177 template<>				inline VkFormat		vertexFormatFromType<tcu::Vec3>		()							{ return VK_FORMAT_R32G32B32_SFLOAT; }
vertexFormatFromType()178 template<>				inline VkFormat		vertexFormatFromType<tcu::Vec4>		()							{ return VK_FORMAT_R32G32B32A32_SFLOAT; }
vertexFormatFromType()179 template<>				inline VkFormat		vertexFormatFromType<Vec2_16>		()							{ return VK_FORMAT_R16G16_SFLOAT; }
vertexFormatFromType()180 template<>				inline VkFormat		vertexFormatFromType<Vec3_16>		()							{ return VK_FORMAT_R16G16B16_SFLOAT; }
vertexFormatFromType()181 template<>				inline VkFormat		vertexFormatFromType<Vec4_16>		()							{ return VK_FORMAT_R16G16B16A16_SFLOAT; }
vertexFormatFromType()182 template<>				inline VkFormat		vertexFormatFromType<Vec2_16SNorm>	()							{ return VK_FORMAT_R16G16_SNORM; }
vertexFormatFromType()183 template<>				inline VkFormat		vertexFormatFromType<Vec3_16SNorm>	()							{ return VK_FORMAT_R16G16B16_SNORM; }
vertexFormatFromType()184 template<>				inline VkFormat		vertexFormatFromType<Vec4_16SNorm>	()							{ return VK_FORMAT_R16G16B16A16_SNORM; }
vertexFormatFromType()185 template<>				inline VkFormat		vertexFormatFromType<tcu::DVec2>	()							{ return VK_FORMAT_R64G64_SFLOAT; }
vertexFormatFromType()186 template<>				inline VkFormat		vertexFormatFromType<tcu::DVec3>	()							{ return VK_FORMAT_R64G64B64_SFLOAT; }
vertexFormatFromType()187 template<>				inline VkFormat		vertexFormatFromType<tcu::DVec4>	()							{ return VK_FORMAT_R64G64B64A64_SFLOAT; }
vertexFormatFromType()188 template<>				inline VkFormat		vertexFormatFromType<Vec2_8SNorm>	()							{ return VK_FORMAT_R8G8_SNORM; }
vertexFormatFromType()189 template<>				inline VkFormat		vertexFormatFromType<Vec3_8SNorm>	()							{ return VK_FORMAT_R8G8B8_SNORM; }
vertexFormatFromType()190 template<>				inline VkFormat		vertexFormatFromType<Vec4_8SNorm>	()							{ return VK_FORMAT_R8G8B8A8_SNORM; }
191 
192 struct EmptyIndex {};
193 template<typename I>	VkIndexType			indexTypeFromType					();
indexTypeFromType()194 template<>				inline VkIndexType	indexTypeFromType<deUint16>			()							{ return VK_INDEX_TYPE_UINT16; }
indexTypeFromType()195 template<>				inline VkIndexType	indexTypeFromType<deUint32>			()							{ return VK_INDEX_TYPE_UINT32; }
indexTypeFromType()196 template<>				inline VkIndexType	indexTypeFromType<EmptyIndex>		()							{ return VK_INDEX_TYPE_NONE_KHR; }
197 
198 template<typename V>	V					convertFloatTo						(const tcu::Vec3& vertex);
convertFloatTo(const tcu::Vec3 & vertex)199 template<>				inline tcu::Vec2	convertFloatTo<tcu::Vec2>			(const tcu::Vec3& vertex)	{ return tcu::Vec2(vertex.x(), vertex.y()); }
convertFloatTo(const tcu::Vec3 & vertex)200 template<>				inline tcu::Vec3	convertFloatTo<tcu::Vec3>			(const tcu::Vec3& vertex)	{ return vertex; }
convertFloatTo(const tcu::Vec3 & vertex)201 template<>				inline tcu::Vec4	convertFloatTo<tcu::Vec4>			(const tcu::Vec3& vertex)	{ return tcu::Vec4(vertex.x(), vertex.y(), vertex.z(), 0.0f); }
convertFloatTo(const tcu::Vec3 & vertex)202 template<>				inline Vec2_16		convertFloatTo<Vec2_16>				(const tcu::Vec3& vertex)	{ return Vec2_16(deFloat32To16(vertex.x()), deFloat32To16(vertex.y())); }
convertFloatTo(const tcu::Vec3 & vertex)203 template<>				inline Vec3_16		convertFloatTo<Vec3_16>				(const tcu::Vec3& vertex)	{ return Vec3_16(deFloat32To16(vertex.x()), deFloat32To16(vertex.y()), deFloat32To16(vertex.z())); }
convertFloatTo(const tcu::Vec3 & vertex)204 template<>				inline Vec4_16		convertFloatTo<Vec4_16>				(const tcu::Vec3& vertex)	{ return Vec4_16(deFloat32To16(vertex.x()), deFloat32To16(vertex.y()), deFloat32To16(vertex.z()), deFloat32To16(0.0f)); }
convertFloatTo(const tcu::Vec3 & vertex)205 template<>				inline Vec2_16SNorm	convertFloatTo<Vec2_16SNorm>		(const tcu::Vec3& vertex)	{ return Vec2_16SNorm(deFloat32ToSNorm<deInt16>(vertex.x()), deFloat32ToSNorm<deInt16>(vertex.y())); }
convertFloatTo(const tcu::Vec3 & vertex)206 template<>				inline Vec3_16SNorm	convertFloatTo<Vec3_16SNorm>		(const tcu::Vec3& vertex)	{ return Vec3_16SNorm(deFloat32ToSNorm<deInt16>(vertex.x()), deFloat32ToSNorm<deInt16>(vertex.y()), deFloat32ToSNorm<deInt16>(vertex.z())); }
convertFloatTo(const tcu::Vec3 & vertex)207 template<>				inline Vec4_16SNorm	convertFloatTo<Vec4_16SNorm>		(const tcu::Vec3& vertex)	{ return Vec4_16SNorm(deFloat32ToSNorm<deInt16>(vertex.x()), deFloat32ToSNorm<deInt16>(vertex.y()), deFloat32ToSNorm<deInt16>(vertex.z()), deFloat32ToSNorm<deInt16>(0.0f)); }
convertFloatTo(const tcu::Vec3 & vertex)208 template<>				inline tcu::DVec2	convertFloatTo<tcu::DVec2>			(const tcu::Vec3& vertex)	{ return tcu::DVec2(static_cast<double>(vertex.x()), static_cast<double>(vertex.y())); }
convertFloatTo(const tcu::Vec3 & vertex)209 template<>				inline tcu::DVec3	convertFloatTo<tcu::DVec3>			(const tcu::Vec3& vertex)	{ return tcu::DVec3(static_cast<double>(vertex.x()), static_cast<double>(vertex.y()), static_cast<double>(vertex.z())); }
convertFloatTo(const tcu::Vec3 & vertex)210 template<>				inline tcu::DVec4	convertFloatTo<tcu::DVec4>			(const tcu::Vec3& vertex)	{ return tcu::DVec4(static_cast<double>(vertex.x()), static_cast<double>(vertex.y()), static_cast<double>(vertex.z()), 0.0); }
convertFloatTo(const tcu::Vec3 & vertex)211 template<>				inline Vec2_8SNorm	convertFloatTo<Vec2_8SNorm>			(const tcu::Vec3& vertex)	{ return Vec2_8SNorm(deFloat32ToSNorm<deInt8>(vertex.x()), deFloat32ToSNorm<deInt8>(vertex.y())); }
convertFloatTo(const tcu::Vec3 & vertex)212 template<>				inline Vec3_8SNorm	convertFloatTo<Vec3_8SNorm>			(const tcu::Vec3& vertex)	{ return Vec3_8SNorm(deFloat32ToSNorm<deInt8>(vertex.x()), deFloat32ToSNorm<deInt8>(vertex.y()), deFloat32ToSNorm<deInt8>(vertex.z())); }
convertFloatTo(const tcu::Vec3 & vertex)213 template<>				inline Vec4_8SNorm	convertFloatTo<Vec4_8SNorm>			(const tcu::Vec3& vertex)	{ return Vec4_8SNorm(deFloat32ToSNorm<deInt8>(vertex.x()), deFloat32ToSNorm<deInt8>(vertex.y()), deFloat32ToSNorm<deInt8>(vertex.z()), deFloat32ToSNorm<deInt8>(0.0f)); }
214 
215 template<typename V>	V					convertIndexTo						(deUint32 index);
convertIndexTo(deUint32 index)216 template<>				inline EmptyIndex	convertIndexTo<EmptyIndex>			(deUint32 index)			{ DE_UNREF(index); TCU_THROW(TestError, "Cannot add empty index"); }
convertIndexTo(deUint32 index)217 template<>				inline deUint16		convertIndexTo<deUint16>			(deUint32 index)			{ return static_cast<deUint16>(index); }
convertIndexTo(deUint32 index)218 template<>				inline deUint32		convertIndexTo<deUint32>			(deUint32 index)			{ return index; }
219 
220 template<typename V, typename I>
221 class RaytracedGeometry : public RaytracedGeometryBase
222 {
223 public:
224 						RaytracedGeometry			()									= delete;
225 						RaytracedGeometry			(const RaytracedGeometry& geometry)	= delete;
226 						RaytracedGeometry			(VkGeometryTypeKHR geometryType, deUint32 paddingBlocks = 0u);
227 						RaytracedGeometry			(VkGeometryTypeKHR geometryType, const std::vector<V>& vertices, const std::vector<I>& indices = std::vector<I>(), deUint32 paddingBlocks = 0u);
228 
229 	deUint32			getVertexCount				(void) const override;
230 	const deUint8*		getVertexPointer			(void) const override;
231 	VkDeviceSize		getVertexStride				(void) const override;
232 	VkDeviceSize		getAABBStride				(void) const override;
233 	size_t				getVertexByteSize			(void) const override;
234 	deUint32			getIndexCount				(void) const override;
235 	const deUint8*		getIndexPointer				(void) const override;
236 	VkDeviceSize		getIndexStride				(void) const override;
237 	size_t				getIndexByteSize			(void) const override;
238 	deUint32			getPrimitiveCount			(void) const override;
239 
240 	void				addVertex					(const tcu::Vec3& vertex) override;
241 	void				addIndex					(const deUint32& index) override;
242 
243 private:
244 	void				init						();					// To be run in constructors.
245 	void				checkGeometryType			() const;			// Checks geometry type is valid.
246 	void				calcBlockSize				();					// Calculates and saves vertex buffer block size.
247 	size_t				getBlockSize				() const;			// Return stored vertex buffer block size.
248 	void				addNativeVertex				(const V& vertex);	// Adds new vertex in native format.
249 
250 	// The implementation below stores vertices as byte blocks to take the requested padding into account. m_vertices is the array
251 	// of bytes containing vertex data.
252 	//
253 	// For triangles, the padding block has a size that is a multiple of the vertex size and each vertex is stored in a byte block
254 	// equivalent to:
255 	//
256 	//	struct Vertex
257 	//	{
258 	//		V		vertex;
259 	//		deUint8	padding[m_paddingBlocks * sizeof(V)];
260 	//	};
261 	//
262 	// For AABBs, the padding block has a size that is a multiple of kAABBPadBaseSize (see below) and vertices are stored in pairs
263 	// before the padding block. This is equivalent to:
264 	//
265 	//		struct VertexPair
266 	//		{
267 	//			V		vertices[2];
268 	//			deUint8	padding[m_paddingBlocks * kAABBPadBaseSize];
269 	//		};
270 	//
271 	// The size of each pseudo-structure above is saved to one of the correspoding union members below.
272 	union BlockSize
273 	{
274 		size_t trianglesBlockSize;
275 		size_t aabbsBlockSize;
276 	};
277 
278 	const deUint32			m_paddingBlocks;
279 	size_t					m_vertexCount;
280 	std::vector<deUint8>	m_vertices;			// Vertices are stored as byte blocks.
281 	std::vector<I>			m_indices;			// Indices are stored natively.
282 	BlockSize				m_blockSize;		// For m_vertices.
283 
284 	// Data sizes.
285 	static constexpr size_t	kVertexSize			= sizeof(V);
286 	static constexpr size_t	kIndexSize			= sizeof(I);
287 	static constexpr size_t	kAABBPadBaseSize	= 8; // As required by the spec.
288 };
289 
290 template<typename V, typename I>
RaytracedGeometry(VkGeometryTypeKHR geometryType,deUint32 paddingBlocks)291 RaytracedGeometry<V, I>::RaytracedGeometry (VkGeometryTypeKHR geometryType, deUint32 paddingBlocks)
292 	: RaytracedGeometryBase(geometryType, vertexFormatFromType<V>(), indexTypeFromType<I>())
293 	, m_paddingBlocks(paddingBlocks)
294 	, m_vertexCount(0)
295 {
296 	init();
297 }
298 
299 template<typename V, typename I>
RaytracedGeometry(VkGeometryTypeKHR geometryType,const std::vector<V> & vertices,const std::vector<I> & indices,deUint32 paddingBlocks)300 RaytracedGeometry<V,I>::RaytracedGeometry (VkGeometryTypeKHR geometryType, const std::vector<V>& vertices, const std::vector<I>& indices, deUint32 paddingBlocks)
301 	: RaytracedGeometryBase(geometryType, vertexFormatFromType<V>(), indexTypeFromType<I>())
302 	, m_paddingBlocks(paddingBlocks)
303 	, m_vertexCount(0)
304 	, m_vertices()
305 	, m_indices(indices)
306 {
307 	init();
308 	for (const auto& vertex : vertices)
309 		addNativeVertex(vertex);
310 }
311 
312 template<typename V, typename I>
getVertexCount(void) const313 deUint32 RaytracedGeometry<V,I>::getVertexCount (void) const
314 {
315 	return (isTrianglesType() ? static_cast<deUint32>(m_vertexCount) : 0u);
316 }
317 
318 template<typename V, typename I>
getVertexPointer(void) const319 const deUint8* RaytracedGeometry<V, I>::getVertexPointer (void) const
320 {
321 	DE_ASSERT(!m_vertices.empty());
322 	return reinterpret_cast<const deUint8*>(m_vertices.data());
323 }
324 
325 template<typename V, typename I>
getVertexStride(void) const326 VkDeviceSize RaytracedGeometry<V,I>::getVertexStride (void) const
327 {
328 	return ((!isTrianglesType()) ? 0ull : static_cast<VkDeviceSize>(getBlockSize()));
329 }
330 
331 template<typename V, typename I>
getAABBStride(void) const332 VkDeviceSize RaytracedGeometry<V, I>::getAABBStride (void) const
333 {
334 	return (isTrianglesType() ? 0ull : static_cast<VkDeviceSize>(getBlockSize()));
335 }
336 
337 template<typename V, typename I>
getVertexByteSize(void) const338 size_t RaytracedGeometry<V, I>::getVertexByteSize (void) const
339 {
340 	return m_vertices.size();
341 }
342 
343 template<typename V, typename I>
getIndexCount(void) const344 deUint32 RaytracedGeometry<V, I>::getIndexCount (void) const
345 {
346 	return static_cast<deUint32>(isTrianglesType() ? m_indices.size() : 0);
347 }
348 
349 template<typename V, typename I>
getIndexPointer(void) const350 const deUint8* RaytracedGeometry<V, I>::getIndexPointer (void) const
351 {
352 	const auto indexCount = getIndexCount();
353 	DE_UNREF(indexCount); // For release builds.
354 	DE_ASSERT(indexCount > 0u);
355 
356 	return reinterpret_cast<const deUint8*>(m_indices.data());
357 }
358 
359 template<typename V, typename I>
getIndexStride(void) const360 VkDeviceSize RaytracedGeometry<V, I>::getIndexStride (void) const
361 {
362 	return static_cast<VkDeviceSize>(kIndexSize);
363 }
364 
365 template<typename V, typename I>
getIndexByteSize(void) const366 size_t RaytracedGeometry<V, I>::getIndexByteSize (void) const
367 {
368 	const auto indexCount = getIndexCount();
369 	DE_ASSERT(indexCount > 0u);
370 
371 	return (indexCount * kIndexSize);
372 }
373 
374 template<typename V, typename I>
getPrimitiveCount(void) const375 deUint32 RaytracedGeometry<V,I>::getPrimitiveCount (void) const
376 {
377 	return static_cast<deUint32>(isTrianglesType() ? (usesIndices() ? m_indices.size() / 3 : m_vertexCount / 3) : (m_vertexCount / 2));
378 }
379 
380 template<typename V, typename I>
addVertex(const tcu::Vec3 & vertex)381 void RaytracedGeometry<V, I>::addVertex (const tcu::Vec3& vertex)
382 {
383 	addNativeVertex(convertFloatTo<V>(vertex));
384 }
385 
386 template<typename V, typename I>
addNativeVertex(const V & vertex)387 void RaytracedGeometry<V, I>::addNativeVertex (const V& vertex)
388 {
389 	const auto oldSize			= m_vertices.size();
390 	const auto blockSize		= getBlockSize();
391 
392 	if (isTrianglesType())
393 	{
394 		// Reserve new block, copy vertex at the beginning of the new block.
395 		m_vertices.resize(oldSize + blockSize, deUint8{0});
396 		deMemcpy(&m_vertices[oldSize], &vertex, kVertexSize);
397 	}
398 	else // AABB
399 	{
400 		if (m_vertexCount % 2 == 0)
401 		{
402 			// New block needed.
403 			m_vertices.resize(oldSize + blockSize, deUint8{0});
404 			deMemcpy(&m_vertices[oldSize], &vertex, kVertexSize);
405 		}
406 		else
407 		{
408 			// Insert in the second position of last existing block.
409 			//
410 			//												Vertex Size
411 			//												+-------+
412 			//	+-------------+------------+----------------------------------------+
413 			//	|             |            |      ...       | vertex vertex padding |
414 			//	+-------------+------------+----------------+-----------------------+
415 			//												+-----------------------+
416 			//														Block Size
417 			//	+-------------------------------------------------------------------+
418 			//							Old Size
419 			//
420 			deMemcpy(&m_vertices[oldSize - blockSize + kVertexSize], &vertex, kVertexSize);
421 		}
422 	}
423 
424 	++m_vertexCount;
425 }
426 
427 template<typename V, typename I>
addIndex(const deUint32 & index)428 void RaytracedGeometry<V, I>::addIndex (const deUint32& index)
429 {
430 	m_indices.push_back(convertIndexTo<I>(index));
431 }
432 
433 template<typename V, typename I>
init()434 void RaytracedGeometry<V, I>::init ()
435 {
436 	checkGeometryType();
437 	calcBlockSize();
438 }
439 
440 template<typename V, typename I>
checkGeometryType() const441 void RaytracedGeometry<V, I>::checkGeometryType () const
442 {
443 	const auto geometryType = getGeometryType();
444 	DE_UNREF(geometryType); // For release builds.
445 	DE_ASSERT(geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR || geometryType == VK_GEOMETRY_TYPE_AABBS_KHR);
446 }
447 
448 template<typename V, typename I>
calcBlockSize()449 void RaytracedGeometry<V, I>::calcBlockSize ()
450 {
451 	if (isTrianglesType())
452 		m_blockSize.trianglesBlockSize = kVertexSize * static_cast<size_t>(1u + m_paddingBlocks);
453 	else
454 		m_blockSize.aabbsBlockSize = 2 * kVertexSize + m_paddingBlocks * kAABBPadBaseSize;
455 }
456 
457 template<typename V, typename I>
getBlockSize() const458 size_t RaytracedGeometry<V, I>::getBlockSize () const
459 {
460 	return (isTrianglesType() ? m_blockSize.trianglesBlockSize : m_blockSize.aabbsBlockSize);
461 }
462 
463 de::SharedPtr<RaytracedGeometryBase> makeRaytracedGeometry (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType, bool padVertices = false);
464 
465 VkDeviceAddress getBufferDeviceAddress ( const DeviceInterface&	vkd,
466 										 const VkDevice			device,
467 										 const VkBuffer			buffer,
468 										 VkDeviceSize			offset );
469 
470 // type used for creating a deep serialization/deserialization of top-level acceleration structures
471 class SerialInfo
472 {
473 	std::vector<deUint64>		m_addresses;
474 	std::vector<VkDeviceSize>	m_sizes;
475 public:
476 
477 	SerialInfo() = default;
478 
479 	// addresses: { (owner-top-level AS address) [, (first bottom_level AS address), (second bottom_level AS address), ...] }
480 	// sizes:     { (owner-top-level AS serial size) [, (first bottom_level AS serial size), (second bottom_level AS serial size), ...] }
SerialInfo(const std::vector<deUint64> & addresses,const std::vector<VkDeviceSize> & sizes)481 	SerialInfo(const std::vector<deUint64>& addresses, const std::vector<VkDeviceSize>& sizes)
482 		: m_addresses(addresses), m_sizes(sizes)
483 	{
484 		DE_ASSERT(!addresses.empty() && addresses.size() == sizes.size());
485 	}
486 
addresses() const487 	const std::vector<deUint64>&		addresses			() const	{ return m_addresses; }
sizes() const488 	const std::vector<VkDeviceSize>&	sizes				() const	{ return m_sizes; }
489 };
490 
491 class SerialStorage
492 {
493 public:
494 	enum
495 	{
496 		DE_SERIALIZED_FIELD(DRIVER_UUID,		VK_UUID_SIZE),		// VK_UUID_SIZE bytes of data matching VkPhysicalDeviceIDProperties::driverUUID
497 		DE_SERIALIZED_FIELD(COMPAT_UUID,		VK_UUID_SIZE),		// VK_UUID_SIZE bytes of data identifying the compatibility for comparison using vkGetDeviceAccelerationStructureCompatibilityKHR
498 		DE_SERIALIZED_FIELD(SERIALIZED_SIZE,	sizeof(deUint64)),	// A 64-bit integer of the total size matching the value queried using VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR
499 		DE_SERIALIZED_FIELD(DESERIALIZED_SIZE,	sizeof(deUint64)),	// A 64-bit integer of the deserialized size to be passed in to VkAccelerationStructureCreateInfoKHR::size
500 		DE_SERIALIZED_FIELD(HANDLES_COUNT,		sizeof(deUint64)),	// A 64-bit integer of the count of the number of acceleration structure handles following. This will be zero for a bottom-level acceleration structure.
501 		SERIAL_STORAGE_SIZE_MIN
502 	};
503 
504 	// An old fashion C-style structure that simplifies an access to the AS header
505 	struct alignas(16) AccelerationStructureHeader
506 	{
507 		union {
508 			struct {
509 				deUint8	driverUUID[VK_UUID_SIZE];
510 				deUint8	compactUUID[VK_UUID_SIZE];
511 			};
512 			deUint8		uuids[VK_UUID_SIZE * 2];
513 		};
514 		deUint64		serializedSize;
515 		deUint64		deserializedSize;
516 		deUint64		handleCount;
517 		VkDeviceAddress	handleArray[1];
518 	};
519 
520 											SerialStorage		() = delete;
521 											SerialStorage		(const DeviceInterface&						vk,
522 																 const VkDevice								device,
523 																 Allocator&									allocator,
524 																 const VkAccelerationStructureBuildTypeKHR	buildType,
525 																 const VkDeviceSize							storageSize);
526 	// An additional constructor for creating a deep copy of top-level AS's.
527 											SerialStorage		(const DeviceInterface&						vk,
528 																 const VkDevice								device,
529 																 Allocator&									allocator,
530 																 const VkAccelerationStructureBuildTypeKHR	buildType,
531 																 const SerialInfo&							SerialInfo);
532 
533 	// below methods will return host addres if AS was build on cpu and device addres when it was build on gpu
534 	VkDeviceOrHostAddressKHR				getAddress			(const DeviceInterface&						vk,
535 																 const VkDevice								device,
536 																 const VkAccelerationStructureBuildTypeKHR	buildType);
537 	VkDeviceOrHostAddressConstKHR			getAddressConst		(const DeviceInterface&						vk,
538 																 const VkDevice								device,
539 																 const VkAccelerationStructureBuildTypeKHR	buildType);
540 
541 	// this methods retun host address regardless of where AS was built
542 	VkDeviceOrHostAddressKHR				getHostAddress		(VkDeviceSize			offset = 0);
543 	VkDeviceOrHostAddressConstKHR			getHostAddressConst	(VkDeviceSize			offset = 0);
544 
545 	// works the similar way as getHostAddressConst() but returns more readable/intuitive object
546 	AccelerationStructureHeader*			getASHeader			();
547 	bool									hasDeepFormat		() const;
548 	de::SharedPtr<SerialStorage>			getBottomStorage	(deUint32			index) const;
549 
550 	VkDeviceSize							getStorageSize		() const;
551 	const SerialInfo&						getSerialInfo		() const;
552 	deUint64								getDeserializedSize	();
553 
554 protected:
555 	const VkAccelerationStructureBuildTypeKHR	m_buildType;
556 	const VkDeviceSize							m_storageSize;
557 	const SerialInfo							m_serialInfo;
558 	de::MovePtr<BufferWithMemory>				m_buffer;
559 	std::vector<de::SharedPtr<SerialStorage>>	m_bottoms;
560 };
561 
562 class BottomLevelAccelerationStructure
563 {
564 public:
565 	static deUint32										getRequiredAllocationCount				(void);
566 
567 														BottomLevelAccelerationStructure		();
568 														BottomLevelAccelerationStructure		(const BottomLevelAccelerationStructure&		other) = delete;
569 	virtual												~BottomLevelAccelerationStructure		();
570 
571 	virtual void										setGeometryData							(const std::vector<tcu::Vec3>&					geometryData,
572 																								 const bool										triangles,
573 																								 const VkGeometryFlagsKHR						geometryFlags			= 0u );
574 	virtual void										setDefaultGeometryData					(const VkShaderStageFlagBits					testStage,
575 																								 const VkGeometryFlagsKHR						geometryFlags			= 0u );
576 	virtual void										setGeometryCount						(const size_t									geometryCount);
577 	virtual void										addGeometry								(de::SharedPtr<RaytracedGeometryBase>&			raytracedGeometry);
578 	virtual void										addGeometry								(const std::vector<tcu::Vec3>&					geometryData,
579 																								 const bool										triangles,
580 																								 const VkGeometryFlagsKHR						geometryFlags			= 0u,
581 																								 const VkAccelerationStructureTrianglesOpacityMicromapEXT *opacityGeometryMicromap = DE_NULL );
582 
583 	virtual void										setBuildType							(const VkAccelerationStructureBuildTypeKHR		buildType) = DE_NULL;
584 	virtual VkAccelerationStructureBuildTypeKHR			getBuildType							() const = 0;
585 	virtual void										setCreateFlags							(const VkAccelerationStructureCreateFlagsKHR	createFlags) = DE_NULL;
586 	virtual void										setCreateGeneric						(bool											createGeneric) = 0;
587 	virtual void										setCreationBufferUnbounded				(bool											creationBufferUnbounded) = 0;
588 	virtual void										setBuildFlags							(const VkBuildAccelerationStructureFlagsKHR		buildFlags) = DE_NULL;
589 	virtual void										setBuildWithoutGeometries				(bool											buildWithoutGeometries) = 0;
590 	virtual void										setBuildWithoutPrimitives				(bool											buildWithoutPrimitives) = 0;
591 	virtual void										setDeferredOperation					(const bool										deferredOperation,
592 																								 const deUint32									workerThreadCount		= 0u ) = DE_NULL;
593 	virtual void										setUseArrayOfPointers					(const bool										useArrayOfPointers) = DE_NULL;
594 	virtual void										setUseMaintenance5						(const bool										useMaintenance5) = DE_NULL;
595 	virtual void										setIndirectBuildParameters				(const VkBuffer									indirectBuffer,
596 																								 const VkDeviceSize								indirectBufferOffset,
597 																								 const deUint32									indirectBufferStride) = DE_NULL;
598 	virtual VkBuildAccelerationStructureFlagsKHR		getBuildFlags							() const = DE_NULL;
599 	VkAccelerationStructureBuildSizesInfoKHR			getStructureBuildSizes					() const;
600 
601 	// methods specific for each acceleration structure
602 	virtual void										create									(const DeviceInterface&							vk,
603 																								 const VkDevice									device,
604 																								 Allocator&										allocator,
605 																								 VkDeviceSize									structureSize,
606 																								 VkDeviceAddress								deviceAddress			= 0u,
607 																								 const void*									pNext					= DE_NULL,
608 																								 const MemoryRequirement&						addMemoryRequirement	= MemoryRequirement::Any,
609 																								 const VkBuffer									creationBuffer			= VK_NULL_HANDLE,
610 																								 const VkDeviceSize								creationBufferSize		= 0u) = DE_NULL;
611 	virtual void										build									(const DeviceInterface&							vk,
612 																								 const VkDevice									device,
613 																								 const VkCommandBuffer							cmdBuffer,
614 																								 BottomLevelAccelerationStructure*				srcAccelerationStructure = DE_NULL) = DE_NULL;
615 	virtual void										copyFrom								(const DeviceInterface&							vk,
616 																								 const VkDevice									device,
617 																								 const VkCommandBuffer							cmdBuffer,
618 																								 BottomLevelAccelerationStructure*				accelerationStructure,
619 																								 bool											compactCopy) = DE_NULL;
620 
621 	virtual void										serialize								(const DeviceInterface&							vk,
622 																								 const VkDevice									device,
623 																								 const VkCommandBuffer							cmdBuffer,
624 																								 SerialStorage*									storage) = DE_NULL;
625 	virtual void										deserialize								(const DeviceInterface&							vk,
626 																								 const VkDevice									device,
627 																								 const VkCommandBuffer							cmdBuffer,
628 																								 SerialStorage*									storage) = DE_NULL;
629 
630 	// helper methods for typical acceleration structure creation tasks
631 	void												createAndBuild							(const DeviceInterface&							vk,
632 																								 const VkDevice									device,
633 																								 const VkCommandBuffer							cmdBuffer,
634 																								 Allocator&										allocator,
635 																								 VkDeviceAddress								deviceAddress			= 0u );
636 	void												createAndCopyFrom						(const DeviceInterface&							vk,
637 																								 const VkDevice									device,
638 																								 const VkCommandBuffer							cmdBuffer,
639 																								 Allocator&										allocator,
640 																								 BottomLevelAccelerationStructure*				accelerationStructure,
641 																								 VkDeviceSize									compactCopySize			= 0u,
642 																								 VkDeviceAddress								deviceAddress			= 0u);
643 	void												createAndDeserializeFrom				(const DeviceInterface&							vk,
644 																								 const VkDevice									device,
645 																								 const VkCommandBuffer							cmdBuffer,
646 																								 Allocator&										allocator,
647 																								 SerialStorage*									storage,
648 																								 VkDeviceAddress								deviceAddress			= 0u);
649 	virtual const VkAccelerationStructureKHR*			getPtr									(void) const = DE_NULL;
650 	virtual void										updateGeometry							(size_t											geometryIndex,
651 																								 de::SharedPtr<RaytracedGeometryBase>&			raytracedGeometry) = DE_NULL;
652 
653 protected:
654 	std::vector<de::SharedPtr<RaytracedGeometryBase>>	m_geometriesData;
655 	VkDeviceSize										m_structureSize;
656 	VkDeviceSize										m_updateScratchSize;
657 	VkDeviceSize										m_buildScratchSize;
658 };
659 
660 de::MovePtr<BottomLevelAccelerationStructure> makeBottomLevelAccelerationStructure ();
661 
662 /**
663  * @brief Implements a pool of BottomLevelAccelerationStructure
664  */
665 class BottomLevelAccelerationStructurePool
666 {
667 public:
668 	typedef de::SharedPtr<BottomLevelAccelerationStructure>	BlasPtr;
669 	struct BlasInfo {
670 		VkDeviceSize	structureSize;
671 		VkDeviceAddress	deviceAddress;
672 	};
673 
674 	BottomLevelAccelerationStructurePool();
675 	virtual ~BottomLevelAccelerationStructurePool();
676 
at(deUint32 index) const677 	BlasPtr		at					(deUint32 index) const	{ return m_structs[index]; }
operator [](deUint32 index) const678 	BlasPtr		operator[]			(deUint32 index) const	{ return m_structs[index]; }
structures() const679 	auto		structures			() const -> const std::vector<BlasPtr>& { return m_structs; }
structCount() const680 	deUint32	structCount			() const { return static_cast<deUint32>(m_structs.size()); }
681 
682 	// defines how many structures will be packet in single buffer
batchStructCount() const683 	deUint32	batchStructCount	() const {return m_batchStructCount; }
684 	void		batchStructCount	(const	deUint32& value);
685 
686 	// defines how many geometries (vertices and/or indices) will be packet in single buffer
batchGeomCount() const687 	deUint32	batchGeomCount		() const {return m_batchGeomCount; }
batchGeomCount(const deUint32 & value)688 	void		batchGeomCount		(const	deUint32& value) { m_batchGeomCount = value; }
689 
tryCachedMemory() const690 	bool		tryCachedMemory		() const { return m_tryCachedMemory; }
tryCachedMemory(const bool cachedMemory)691 	void		tryCachedMemory		(const bool	cachedMemory) { m_tryCachedMemory = cachedMemory; }
692 
693 	BlasPtr		add					(VkDeviceSize			structureSize = 0,
694 									 VkDeviceAddress		deviceAddress = 0);
695 	/**
696 	 * @brief Creates previously added bottoms at a time.
697 	 * @note  All geometries must be known before call this method.
698 	 */
699 	void		batchCreate			(const DeviceInterface&		vkd,
700 									 const VkDevice				device,
701 									 Allocator&					allocator);
702 	void		batchCreateAdjust	(const DeviceInterface&		vkd,
703 									 const VkDevice				device,
704 									 Allocator&					allocator,
705 									 const VkDeviceSize			maxBufferSize);
706 	void		batchBuild			(const DeviceInterface&		vk,
707 									 const VkDevice				device,
708 									 VkCommandBuffer			cmdBuffer);
709 	void		batchBuild			(const DeviceInterface&		vk,
710 									 const VkDevice				device,
711 									 VkCommandPool				cmdPool,
712 									 VkQueue					queue,
713 									 qpWatchDog*				watchDog);
714 	size_t		getAllocationCount	() const;
715 	size_t		getAllocationCount	(const DeviceInterface&		vk,
716 									 const VkDevice				device,
717 									 const VkDeviceSize			maxBufferSize) const;
718 	auto		getAllocationSizes	(const DeviceInterface&		vk,	// (strBuff, scratchBuff, vertBuff, indexBuff)
719 									 const VkDevice				device) const -> tcu::Vector<VkDeviceSize, 4>;
720 protected:
721 	deUint32				m_batchStructCount; // default is 4
722 	deUint32				m_batchGeomCount; // default is 0, if zero then batchStructCount is used
723 	std::vector<BlasInfo>	m_infos;
724 	std::vector<BlasPtr>	m_structs;
725 	bool					m_createOnce;
726 	bool					m_tryCachedMemory;
727 	VkDeviceSize			m_structsBuffSize;
728 	VkDeviceSize			m_updatesScratchSize;
729 	VkDeviceSize			m_buildsScratchSize;
730 	VkDeviceSize			m_verticesSize;
731 	VkDeviceSize			m_indicesSize;
732 
733 protected:
734 	struct Impl;
735 	Impl*					m_impl;
736 };
737 
738 struct InstanceData
739 {
InstanceDatavk::InstanceData740 								InstanceData (VkTransformMatrixKHR							matrix_,
741 											  deUint32										instanceCustomIndex_,
742 											  deUint32										mask_,
743 											  deUint32										instanceShaderBindingTableRecordOffset_,
744 											  VkGeometryInstanceFlagsKHR					flags_)
745 									: matrix(matrix_), instanceCustomIndex(instanceCustomIndex_), mask(mask_), instanceShaderBindingTableRecordOffset(instanceShaderBindingTableRecordOffset_), flags(flags_)
746 								{
747 								}
748 	VkTransformMatrixKHR		matrix;
749 	deUint32					instanceCustomIndex;
750 	deUint32					mask;
751 	deUint32					instanceShaderBindingTableRecordOffset;
752 	VkGeometryInstanceFlagsKHR	flags;
753 };
754 
755 class TopLevelAccelerationStructure
756 {
757 public:
758 	struct CreationSizes
759 	{
760 		VkDeviceSize	structure;
761 		VkDeviceSize	updateScratch;
762 		VkDeviceSize	buildScratch;
763 		VkDeviceSize	instancePointers;
764 		VkDeviceSize	instancesBuffer;
765 		VkDeviceSize	sum () const;
766 	};
767 
768 	static deUint32													getRequiredAllocationCount			(void);
769 
770 																	TopLevelAccelerationStructure		();
771 																	TopLevelAccelerationStructure		(const TopLevelAccelerationStructure&				other) = delete;
772 	virtual															~TopLevelAccelerationStructure		();
773 
774 	virtual void													setInstanceCount					(const size_t										instanceCount);
775 	virtual void													addInstance							(de::SharedPtr<BottomLevelAccelerationStructure>	bottomLevelStructure,
776 																										 const VkTransformMatrixKHR&						matrix									= identityMatrix3x4,
777 																										 deUint32											instanceCustomIndex						= 0,
778 																										 deUint32											mask									= 0xFF,
779 																										 deUint32											instanceShaderBindingTableRecordOffset	= 0,
780 																										 VkGeometryInstanceFlagsKHR							flags									= VkGeometryInstanceFlagBitsKHR(0u)	);
781 
782 	virtual void													setBuildType						(const VkAccelerationStructureBuildTypeKHR			buildType) = DE_NULL;
783 	virtual void													setCreateFlags						(const VkAccelerationStructureCreateFlagsKHR		createFlags) = DE_NULL;
784 	virtual void													setCreateGeneric					(bool												createGeneric) = 0;
785 	virtual void													setCreationBufferUnbounded			(bool												creationBufferUnbounded) = 0;
786 	virtual void													setBuildFlags						(const VkBuildAccelerationStructureFlagsKHR			buildFlags) = DE_NULL;
787 	virtual void													setBuildWithoutPrimitives			(bool												buildWithoutPrimitives) = 0;
788 	virtual void													setInactiveInstances				(bool												inactiveInstances) = 0;
789 	virtual void													setDeferredOperation				(const bool											deferredOperation,
790 																										 const deUint32										workerThreadCount = 0u) = DE_NULL;
791 	virtual void													setUseArrayOfPointers				(const bool											useArrayOfPointers) = DE_NULL;
792 	virtual void													setIndirectBuildParameters			(const VkBuffer										indirectBuffer,
793 																										 const VkDeviceSize									indirectBufferOffset,
794 																										 const deUint32										indirectBufferStride) = DE_NULL;
795 	virtual void													setUsePPGeometries					(const bool											usePPGeometries) = 0;
796 	virtual void													setTryCachedMemory					(const bool											tryCachedMemory) = 0;
797 	virtual VkBuildAccelerationStructureFlagsKHR					getBuildFlags						() const = DE_NULL;
798 	VkAccelerationStructureBuildSizesInfoKHR						getStructureBuildSizes				() const;
799 
800 	// methods specific for each acceleration structure
801 	virtual void													getCreationSizes					(const DeviceInterface&						vk,
802 																										 const VkDevice								device,
803 																										 const VkDeviceSize							structureSize,
804 																										 CreationSizes&								sizes) = 0;
805 	virtual void													create								(const DeviceInterface&						vk,
806 																										 const VkDevice								device,
807 																										 Allocator&									allocator,
808 																										 VkDeviceSize								structureSize			= 0u,
809 																										 VkDeviceAddress							deviceAddress			= 0u,
810 																										 const void*								pNext					= DE_NULL,
811 																										 const MemoryRequirement&					addMemoryRequirement	= MemoryRequirement::Any,
812 																										 const VkBuffer								creationBuffer			= VK_NULL_HANDLE,
813 																										 const VkDeviceSize							creationBufferSize		= 0u) = DE_NULL;
814 	virtual void													build								(const DeviceInterface&						vk,
815 																										 const VkDevice								device,
816 																										 const VkCommandBuffer						cmdBuffer,
817 																										 TopLevelAccelerationStructure*				srcAccelerationStructure = DE_NULL) = DE_NULL;
818 	virtual void													copyFrom							(const DeviceInterface&						vk,
819 																										 const VkDevice								device,
820 																										 const VkCommandBuffer						cmdBuffer,
821 																										 TopLevelAccelerationStructure*				accelerationStructure,
822 																										 bool										compactCopy) = DE_NULL;
823 
824 	virtual void													serialize							(const DeviceInterface&						vk,
825 																										 const VkDevice								device,
826 																										 const VkCommandBuffer						cmdBuffer,
827 																										 SerialStorage*								storage) = DE_NULL;
828 	virtual void													deserialize							(const DeviceInterface&						vk,
829 																										 const VkDevice								device,
830 																										 const VkCommandBuffer						cmdBuffer,
831 																										 SerialStorage*								storage) = DE_NULL;
832 
833 	virtual std::vector<VkDeviceSize>								getSerializingSizes					(const DeviceInterface&						vk,
834 																										 const VkDevice								device,
835 																										 const VkQueue								queue,
836 																										 const deUint32								queueFamilyIndex) = DE_NULL;
837 
838 	virtual std::vector<deUint64>									getSerializingAddresses				(const DeviceInterface&						vk,
839 																										 const VkDevice								device) const = DE_NULL;
840 
841 	// helper methods for typical acceleration structure creation tasks
842 	void															createAndBuild						(const DeviceInterface&						vk,
843 																										 const VkDevice								device,
844 																										 const VkCommandBuffer						cmdBuffer,
845 																										 Allocator&									allocator,
846 																										 VkDeviceAddress							deviceAddress			= 0u );
847 	void															createAndCopyFrom					(const DeviceInterface&						vk,
848 																										 const VkDevice								device,
849 																										 const VkCommandBuffer						cmdBuffer,
850 																										 Allocator&									allocator,
851 																										 TopLevelAccelerationStructure*				accelerationStructure,
852 																										 VkDeviceSize								compactCopySize			= 0u,
853 																										 VkDeviceAddress							deviceAddress			= 0u);
854 	void															createAndDeserializeFrom			(const DeviceInterface&						vk,
855 																										 const VkDevice								device,
856 																										 const VkCommandBuffer						cmdBuffer,
857 																										 Allocator&									allocator,
858 																										 SerialStorage*								storage,
859 																										 VkDeviceAddress							deviceAddress			= 0u);
860 
861 	virtual const VkAccelerationStructureKHR*						getPtr								(void) const = DE_NULL;
862 
863 	virtual void													updateInstanceMatrix				(const DeviceInterface&						vk,
864 																										 const VkDevice								device,
865 																										 size_t										instanceIndex,
866 																										 const VkTransformMatrixKHR&				matrix) = 0;
867 
868 protected:
869 	std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	m_bottomLevelInstances;
870 	std::vector<InstanceData>										m_instanceData;
871 	VkDeviceSize													m_structureSize;
872 	VkDeviceSize													m_updateScratchSize;
873 	VkDeviceSize													m_buildScratchSize;
874 
875 	virtual void													createAndDeserializeBottoms			(const DeviceInterface&						vk,
876 																										 const VkDevice								device,
877 																										 const VkCommandBuffer						cmdBuffer,
878 																										 Allocator&									allocator,
879 																										 SerialStorage*								storage) = DE_NULL;
880 };
881 
882 de::MovePtr<TopLevelAccelerationStructure> makeTopLevelAccelerationStructure ();
883 
884 template<class ASType> de::MovePtr<ASType> makeAccelerationStructure ();
makeAccelerationStructure()885 template<> inline de::MovePtr<BottomLevelAccelerationStructure>	makeAccelerationStructure () { return makeBottomLevelAccelerationStructure(); }
makeAccelerationStructure()886 template<> inline de::MovePtr<TopLevelAccelerationStructure>	makeAccelerationStructure () { return makeTopLevelAccelerationStructure(); }
887 
888 bool queryAccelerationStructureSize (const DeviceInterface&							vk,
889 									 const VkDevice									device,
890 									 const VkCommandBuffer							cmdBuffer,
891 									 const std::vector<VkAccelerationStructureKHR>&	accelerationStructureHandles,
892 									 VkAccelerationStructureBuildTypeKHR			buildType,
893 									 const VkQueryPool								queryPool,
894 									 VkQueryType									queryType,
895 									 deUint32										firstQuery,
896 									 std::vector<VkDeviceSize>&						results);
897 
898 class RayTracingPipeline
899 {
900 public:
901 	class CompileRequiredError : public std::runtime_error
902 	{
903 	public:
CompileRequiredError(const std::string & error)904 		CompileRequiredError (const std::string& error)
905 			: std::runtime_error(error)
906 			{}
907 	};
908 
909 																RayTracingPipeline			();
910 																~RayTracingPipeline			();
911 
912 	void														addShader					(VkShaderStageFlagBits									shaderStage,
913 																							 Move<VkShaderModule>									shaderModule,
914 																							 deUint32												group,
915 																							 const VkSpecializationInfo*							specializationInfo = nullptr,
916 																							 const VkPipelineShaderStageCreateFlags					pipelineShaderStageCreateFlags = static_cast<VkPipelineShaderStageCreateFlags>(0),
917 																							 const void*											pipelineShaderStageCreateInfopNext = nullptr);
918 	void														addShader					(VkShaderStageFlagBits									shaderStage,
919 																							 de::SharedPtr<Move<VkShaderModule>>					shaderModule,
920 																							 deUint32												group,
921 																							 const VkSpecializationInfo*							specializationInfoPtr = nullptr,
922 																							 const VkPipelineShaderStageCreateFlags					pipelineShaderStageCreateFlags = static_cast<VkPipelineShaderStageCreateFlags>(0),
923 																							 const void*											pipelineShaderStageCreateInfopNext = nullptr);
924 	void														addShader					(VkShaderStageFlagBits									shaderStage,
925 																							 VkShaderModule											shaderModule,
926 																							 deUint32												group,
927 																							 const VkSpecializationInfo*							specializationInfo = nullptr,
928 																							 const VkPipelineShaderStageCreateFlags					pipelineShaderStageCreateFlags = static_cast<VkPipelineShaderStageCreateFlags>(0),
929 																							 const void*											pipelineShaderStageCreateInfopNext = nullptr);
930 	void														setGroupCaptureReplayHandle	(uint32_t												group,
931 																							 const void*pShaderGroupCaptureReplayHandle);
932 	void														addLibrary					(de::SharedPtr<de::MovePtr<RayTracingPipeline>>			pipelineLibrary);
933 	uint32_t													getShaderGroupCount			(void); // This pipeline only.
934 	uint32_t													getFullShaderGroupCount		(void); // This pipeline and its included pipeline libraries, recursively.
935 	Move<VkPipeline>											createPipeline				(const DeviceInterface&									vk,
936 																							 const VkDevice											device,
937 																							 const VkPipelineLayout									pipelineLayout,
938 																							 const std::vector<de::SharedPtr<Move<VkPipeline>>>&	pipelineLibraries			= std::vector<de::SharedPtr<Move<VkPipeline>>>());
939 	Move<VkPipeline>											createPipeline				(const DeviceInterface&									vk,
940 																							 const VkDevice											device,
941 																							 const VkPipelineLayout									pipelineLayout,
942 																							 const std::vector<VkPipeline>&							pipelineLibraries,
943 																							 const VkPipelineCache									pipelineCache);
944 	std::vector<de::SharedPtr<Move<VkPipeline>>>				createPipelineWithLibraries	(const DeviceInterface&									vk,
945 																							 const VkDevice											device,
946 																							 const VkPipelineLayout									pipelineLayout);
947 	std::vector<uint8_t>										getShaderGroupHandles		(const DeviceInterface&									vk,
948 																							 const VkDevice											device,
949 																							 const VkPipeline										pipeline,
950 																							 const deUint32											shaderGroupHandleSize,
951 																							 const deUint32											firstGroup,
952 																							 const deUint32											groupCount) const;
953 	std::vector<uint8_t>										getShaderGroupReplayHandles	(const DeviceInterface&									vk,
954 																							 const VkDevice											device,
955 																							 const VkPipeline										pipeline,
956 																							 const deUint32											shaderGroupHandleReplaySize,
957 																							 const deUint32											firstGroup,
958 																							 const deUint32											groupCount) const;
959 	de::MovePtr<BufferWithMemory>								createShaderBindingTable	(const DeviceInterface&									vk,
960 																							 const VkDevice											device,
961 																							 const VkPipeline										pipeline,
962 																							 Allocator&												allocator,
963 																							 const deUint32&										shaderGroupHandleSize,
964 																							 const deUint32											shaderGroupBaseAlignment,
965 																							 const deUint32&										firstGroup,
966 																							 const deUint32&										groupCount,
967 																							 const VkBufferCreateFlags&								additionalBufferCreateFlags	= VkBufferCreateFlags(0u),
968 																							 const VkBufferUsageFlags&								additionalBufferUsageFlags	= VkBufferUsageFlags(0u),
969 																							 const MemoryRequirement&								additionalMemoryRequirement	= MemoryRequirement::Any,
970 																							 const VkDeviceAddress&									opaqueCaptureAddress		= 0u,
971 																							 const deUint32											shaderBindingTableOffset	= 0u,
972 																							 const deUint32											shaderRecordSize			= 0u,
973 																							 const void**											shaderGroupDataPtrPerGroup	= nullptr,
974 																							 const bool												autoAlignRecords			= true);
975 	de::MovePtr<BufferWithMemory>								createShaderBindingTable	(const DeviceInterface&									vk,
976 																							 const VkDevice											device,
977 																							 Allocator&												allocator,
978 																							 const deUint32											shaderGroupHandleSize,
979 																							 const deUint32											shaderGroupBaseAlignment,
980 																							 const std::vector<uint8_t>&							shaderHandles,
981 																							 const VkBufferCreateFlags								additionalBufferCreateFlags	= VkBufferCreateFlags(0u),
982 																							 const VkBufferUsageFlags								additionalBufferUsageFlags	= VkBufferUsageFlags(0u),
983 																							 const MemoryRequirement&								additionalMemoryRequirement	= MemoryRequirement::Any,
984 																							 const VkDeviceAddress									opaqueCaptureAddress		= 0u,
985 																							 const deUint32											shaderBindingTableOffset	= 0u,
986 																							 const deUint32											shaderRecordSize			= 0u,
987 																							 const void**											shaderGroupDataPtrPerGroup	= nullptr,
988 																							 const bool												autoAlignRecords			= true);
989 	void														setCreateFlags				(const VkPipelineCreateFlags&							pipelineCreateFlags);
990 	void														setCreateFlags2				(const VkPipelineCreateFlags2KHR&						pipelineCreateFlags2);
991 	void														setMaxRecursionDepth		(const deUint32&										maxRecursionDepth);
992 	void														setMaxPayloadSize			(const deUint32&										maxPayloadSize);
993 	void														setMaxAttributeSize			(const deUint32&										maxAttributeSize);
994 	void														setDeferredOperation		(const bool												deferredOperation,
995 																							 const deUint32											workerThreadCount = 0);
996 	void														addDynamicState				(const VkDynamicState&									dynamicState);
997 
998 
999 protected:
1000 	Move<VkPipeline>											createPipelineKHR			(const DeviceInterface&			vk,
1001 																							 const VkDevice					device,
1002 																							 const VkPipelineLayout			pipelineLayout,
1003 																							 const std::vector<VkPipeline>&	pipelineLibraries,
1004 																							 const VkPipelineCache			pipelineCache = DE_NULL);
1005 
1006 	std::vector<de::SharedPtr<Move<VkShaderModule> > >			m_shadersModules;
1007 	std::vector<de::SharedPtr<de::MovePtr<RayTracingPipeline>>>	m_pipelineLibraries;
1008 	std::vector<VkPipelineShaderStageCreateInfo>				m_shaderCreateInfos;
1009 	std::vector<VkRayTracingShaderGroupCreateInfoKHR>			m_shadersGroupCreateInfos;
1010 	VkPipelineCreateFlags										m_pipelineCreateFlags;
1011 	VkPipelineCreateFlags2KHR									m_pipelineCreateFlags2;
1012 	deUint32													m_maxRecursionDepth;
1013 	deUint32													m_maxPayloadSize;
1014 	deUint32													m_maxAttributeSize;
1015 	bool														m_deferredOperation;
1016 	deUint32													m_workerThreadCount;
1017 	std::vector<VkDynamicState>									m_dynamicStates;
1018 };
1019 
1020 class RayTracingProperties
1021 {
1022 protected:
RayTracingProperties()1023 									RayTracingProperties						() {}
1024 
1025 public:
RayTracingProperties(const InstanceInterface & vki,const VkPhysicalDevice physicalDevice)1026 									RayTracingProperties						(const InstanceInterface&	vki,
1027 																				 const VkPhysicalDevice		physicalDevice) { DE_UNREF(vki); DE_UNREF(physicalDevice); }
~RayTracingProperties()1028 	virtual							~RayTracingProperties						() {}
1029 
1030 	virtual uint32_t				getShaderGroupHandleSize					(void)	= 0;
1031 	virtual uint32_t				getShaderGroupHandleAlignment				(void)	= 0;
1032 	virtual uint32_t				getShaderGroupHandleCaptureReplaySize		(void)	= 0;
1033 	virtual uint32_t				getMaxRecursionDepth						(void)	= 0;
1034 	virtual uint32_t				getMaxShaderGroupStride						(void)	= 0;
1035 	virtual uint32_t				getShaderGroupBaseAlignment					(void)	= 0;
1036 	virtual uint64_t				getMaxGeometryCount							(void)	= 0;
1037 	virtual uint64_t				getMaxInstanceCount							(void)	= 0;
1038 	virtual uint64_t				getMaxPrimitiveCount						(void)	= 0;
1039 	virtual uint32_t				getMaxDescriptorSetAccelerationStructures	(void)	= 0;
1040 	virtual uint32_t				getMaxRayDispatchInvocationCount			(void)	= 0;
1041 	virtual uint32_t				getMaxRayHitAttributeSize					(void)	= 0;
1042 	virtual uint32_t				getMaxMemoryAllocationCount					(void)	= 0;
1043 };
1044 
1045 de::MovePtr<RayTracingProperties> makeRayTracingProperties (const InstanceInterface&	vki,
1046 															const VkPhysicalDevice		physicalDevice);
1047 
1048 void cmdTraceRays	(const DeviceInterface&					vk,
1049 					 VkCommandBuffer						commandBuffer,
1050 					 const VkStridedDeviceAddressRegionKHR*	raygenShaderBindingTableRegion,
1051 					 const VkStridedDeviceAddressRegionKHR*	missShaderBindingTableRegion,
1052 					 const VkStridedDeviceAddressRegionKHR*	hitShaderBindingTableRegion,
1053 					 const VkStridedDeviceAddressRegionKHR*	callableShaderBindingTableRegion,
1054 					 deUint32								width,
1055 					 deUint32								height,
1056 					 deUint32								depth);
1057 
1058 void cmdTraceRaysIndirect	(const DeviceInterface&					vk,
1059 							 VkCommandBuffer						commandBuffer,
1060 							 const VkStridedDeviceAddressRegionKHR*	raygenShaderBindingTableRegion,
1061 							 const VkStridedDeviceAddressRegionKHR*	missShaderBindingTableRegion,
1062 							 const VkStridedDeviceAddressRegionKHR*	hitShaderBindingTableRegion,
1063 							 const VkStridedDeviceAddressRegionKHR*	callableShaderBindingTableRegion,
1064 							 VkDeviceAddress						indirectDeviceAddress);
1065 
1066 void cmdTraceRaysIndirect2	(const DeviceInterface&					vk,
1067 							 VkCommandBuffer						commandBuffer,
1068 							 VkDeviceAddress						indirectDeviceAddress);
1069 
1070 
makeDeviceOrHostAddressConstKHR(const void * hostAddress)1071 static inline VkDeviceOrHostAddressConstKHR makeDeviceOrHostAddressConstKHR(const void* hostAddress)
1072 {
1073 	// VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported.
1074 	VkDeviceOrHostAddressConstKHR result;
1075 
1076 	deMemset(&result, 0, sizeof(result));
1077 
1078 	result.hostAddress = hostAddress;
1079 
1080 	return result;
1081 }
1082 
makeDeviceOrHostAddressKHR(void * hostAddress)1083 static inline VkDeviceOrHostAddressKHR makeDeviceOrHostAddressKHR(void* hostAddress)
1084 {
1085 	// VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported.
1086 	VkDeviceOrHostAddressKHR result;
1087 
1088 	deMemset(&result, 0, sizeof(result));
1089 
1090 	result.hostAddress = hostAddress;
1091 
1092 	return result;
1093 }
1094 
makeDeviceOrHostAddressConstKHR(const DeviceInterface & vk,const VkDevice device,VkBuffer buffer,VkDeviceSize offset)1095 static inline VkDeviceOrHostAddressConstKHR makeDeviceOrHostAddressConstKHR(const DeviceInterface& vk,
1096 	const VkDevice			device,
1097 	VkBuffer					buffer,
1098 	VkDeviceSize				offset)
1099 {
1100 	// VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported.
1101 	VkDeviceOrHostAddressConstKHR result;
1102 
1103 	deMemset(&result, 0, sizeof(result));
1104 
1105 	VkBufferDeviceAddressInfo bufferDeviceAddressInfo =
1106 	{
1107 		VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR,	// VkStructureType	 sType;
1108 		DE_NULL,											// const void*		 pNext;
1109 		buffer,												// VkBuffer			buffer
1110 	};
1111 	result.deviceAddress = vk.getBufferDeviceAddress(device, &bufferDeviceAddressInfo) + offset;
1112 
1113 	return result;
1114 }
1115 
makeDeviceOrHostAddressKHR(const DeviceInterface & vk,const VkDevice device,VkBuffer buffer,VkDeviceSize offset)1116 static inline VkDeviceOrHostAddressKHR makeDeviceOrHostAddressKHR(const DeviceInterface& vk,
1117 	const VkDevice			device,
1118 	VkBuffer					buffer,
1119 	VkDeviceSize				offset)
1120 {
1121 	// VS2015: Cannot create as a const due to cannot assign hostAddress due to it is a second field. Only assigning of first field supported.
1122 	VkDeviceOrHostAddressKHR result;
1123 
1124 	deMemset(&result, 0, sizeof(result));
1125 
1126 	VkBufferDeviceAddressInfo bufferDeviceAddressInfo =
1127 	{
1128 		VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR,	// VkStructureType	 sType;
1129 		DE_NULL,											// const void*		 pNext;
1130 		buffer,												// VkBuffer			buffer
1131 	};
1132 	result.deviceAddress = vk.getBufferDeviceAddress(device, &bufferDeviceAddressInfo) + offset;
1133 
1134 	return result;
1135 }
1136 
1137 #else
1138 
1139 deUint32 rayTracingDefineAnything();
1140 
1141 #endif // CTS_USES_VULKANSC
1142 
1143 } // vk
1144 
1145 #endif // _VKRAYTRACINGUTIL_HPP
1146