1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan CTS Framework
3e5c31af7Sopenharmony_ci * --------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2020 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Utilities for creating commonly used Vulkan objects
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "vkRayTracingUtil.hpp"
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "vkRefUtil.hpp"
27e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp"
28e5c31af7Sopenharmony_ci#include "vkObjUtil.hpp"
29e5c31af7Sopenharmony_ci#include "vkBarrierUtil.hpp"
30e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp"
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
33e5c31af7Sopenharmony_ci#include "deSTLUtil.hpp"
34e5c31af7Sopenharmony_ci
35e5c31af7Sopenharmony_ci#include <vector>
36e5c31af7Sopenharmony_ci#include <string>
37e5c31af7Sopenharmony_ci#include <thread>
38e5c31af7Sopenharmony_ci#include <limits>
39e5c31af7Sopenharmony_ci#include <type_traits>
40e5c31af7Sopenharmony_ci#include <map>
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_cinamespace vk
43e5c31af7Sopenharmony_ci{
44e5c31af7Sopenharmony_ci
45e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_cistatic const deUint32 WATCHDOG_INTERVAL = 16384; // Touch watchDog every N iterations.
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_cistruct DeferredThreadParams
50e5c31af7Sopenharmony_ci{
51e5c31af7Sopenharmony_ci	const DeviceInterface&	vk;
52e5c31af7Sopenharmony_ci	VkDevice				device;
53e5c31af7Sopenharmony_ci	VkDeferredOperationKHR	deferredOperation;
54e5c31af7Sopenharmony_ci	VkResult				result;
55e5c31af7Sopenharmony_ci};
56e5c31af7Sopenharmony_ci
57e5c31af7Sopenharmony_cistd::string getFormatSimpleName (vk::VkFormat format)
58e5c31af7Sopenharmony_ci{
59e5c31af7Sopenharmony_ci	constexpr size_t kPrefixLen = 10; // strlen("VK_FORMAT_")
60e5c31af7Sopenharmony_ci	return de::toLower(de::toString(format).substr(kPrefixLen));
61e5c31af7Sopenharmony_ci}
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_cibool pointInTriangle2D(const tcu::Vec3& p, const tcu::Vec3& p0, const tcu::Vec3& p1, const tcu::Vec3& p2)
64e5c31af7Sopenharmony_ci{
65e5c31af7Sopenharmony_ci	float s = p0.y() * p2.x() - p0.x() * p2.y() + (p2.y() - p0.y()) * p.x() + (p0.x() - p2.x()) * p.y();
66e5c31af7Sopenharmony_ci	float t = p0.x() * p1.y() - p0.y() * p1.x() + (p0.y() - p1.y()) * p.x() + (p1.x() - p0.x()) * p.y();
67e5c31af7Sopenharmony_ci
68e5c31af7Sopenharmony_ci	if ((s < 0) != (t < 0))
69e5c31af7Sopenharmony_ci		return false;
70e5c31af7Sopenharmony_ci
71e5c31af7Sopenharmony_ci	float a = -p1.y() * p2.x() + p0.y() * (p2.x() - p1.x()) + p0.x() * (p1.y() - p2.y()) + p1.x() * p2.y();
72e5c31af7Sopenharmony_ci
73e5c31af7Sopenharmony_ci	return a < 0 ?
74e5c31af7Sopenharmony_ci		(s <= 0 && s + t >= a) :
75e5c31af7Sopenharmony_ci		(s >= 0 && s + t <= a);
76e5c31af7Sopenharmony_ci}
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_ci// Returns true if VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR needs to be supported for the given format.
79e5c31af7Sopenharmony_cistatic bool isMandatoryAccelerationStructureVertexBufferFormat (vk::VkFormat format)
80e5c31af7Sopenharmony_ci{
81e5c31af7Sopenharmony_ci	bool mandatory = false;
82e5c31af7Sopenharmony_ci
83e5c31af7Sopenharmony_ci	switch (format)
84e5c31af7Sopenharmony_ci	{
85e5c31af7Sopenharmony_ci    case VK_FORMAT_R32G32_SFLOAT:
86e5c31af7Sopenharmony_ci    case VK_FORMAT_R32G32B32_SFLOAT:
87e5c31af7Sopenharmony_ci    case VK_FORMAT_R16G16_SFLOAT:
88e5c31af7Sopenharmony_ci    case VK_FORMAT_R16G16B16A16_SFLOAT:
89e5c31af7Sopenharmony_ci    case VK_FORMAT_R16G16_SNORM:
90e5c31af7Sopenharmony_ci    case VK_FORMAT_R16G16B16A16_SNORM:
91e5c31af7Sopenharmony_ci		mandatory = true;
92e5c31af7Sopenharmony_ci		break;
93e5c31af7Sopenharmony_ci	default:
94e5c31af7Sopenharmony_ci		break;
95e5c31af7Sopenharmony_ci	}
96e5c31af7Sopenharmony_ci
97e5c31af7Sopenharmony_ci	return mandatory;
98e5c31af7Sopenharmony_ci}
99e5c31af7Sopenharmony_ci
100e5c31af7Sopenharmony_civoid checkAccelerationStructureVertexBufferFormat (const vk::InstanceInterface &vki, vk::VkPhysicalDevice physicalDevice, vk::VkFormat format)
101e5c31af7Sopenharmony_ci{
102e5c31af7Sopenharmony_ci	const vk::VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
103e5c31af7Sopenharmony_ci
104e5c31af7Sopenharmony_ci	if ((formatProperties.bufferFeatures & vk::VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR) == 0u)
105e5c31af7Sopenharmony_ci	{
106e5c31af7Sopenharmony_ci		const std::string errorMsg = "Format not supported for acceleration structure vertex buffers";
107e5c31af7Sopenharmony_ci		if (isMandatoryAccelerationStructureVertexBufferFormat(format))
108e5c31af7Sopenharmony_ci			TCU_FAIL(errorMsg);
109e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, errorMsg);
110e5c31af7Sopenharmony_ci	}
111e5c31af7Sopenharmony_ci}
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_cistd::string getCommonRayGenerationShader (void)
114e5c31af7Sopenharmony_ci{
115e5c31af7Sopenharmony_ci	return
116e5c31af7Sopenharmony_ci		"#version 460 core\n"
117e5c31af7Sopenharmony_ci		"#extension GL_EXT_ray_tracing : require\n"
118e5c31af7Sopenharmony_ci		"layout(location = 0) rayPayloadEXT vec3 hitValue;\n"
119e5c31af7Sopenharmony_ci		"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
120e5c31af7Sopenharmony_ci		"\n"
121e5c31af7Sopenharmony_ci		"void main()\n"
122e5c31af7Sopenharmony_ci		"{\n"
123e5c31af7Sopenharmony_ci		"  uint  rayFlags = 0;\n"
124e5c31af7Sopenharmony_ci		"  uint  cullMask = 0xFF;\n"
125e5c31af7Sopenharmony_ci		"  float tmin     = 0.0;\n"
126e5c31af7Sopenharmony_ci		"  float tmax     = 9.0;\n"
127e5c31af7Sopenharmony_ci		"  vec3  origin   = vec3((float(gl_LaunchIDEXT.x) + 0.5f) / float(gl_LaunchSizeEXT.x), (float(gl_LaunchIDEXT.y) + 0.5f) / float(gl_LaunchSizeEXT.y), 0.0);\n"
128e5c31af7Sopenharmony_ci		"  vec3  direct   = vec3(0.0, 0.0, -1.0);\n"
129e5c31af7Sopenharmony_ci		"  traceRayEXT(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
130e5c31af7Sopenharmony_ci		"}\n";
131e5c31af7Sopenharmony_ci}
132e5c31af7Sopenharmony_ci
133e5c31af7Sopenharmony_ciRaytracedGeometryBase::RaytracedGeometryBase (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType)
134e5c31af7Sopenharmony_ci	: m_geometryType	(geometryType)
135e5c31af7Sopenharmony_ci	, m_vertexFormat	(vertexFormat)
136e5c31af7Sopenharmony_ci	, m_indexType		(indexType)
137e5c31af7Sopenharmony_ci	, m_geometryFlags	((VkGeometryFlagsKHR)0u)
138e5c31af7Sopenharmony_ci	, m_hasOpacityMicromap (false)
139e5c31af7Sopenharmony_ci{
140e5c31af7Sopenharmony_ci	if (m_geometryType == VK_GEOMETRY_TYPE_AABBS_KHR)
141e5c31af7Sopenharmony_ci		DE_ASSERT(m_vertexFormat == VK_FORMAT_R32G32B32_SFLOAT);
142e5c31af7Sopenharmony_ci}
143e5c31af7Sopenharmony_ci
144e5c31af7Sopenharmony_ciRaytracedGeometryBase::~RaytracedGeometryBase ()
145e5c31af7Sopenharmony_ci{
146e5c31af7Sopenharmony_ci}
147e5c31af7Sopenharmony_ci
148e5c31af7Sopenharmony_cistruct GeometryBuilderParams
149e5c31af7Sopenharmony_ci{
150e5c31af7Sopenharmony_ci	VkGeometryTypeKHR	geometryType;
151e5c31af7Sopenharmony_ci	bool				usePadding;
152e5c31af7Sopenharmony_ci};
153e5c31af7Sopenharmony_ci
154e5c31af7Sopenharmony_citemplate <typename V, typename I>
155e5c31af7Sopenharmony_ciRaytracedGeometryBase* buildRaytracedGeometry (const GeometryBuilderParams& params)
156e5c31af7Sopenharmony_ci{
157e5c31af7Sopenharmony_ci	return new RaytracedGeometry<V, I>(params.geometryType, (params.usePadding ? 1u : 0u));
158e5c31af7Sopenharmony_ci}
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_cide::SharedPtr<RaytracedGeometryBase> makeRaytracedGeometry (VkGeometryTypeKHR geometryType, VkFormat vertexFormat, VkIndexType indexType, bool padVertices)
161e5c31af7Sopenharmony_ci{
162e5c31af7Sopenharmony_ci	const GeometryBuilderParams builderParams { geometryType, padVertices };
163e5c31af7Sopenharmony_ci
164e5c31af7Sopenharmony_ci	switch (vertexFormat)
165e5c31af7Sopenharmony_ci	{
166e5c31af7Sopenharmony_ci		case VK_FORMAT_R32G32_SFLOAT:
167e5c31af7Sopenharmony_ci			switch (indexType)
168e5c31af7Sopenharmony_ci			{
169e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec2, deUint16>(builderParams));
170e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec2, deUint32>(builderParams));
171e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec2, EmptyIndex>(builderParams));
172e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
173e5c31af7Sopenharmony_ci			}
174e5c31af7Sopenharmony_ci		case VK_FORMAT_R32G32B32_SFLOAT:
175e5c31af7Sopenharmony_ci			switch (indexType)
176e5c31af7Sopenharmony_ci			{
177e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec3, deUint16>(builderParams));
178e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec3, deUint32>(builderParams));
179e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec3, EmptyIndex>(builderParams));
180e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
181e5c31af7Sopenharmony_ci			}
182e5c31af7Sopenharmony_ci		case VK_FORMAT_R32G32B32A32_SFLOAT:
183e5c31af7Sopenharmony_ci			switch (indexType)
184e5c31af7Sopenharmony_ci			{
185e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec4, deUint16>(builderParams));
186e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec4, deUint32>(builderParams));
187e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::Vec4, EmptyIndex>(builderParams));
188e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
189e5c31af7Sopenharmony_ci			}
190e5c31af7Sopenharmony_ci		case VK_FORMAT_R16G16_SFLOAT:
191e5c31af7Sopenharmony_ci			switch (indexType)
192e5c31af7Sopenharmony_ci			{
193e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_16, deUint16>(builderParams));
194e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_16, deUint32>(builderParams));
195e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_16, EmptyIndex>(builderParams));
196e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
197e5c31af7Sopenharmony_ci			}
198e5c31af7Sopenharmony_ci		case VK_FORMAT_R16G16B16_SFLOAT:
199e5c31af7Sopenharmony_ci			switch (indexType)
200e5c31af7Sopenharmony_ci			{
201e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_16, deUint16>(builderParams));
202e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_16, deUint32>(builderParams));
203e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_16, EmptyIndex>(builderParams));
204e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
205e5c31af7Sopenharmony_ci			}
206e5c31af7Sopenharmony_ci		case VK_FORMAT_R16G16B16A16_SFLOAT:
207e5c31af7Sopenharmony_ci			switch (indexType)
208e5c31af7Sopenharmony_ci			{
209e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_16, deUint16>(builderParams));
210e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_16, deUint32>(builderParams));
211e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_16, EmptyIndex>(builderParams));
212e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
213e5c31af7Sopenharmony_ci			}
214e5c31af7Sopenharmony_ci		case VK_FORMAT_R16G16_SNORM:
215e5c31af7Sopenharmony_ci			switch (indexType)
216e5c31af7Sopenharmony_ci			{
217e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_16SNorm, deUint16>(builderParams));
218e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_16SNorm, deUint32>(builderParams));
219e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_16SNorm, EmptyIndex>(builderParams));
220e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
221e5c31af7Sopenharmony_ci			}
222e5c31af7Sopenharmony_ci		case VK_FORMAT_R16G16B16_SNORM:
223e5c31af7Sopenharmony_ci			switch (indexType)
224e5c31af7Sopenharmony_ci			{
225e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_16SNorm, deUint16>(builderParams));
226e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_16SNorm, deUint32>(builderParams));
227e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_16SNorm, EmptyIndex>(builderParams));
228e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
229e5c31af7Sopenharmony_ci			}
230e5c31af7Sopenharmony_ci		case VK_FORMAT_R16G16B16A16_SNORM:
231e5c31af7Sopenharmony_ci			switch (indexType)
232e5c31af7Sopenharmony_ci			{
233e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_16SNorm, deUint16>(builderParams));
234e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_16SNorm, deUint32>(builderParams));
235e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_16SNorm, EmptyIndex>(builderParams));
236e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
237e5c31af7Sopenharmony_ci			}
238e5c31af7Sopenharmony_ci		case VK_FORMAT_R64G64_SFLOAT:
239e5c31af7Sopenharmony_ci			switch (indexType)
240e5c31af7Sopenharmony_ci			{
241e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec2, deUint16>(builderParams));
242e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec2, deUint32>(builderParams));
243e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec2, EmptyIndex>(builderParams));
244e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
245e5c31af7Sopenharmony_ci			}
246e5c31af7Sopenharmony_ci		case VK_FORMAT_R64G64B64_SFLOAT:
247e5c31af7Sopenharmony_ci			switch (indexType)
248e5c31af7Sopenharmony_ci			{
249e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec3, deUint16>(builderParams));
250e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec3, deUint32>(builderParams));
251e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec3, EmptyIndex>(builderParams));
252e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
253e5c31af7Sopenharmony_ci			}
254e5c31af7Sopenharmony_ci		case VK_FORMAT_R64G64B64A64_SFLOAT:
255e5c31af7Sopenharmony_ci			switch (indexType)
256e5c31af7Sopenharmony_ci			{
257e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec4, deUint16>(builderParams));
258e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec4, deUint32>(builderParams));
259e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<tcu::DVec4, EmptyIndex>(builderParams));
260e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
261e5c31af7Sopenharmony_ci			}
262e5c31af7Sopenharmony_ci		case VK_FORMAT_R8G8_SNORM:
263e5c31af7Sopenharmony_ci			switch (indexType)
264e5c31af7Sopenharmony_ci			{
265e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_8SNorm, deUint16>(builderParams));
266e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_8SNorm, deUint32>(builderParams));
267e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec2_8SNorm, EmptyIndex>(builderParams));
268e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
269e5c31af7Sopenharmony_ci			}
270e5c31af7Sopenharmony_ci		case VK_FORMAT_R8G8B8_SNORM:
271e5c31af7Sopenharmony_ci			switch (indexType)
272e5c31af7Sopenharmony_ci			{
273e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_8SNorm, deUint16>(builderParams));
274e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_8SNorm, deUint32>(builderParams));
275e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec3_8SNorm, EmptyIndex>(builderParams));
276e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
277e5c31af7Sopenharmony_ci			}
278e5c31af7Sopenharmony_ci		case VK_FORMAT_R8G8B8A8_SNORM:
279e5c31af7Sopenharmony_ci			switch (indexType)
280e5c31af7Sopenharmony_ci			{
281e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT16:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_8SNorm, deUint16>(builderParams));
282e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_UINT32:		return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_8SNorm, deUint32>(builderParams));
283e5c31af7Sopenharmony_ci				case VK_INDEX_TYPE_NONE_KHR:	return de::SharedPtr<RaytracedGeometryBase>(buildRaytracedGeometry<Vec4_8SNorm, EmptyIndex>(builderParams));
284e5c31af7Sopenharmony_ci				default:						TCU_THROW(InternalError, "Wrong index type");
285e5c31af7Sopenharmony_ci			}
286e5c31af7Sopenharmony_ci		default:
287e5c31af7Sopenharmony_ci			TCU_THROW(InternalError, "Wrong vertex format");
288e5c31af7Sopenharmony_ci	}
289e5c31af7Sopenharmony_ci
290e5c31af7Sopenharmony_ci}
291e5c31af7Sopenharmony_ci
292e5c31af7Sopenharmony_ciVkDeviceAddress getBufferDeviceAddress ( const DeviceInterface&	vk,
293e5c31af7Sopenharmony_ci										 const VkDevice			device,
294e5c31af7Sopenharmony_ci										 const VkBuffer			buffer,
295e5c31af7Sopenharmony_ci										 VkDeviceSize			offset )
296e5c31af7Sopenharmony_ci{
297e5c31af7Sopenharmony_ci
298e5c31af7Sopenharmony_ci	if (buffer == DE_NULL)
299e5c31af7Sopenharmony_ci		return 0;
300e5c31af7Sopenharmony_ci
301e5c31af7Sopenharmony_ci	VkBufferDeviceAddressInfo deviceAddressInfo
302e5c31af7Sopenharmony_ci	{
303e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,		// VkStructureType    sType
304e5c31af7Sopenharmony_ci		DE_NULL,											// const void*        pNext
305e5c31af7Sopenharmony_ci		buffer												// VkBuffer           buffer;
306e5c31af7Sopenharmony_ci	};
307e5c31af7Sopenharmony_ci	return vk.getBufferDeviceAddress(device, &deviceAddressInfo) + offset;
308e5c31af7Sopenharmony_ci}
309e5c31af7Sopenharmony_ci
310e5c31af7Sopenharmony_ci
311e5c31af7Sopenharmony_cistatic inline Move<VkQueryPool> makeQueryPool (const DeviceInterface&		vk,
312e5c31af7Sopenharmony_ci											   const VkDevice				device,
313e5c31af7Sopenharmony_ci											   const VkQueryType			queryType,
314e5c31af7Sopenharmony_ci											   deUint32					queryCount)
315e5c31af7Sopenharmony_ci{
316e5c31af7Sopenharmony_ci	const VkQueryPoolCreateInfo				queryPoolCreateInfo =
317e5c31af7Sopenharmony_ci	{
318e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,		// sType
319e5c31af7Sopenharmony_ci		DE_NULL,										// pNext
320e5c31af7Sopenharmony_ci		(VkQueryPoolCreateFlags)0,						// flags
321e5c31af7Sopenharmony_ci		queryType,										// queryType
322e5c31af7Sopenharmony_ci		queryCount,										// queryCount
323e5c31af7Sopenharmony_ci		0u,												// pipelineStatistics
324e5c31af7Sopenharmony_ci	};
325e5c31af7Sopenharmony_ci	return createQueryPool(vk, device, &queryPoolCreateInfo);
326e5c31af7Sopenharmony_ci}
327e5c31af7Sopenharmony_ci
328e5c31af7Sopenharmony_cistatic inline VkAccelerationStructureGeometryDataKHR makeVkAccelerationStructureGeometryDataKHR (const VkAccelerationStructureGeometryTrianglesDataKHR& triangles)
329e5c31af7Sopenharmony_ci{
330e5c31af7Sopenharmony_ci	VkAccelerationStructureGeometryDataKHR result;
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci	deMemset(&result, 0, sizeof(result));
333e5c31af7Sopenharmony_ci
334e5c31af7Sopenharmony_ci	result.triangles = triangles;
335e5c31af7Sopenharmony_ci
336e5c31af7Sopenharmony_ci	return result;
337e5c31af7Sopenharmony_ci}
338e5c31af7Sopenharmony_ci
339e5c31af7Sopenharmony_cistatic inline VkAccelerationStructureGeometryDataKHR makeVkAccelerationStructureGeometryDataKHR (const VkAccelerationStructureGeometryAabbsDataKHR& aabbs)
340e5c31af7Sopenharmony_ci{
341e5c31af7Sopenharmony_ci	VkAccelerationStructureGeometryDataKHR result;
342e5c31af7Sopenharmony_ci
343e5c31af7Sopenharmony_ci	deMemset(&result, 0, sizeof(result));
344e5c31af7Sopenharmony_ci
345e5c31af7Sopenharmony_ci	result.aabbs = aabbs;
346e5c31af7Sopenharmony_ci
347e5c31af7Sopenharmony_ci	return result;
348e5c31af7Sopenharmony_ci}
349e5c31af7Sopenharmony_ci
350e5c31af7Sopenharmony_cistatic inline VkAccelerationStructureGeometryDataKHR makeVkAccelerationStructureInstancesDataKHR (const VkAccelerationStructureGeometryInstancesDataKHR& instances)
351e5c31af7Sopenharmony_ci{
352e5c31af7Sopenharmony_ci	VkAccelerationStructureGeometryDataKHR result;
353e5c31af7Sopenharmony_ci
354e5c31af7Sopenharmony_ci	deMemset(&result, 0, sizeof(result));
355e5c31af7Sopenharmony_ci
356e5c31af7Sopenharmony_ci	result.instances = instances;
357e5c31af7Sopenharmony_ci
358e5c31af7Sopenharmony_ci	return result;
359e5c31af7Sopenharmony_ci}
360e5c31af7Sopenharmony_ci
361e5c31af7Sopenharmony_cistatic inline VkAccelerationStructureInstanceKHR makeVkAccelerationStructureInstanceKHR (const VkTransformMatrixKHR&			transform,
362e5c31af7Sopenharmony_ci																						 deUint32								instanceCustomIndex,
363e5c31af7Sopenharmony_ci																						 deUint32								mask,
364e5c31af7Sopenharmony_ci																						 deUint32								instanceShaderBindingTableRecordOffset,
365e5c31af7Sopenharmony_ci																						 VkGeometryInstanceFlagsKHR				flags,
366e5c31af7Sopenharmony_ci																						 deUint64								accelerationStructureReference)
367e5c31af7Sopenharmony_ci{
368e5c31af7Sopenharmony_ci	VkAccelerationStructureInstanceKHR instance		= { transform, 0, 0, 0, 0, accelerationStructureReference };
369e5c31af7Sopenharmony_ci	instance.instanceCustomIndex					= instanceCustomIndex & 0xFFFFFF;
370e5c31af7Sopenharmony_ci	instance.mask									= mask & 0xFF;
371e5c31af7Sopenharmony_ci	instance.instanceShaderBindingTableRecordOffset	= instanceShaderBindingTableRecordOffset & 0xFFFFFF;
372e5c31af7Sopenharmony_ci	instance.flags									= flags & 0xFF;
373e5c31af7Sopenharmony_ci	return instance;
374e5c31af7Sopenharmony_ci}
375e5c31af7Sopenharmony_ci
376e5c31af7Sopenharmony_ciVkResult getRayTracingShaderGroupHandlesKHR (const DeviceInterface&		vk,
377e5c31af7Sopenharmony_ci											 const VkDevice				device,
378e5c31af7Sopenharmony_ci											 const VkPipeline			pipeline,
379e5c31af7Sopenharmony_ci											 const deUint32				firstGroup,
380e5c31af7Sopenharmony_ci											 const deUint32				groupCount,
381e5c31af7Sopenharmony_ci											 const deUintptr			dataSize,
382e5c31af7Sopenharmony_ci											 void*						pData)
383e5c31af7Sopenharmony_ci{
384e5c31af7Sopenharmony_ci	return vk.getRayTracingShaderGroupHandlesKHR(device, pipeline, firstGroup, groupCount, dataSize, pData);
385e5c31af7Sopenharmony_ci}
386e5c31af7Sopenharmony_ci
387e5c31af7Sopenharmony_ciVkResult getRayTracingShaderGroupHandles (const DeviceInterface&		vk,
388e5c31af7Sopenharmony_ci										  const VkDevice				device,
389e5c31af7Sopenharmony_ci										  const VkPipeline				pipeline,
390e5c31af7Sopenharmony_ci										  const deUint32				firstGroup,
391e5c31af7Sopenharmony_ci										  const deUint32				groupCount,
392e5c31af7Sopenharmony_ci										  const deUintptr				dataSize,
393e5c31af7Sopenharmony_ci										  void*							pData)
394e5c31af7Sopenharmony_ci{
395e5c31af7Sopenharmony_ci	return getRayTracingShaderGroupHandlesKHR(vk, device, pipeline, firstGroup, groupCount, dataSize, pData);
396e5c31af7Sopenharmony_ci}
397e5c31af7Sopenharmony_ci
398e5c31af7Sopenharmony_ciVkResult getRayTracingCaptureReplayShaderGroupHandles (const DeviceInterface&	vk,
399e5c31af7Sopenharmony_ci													   const VkDevice			device,
400e5c31af7Sopenharmony_ci													   const VkPipeline			pipeline,
401e5c31af7Sopenharmony_ci													   const deUint32			firstGroup,
402e5c31af7Sopenharmony_ci													   const deUint32			groupCount,
403e5c31af7Sopenharmony_ci													   const deUintptr			dataSize,
404e5c31af7Sopenharmony_ci													   void*					pData)
405e5c31af7Sopenharmony_ci{
406e5c31af7Sopenharmony_ci	return vk.getRayTracingCaptureReplayShaderGroupHandlesKHR(device, pipeline, firstGroup, groupCount, dataSize, pData);
407e5c31af7Sopenharmony_ci}
408e5c31af7Sopenharmony_ci
409e5c31af7Sopenharmony_ciVkResult finishDeferredOperation (const DeviceInterface&	vk,
410e5c31af7Sopenharmony_ci								  VkDevice					device,
411e5c31af7Sopenharmony_ci								  VkDeferredOperationKHR	deferredOperation)
412e5c31af7Sopenharmony_ci{
413e5c31af7Sopenharmony_ci	VkResult result = vk.deferredOperationJoinKHR(device, deferredOperation);
414e5c31af7Sopenharmony_ci
415e5c31af7Sopenharmony_ci	while (result == VK_THREAD_IDLE_KHR)
416e5c31af7Sopenharmony_ci	{
417e5c31af7Sopenharmony_ci		std::this_thread::yield();
418e5c31af7Sopenharmony_ci		result = vk.deferredOperationJoinKHR(device, deferredOperation);
419e5c31af7Sopenharmony_ci	}
420e5c31af7Sopenharmony_ci
421e5c31af7Sopenharmony_ci	switch( result )
422e5c31af7Sopenharmony_ci	{
423e5c31af7Sopenharmony_ci		case VK_SUCCESS:
424e5c31af7Sopenharmony_ci		{
425e5c31af7Sopenharmony_ci			// Deferred operation has finished. Query its result
426e5c31af7Sopenharmony_ci			result = vk.getDeferredOperationResultKHR(device, deferredOperation);
427e5c31af7Sopenharmony_ci
428e5c31af7Sopenharmony_ci			break;
429e5c31af7Sopenharmony_ci		}
430e5c31af7Sopenharmony_ci
431e5c31af7Sopenharmony_ci		case VK_THREAD_DONE_KHR:
432e5c31af7Sopenharmony_ci		{
433e5c31af7Sopenharmony_ci			// Deferred operation is being wrapped up by another thread
434e5c31af7Sopenharmony_ci			// wait for that thread to finish
435e5c31af7Sopenharmony_ci			do
436e5c31af7Sopenharmony_ci			{
437e5c31af7Sopenharmony_ci				std::this_thread::yield();
438e5c31af7Sopenharmony_ci				result = vk.getDeferredOperationResultKHR(device, deferredOperation);
439e5c31af7Sopenharmony_ci			} while (result == VK_NOT_READY);
440e5c31af7Sopenharmony_ci
441e5c31af7Sopenharmony_ci			break;
442e5c31af7Sopenharmony_ci		}
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_ci		default:
445e5c31af7Sopenharmony_ci		{
446e5c31af7Sopenharmony_ci			DE_ASSERT(false);
447e5c31af7Sopenharmony_ci
448e5c31af7Sopenharmony_ci			break;
449e5c31af7Sopenharmony_ci		}
450e5c31af7Sopenharmony_ci	}
451e5c31af7Sopenharmony_ci
452e5c31af7Sopenharmony_ci	return result;
453e5c31af7Sopenharmony_ci}
454e5c31af7Sopenharmony_ci
455e5c31af7Sopenharmony_civoid finishDeferredOperationThreaded (DeferredThreadParams* deferredThreadParams)
456e5c31af7Sopenharmony_ci{
457e5c31af7Sopenharmony_ci	deferredThreadParams->result = finishDeferredOperation(deferredThreadParams->vk, deferredThreadParams->device, deferredThreadParams->deferredOperation);
458e5c31af7Sopenharmony_ci}
459e5c31af7Sopenharmony_ci
460e5c31af7Sopenharmony_civoid finishDeferredOperation (const DeviceInterface&	vk,
461e5c31af7Sopenharmony_ci							  VkDevice					device,
462e5c31af7Sopenharmony_ci							  VkDeferredOperationKHR	deferredOperation,
463e5c31af7Sopenharmony_ci							  const deUint32			workerThreadCount,
464e5c31af7Sopenharmony_ci							  const bool				operationNotDeferred)
465e5c31af7Sopenharmony_ci{
466e5c31af7Sopenharmony_ci
467e5c31af7Sopenharmony_ci	if (operationNotDeferred)
468e5c31af7Sopenharmony_ci	{
469e5c31af7Sopenharmony_ci		// when the operation deferral returns VK_OPERATION_NOT_DEFERRED_KHR,
470e5c31af7Sopenharmony_ci		// the deferred operation should act as if no command was deferred
471e5c31af7Sopenharmony_ci		VK_CHECK(vk.getDeferredOperationResultKHR(device, deferredOperation));
472e5c31af7Sopenharmony_ci
473e5c31af7Sopenharmony_ci
474e5c31af7Sopenharmony_ci		// there is not need to join any threads to the deferred operation,
475e5c31af7Sopenharmony_ci		// so below can be skipped.
476e5c31af7Sopenharmony_ci		return;
477e5c31af7Sopenharmony_ci	}
478e5c31af7Sopenharmony_ci
479e5c31af7Sopenharmony_ci	if (workerThreadCount == 0)
480e5c31af7Sopenharmony_ci	{
481e5c31af7Sopenharmony_ci		VK_CHECK(finishDeferredOperation(vk, device, deferredOperation));
482e5c31af7Sopenharmony_ci	}
483e5c31af7Sopenharmony_ci	else
484e5c31af7Sopenharmony_ci	{
485e5c31af7Sopenharmony_ci		const deUint32							maxThreadCountSupported	= deMinu32(256u, vk.getDeferredOperationMaxConcurrencyKHR(device, deferredOperation));
486e5c31af7Sopenharmony_ci		const deUint32							requestedThreadCount	= workerThreadCount;
487e5c31af7Sopenharmony_ci		const deUint32							testThreadCount			= requestedThreadCount == std::numeric_limits<deUint32>::max() ? maxThreadCountSupported : requestedThreadCount;
488e5c31af7Sopenharmony_ci
489e5c31af7Sopenharmony_ci		if (maxThreadCountSupported == 0)
490e5c31af7Sopenharmony_ci			TCU_FAIL("vkGetDeferredOperationMaxConcurrencyKHR must not return 0");
491e5c31af7Sopenharmony_ci
492e5c31af7Sopenharmony_ci		const DeferredThreadParams				deferredThreadParams	=
493e5c31af7Sopenharmony_ci		{
494e5c31af7Sopenharmony_ci			vk,					//  const DeviceInterface&	vk;
495e5c31af7Sopenharmony_ci			device,				//  VkDevice				device;
496e5c31af7Sopenharmony_ci			deferredOperation,	//  VkDeferredOperationKHR	deferredOperation;
497e5c31af7Sopenharmony_ci			VK_RESULT_MAX_ENUM,	//  VResult					result;
498e5c31af7Sopenharmony_ci		};
499e5c31af7Sopenharmony_ci		std::vector<DeferredThreadParams>		threadParams	(testThreadCount, deferredThreadParams);
500e5c31af7Sopenharmony_ci		std::vector<de::MovePtr<std::thread> >	threads			(testThreadCount);
501e5c31af7Sopenharmony_ci		bool									executionResult	= false;
502e5c31af7Sopenharmony_ci
503e5c31af7Sopenharmony_ci		DE_ASSERT(threads.size() > 0 && threads.size() == testThreadCount);
504e5c31af7Sopenharmony_ci
505e5c31af7Sopenharmony_ci		for (deUint32 threadNdx = 0; threadNdx < testThreadCount; ++threadNdx)
506e5c31af7Sopenharmony_ci			threads[threadNdx] = de::MovePtr<std::thread>(new std::thread(finishDeferredOperationThreaded, &threadParams[threadNdx]));
507e5c31af7Sopenharmony_ci
508e5c31af7Sopenharmony_ci		for (deUint32 threadNdx = 0; threadNdx < testThreadCount; ++threadNdx)
509e5c31af7Sopenharmony_ci			threads[threadNdx]->join();
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ci		for (deUint32 threadNdx = 0; threadNdx < testThreadCount; ++threadNdx)
512e5c31af7Sopenharmony_ci			if (threadParams[threadNdx].result == VK_SUCCESS)
513e5c31af7Sopenharmony_ci				executionResult = true;
514e5c31af7Sopenharmony_ci
515e5c31af7Sopenharmony_ci		if (!executionResult)
516e5c31af7Sopenharmony_ci			TCU_FAIL("Neither reported VK_SUCCESS");
517e5c31af7Sopenharmony_ci	}
518e5c31af7Sopenharmony_ci}
519e5c31af7Sopenharmony_ci
520e5c31af7Sopenharmony_ciSerialStorage::SerialStorage (const DeviceInterface&									vk,
521e5c31af7Sopenharmony_ci							  const VkDevice											device,
522e5c31af7Sopenharmony_ci							  Allocator&												allocator,
523e5c31af7Sopenharmony_ci							  const VkAccelerationStructureBuildTypeKHR					buildType,
524e5c31af7Sopenharmony_ci							  const VkDeviceSize										storageSize)
525e5c31af7Sopenharmony_ci	: m_buildType		(buildType)
526e5c31af7Sopenharmony_ci	, m_storageSize		(storageSize)
527e5c31af7Sopenharmony_ci	, m_serialInfo		()
528e5c31af7Sopenharmony_ci{
529e5c31af7Sopenharmony_ci	const VkBufferCreateInfo	bufferCreateInfo	= makeBufferCreateInfo(storageSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
530e5c31af7Sopenharmony_ci	try
531e5c31af7Sopenharmony_ci	{
532e5c31af7Sopenharmony_ci		m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::Cached | MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
533e5c31af7Sopenharmony_ci	}
534e5c31af7Sopenharmony_ci	catch (const tcu::NotSupportedError&)
535e5c31af7Sopenharmony_ci	{
536e5c31af7Sopenharmony_ci		// retry without Cached flag
537e5c31af7Sopenharmony_ci		m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
538e5c31af7Sopenharmony_ci	}
539e5c31af7Sopenharmony_ci}
540e5c31af7Sopenharmony_ci
541e5c31af7Sopenharmony_ciSerialStorage::SerialStorage (const DeviceInterface&						vk,
542e5c31af7Sopenharmony_ci							  const VkDevice								device,
543e5c31af7Sopenharmony_ci							  Allocator&									allocator,
544e5c31af7Sopenharmony_ci							  const VkAccelerationStructureBuildTypeKHR		buildType,
545e5c31af7Sopenharmony_ci							  const SerialInfo&								serialInfo)
546e5c31af7Sopenharmony_ci	: m_buildType		(buildType)
547e5c31af7Sopenharmony_ci	, m_storageSize		(serialInfo.sizes()[0])	// raise assertion if serialInfo is empty
548e5c31af7Sopenharmony_ci	, m_serialInfo		(serialInfo)
549e5c31af7Sopenharmony_ci{
550e5c31af7Sopenharmony_ci	DE_ASSERT(serialInfo.sizes().size() >= 2u);
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_ci	// create buffer for top-level acceleration structure
553e5c31af7Sopenharmony_ci	{
554e5c31af7Sopenharmony_ci		const VkBufferCreateInfo	bufferCreateInfo	= makeBufferCreateInfo(m_storageSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
555e5c31af7Sopenharmony_ci		m_buffer										= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
556e5c31af7Sopenharmony_ci	}
557e5c31af7Sopenharmony_ci
558e5c31af7Sopenharmony_ci	// create buffers for bottom-level acceleration structures
559e5c31af7Sopenharmony_ci	{
560e5c31af7Sopenharmony_ci		std::vector<deUint64>	addrs;
561e5c31af7Sopenharmony_ci
562e5c31af7Sopenharmony_ci		for (std::size_t i = 1; i < serialInfo.addresses().size(); ++i)
563e5c31af7Sopenharmony_ci		{
564e5c31af7Sopenharmony_ci			const deUint64& lookAddr = serialInfo.addresses()[i];
565e5c31af7Sopenharmony_ci			auto end = addrs.end();
566e5c31af7Sopenharmony_ci			auto match = std::find_if(addrs.begin(), end, [&](const deUint64& item){ return item == lookAddr; });
567e5c31af7Sopenharmony_ci			if (match == end)
568e5c31af7Sopenharmony_ci			{
569e5c31af7Sopenharmony_ci				addrs.emplace_back(lookAddr);
570e5c31af7Sopenharmony_ci				m_bottoms.emplace_back(de::SharedPtr<SerialStorage>(new SerialStorage(vk, device, allocator, buildType, serialInfo.sizes()[i])));
571e5c31af7Sopenharmony_ci			}
572e5c31af7Sopenharmony_ci		}
573e5c31af7Sopenharmony_ci	}
574e5c31af7Sopenharmony_ci}
575e5c31af7Sopenharmony_ci
576e5c31af7Sopenharmony_ciVkDeviceOrHostAddressKHR SerialStorage::getAddress (const DeviceInterface&						vk,
577e5c31af7Sopenharmony_ci													const VkDevice								device,
578e5c31af7Sopenharmony_ci													const VkAccelerationStructureBuildTypeKHR	buildType)
579e5c31af7Sopenharmony_ci{
580e5c31af7Sopenharmony_ci	if (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
581e5c31af7Sopenharmony_ci		return makeDeviceOrHostAddressKHR(vk, device, m_buffer->get(), 0);
582e5c31af7Sopenharmony_ci	else
583e5c31af7Sopenharmony_ci		return makeDeviceOrHostAddressKHR(m_buffer->getAllocation().getHostPtr());
584e5c31af7Sopenharmony_ci}
585e5c31af7Sopenharmony_ci
586e5c31af7Sopenharmony_ciSerialStorage::AccelerationStructureHeader* SerialStorage::getASHeader ()
587e5c31af7Sopenharmony_ci{
588e5c31af7Sopenharmony_ci	return reinterpret_cast<AccelerationStructureHeader*>(getHostAddress().hostAddress);
589e5c31af7Sopenharmony_ci}
590e5c31af7Sopenharmony_ci
591e5c31af7Sopenharmony_cibool SerialStorage::hasDeepFormat () const
592e5c31af7Sopenharmony_ci{
593e5c31af7Sopenharmony_ci	return (m_serialInfo.sizes().size() >= 2u);
594e5c31af7Sopenharmony_ci}
595e5c31af7Sopenharmony_ci
596e5c31af7Sopenharmony_cide::SharedPtr<SerialStorage> SerialStorage::getBottomStorage (deUint32 index) const
597e5c31af7Sopenharmony_ci{
598e5c31af7Sopenharmony_ci	return m_bottoms[index];
599e5c31af7Sopenharmony_ci}
600e5c31af7Sopenharmony_ci
601e5c31af7Sopenharmony_ciVkDeviceOrHostAddressKHR SerialStorage::getHostAddress (VkDeviceSize offset)
602e5c31af7Sopenharmony_ci{
603e5c31af7Sopenharmony_ci	DE_ASSERT(offset < m_storageSize);
604e5c31af7Sopenharmony_ci	return makeDeviceOrHostAddressKHR(static_cast<deUint8*>(m_buffer->getAllocation().getHostPtr()) + offset);
605e5c31af7Sopenharmony_ci}
606e5c31af7Sopenharmony_ci
607e5c31af7Sopenharmony_ciVkDeviceOrHostAddressConstKHR SerialStorage::getHostAddressConst (VkDeviceSize offset)
608e5c31af7Sopenharmony_ci{
609e5c31af7Sopenharmony_ci	return makeDeviceOrHostAddressConstKHR(static_cast<deUint8*>(m_buffer->getAllocation().getHostPtr()) + offset);
610e5c31af7Sopenharmony_ci}
611e5c31af7Sopenharmony_ci
612e5c31af7Sopenharmony_ciVkDeviceOrHostAddressConstKHR SerialStorage::getAddressConst (const DeviceInterface&					vk,
613e5c31af7Sopenharmony_ci															  const VkDevice							device,
614e5c31af7Sopenharmony_ci															  const VkAccelerationStructureBuildTypeKHR	buildType)
615e5c31af7Sopenharmony_ci{
616e5c31af7Sopenharmony_ci	if (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
617e5c31af7Sopenharmony_ci		return makeDeviceOrHostAddressConstKHR(vk, device, m_buffer->get(), 0);
618e5c31af7Sopenharmony_ci	else
619e5c31af7Sopenharmony_ci		return getHostAddressConst();
620e5c31af7Sopenharmony_ci}
621e5c31af7Sopenharmony_ci
622e5c31af7Sopenharmony_ciinline VkDeviceSize SerialStorage::getStorageSize () const
623e5c31af7Sopenharmony_ci{
624e5c31af7Sopenharmony_ci	return m_storageSize;
625e5c31af7Sopenharmony_ci}
626e5c31af7Sopenharmony_ci
627e5c31af7Sopenharmony_ciinline const SerialInfo& SerialStorage::getSerialInfo () const
628e5c31af7Sopenharmony_ci{
629e5c31af7Sopenharmony_ci	return m_serialInfo;
630e5c31af7Sopenharmony_ci}
631e5c31af7Sopenharmony_ci
632e5c31af7Sopenharmony_cideUint64 SerialStorage::getDeserializedSize ()
633e5c31af7Sopenharmony_ci{
634e5c31af7Sopenharmony_ci	deUint64		result		= 0;
635e5c31af7Sopenharmony_ci	const deUint8*	startPtr	= static_cast<deUint8*>(m_buffer->getAllocation().getHostPtr());
636e5c31af7Sopenharmony_ci
637e5c31af7Sopenharmony_ci	DE_ASSERT(sizeof(result) == DESERIALIZED_SIZE_SIZE);
638e5c31af7Sopenharmony_ci
639e5c31af7Sopenharmony_ci	deMemcpy(&result, startPtr + DESERIALIZED_SIZE_OFFSET, sizeof(result));
640e5c31af7Sopenharmony_ci
641e5c31af7Sopenharmony_ci	return result;
642e5c31af7Sopenharmony_ci}
643e5c31af7Sopenharmony_ci
644e5c31af7Sopenharmony_ciBottomLevelAccelerationStructure::~BottomLevelAccelerationStructure ()
645e5c31af7Sopenharmony_ci{
646e5c31af7Sopenharmony_ci}
647e5c31af7Sopenharmony_ci
648e5c31af7Sopenharmony_ciBottomLevelAccelerationStructure::BottomLevelAccelerationStructure ()
649e5c31af7Sopenharmony_ci	: m_structureSize		(0u)
650e5c31af7Sopenharmony_ci	, m_updateScratchSize	(0u)
651e5c31af7Sopenharmony_ci	, m_buildScratchSize	(0u)
652e5c31af7Sopenharmony_ci{
653e5c31af7Sopenharmony_ci}
654e5c31af7Sopenharmony_ci
655e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructure::setGeometryData (const std::vector<tcu::Vec3>&	geometryData,
656e5c31af7Sopenharmony_ci														const bool						triangles,
657e5c31af7Sopenharmony_ci														const VkGeometryFlagsKHR		geometryFlags)
658e5c31af7Sopenharmony_ci{
659e5c31af7Sopenharmony_ci	if (triangles)
660e5c31af7Sopenharmony_ci		DE_ASSERT((geometryData.size() % 3) == 0);
661e5c31af7Sopenharmony_ci	else
662e5c31af7Sopenharmony_ci		DE_ASSERT((geometryData.size() % 2) == 0);
663e5c31af7Sopenharmony_ci
664e5c31af7Sopenharmony_ci	setGeometryCount(1u);
665e5c31af7Sopenharmony_ci
666e5c31af7Sopenharmony_ci	addGeometry(geometryData, triangles, geometryFlags);
667e5c31af7Sopenharmony_ci}
668e5c31af7Sopenharmony_ci
669e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructure::setDefaultGeometryData (const VkShaderStageFlagBits	testStage,
670e5c31af7Sopenharmony_ci															   const VkGeometryFlagsKHR		geometryFlags)
671e5c31af7Sopenharmony_ci{
672e5c31af7Sopenharmony_ci	bool					trianglesData	= false;
673e5c31af7Sopenharmony_ci	float					z				= 0.0f;
674e5c31af7Sopenharmony_ci	std::vector<tcu::Vec3>	geometryData;
675e5c31af7Sopenharmony_ci
676e5c31af7Sopenharmony_ci	switch (testStage)
677e5c31af7Sopenharmony_ci	{
678e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_RAYGEN_BIT_KHR:		z = -1.0f; trianglesData = true;	break;
679e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:		z = -1.0f; trianglesData = true;	break;
680e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:	z = -1.0f; trianglesData = true;	break;
681e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_MISS_BIT_KHR:			z = -9.9f; trianglesData = true;	break;
682e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:	z = -1.0f; trianglesData = false;	break;
683e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_CALLABLE_BIT_KHR:		z = -1.0f; trianglesData = true;	break;
684e5c31af7Sopenharmony_ci		default:									TCU_THROW(InternalError, "Unacceptable stage");
685e5c31af7Sopenharmony_ci	}
686e5c31af7Sopenharmony_ci
687e5c31af7Sopenharmony_ci	if (trianglesData)
688e5c31af7Sopenharmony_ci	{
689e5c31af7Sopenharmony_ci		geometryData.reserve(6);
690e5c31af7Sopenharmony_ci
691e5c31af7Sopenharmony_ci		geometryData.push_back(tcu::Vec3(-1.0f, -1.0f, z));
692e5c31af7Sopenharmony_ci		geometryData.push_back(tcu::Vec3(-1.0f, +1.0f, z));
693e5c31af7Sopenharmony_ci		geometryData.push_back(tcu::Vec3(+1.0f, -1.0f, z));
694e5c31af7Sopenharmony_ci		geometryData.push_back(tcu::Vec3(+1.0f, -1.0f, z));
695e5c31af7Sopenharmony_ci		geometryData.push_back(tcu::Vec3(-1.0f, +1.0f, z));
696e5c31af7Sopenharmony_ci		geometryData.push_back(tcu::Vec3(+1.0f, +1.0f, z));
697e5c31af7Sopenharmony_ci	}
698e5c31af7Sopenharmony_ci	else
699e5c31af7Sopenharmony_ci	{
700e5c31af7Sopenharmony_ci		geometryData.reserve(2);
701e5c31af7Sopenharmony_ci
702e5c31af7Sopenharmony_ci		geometryData.push_back(tcu::Vec3(-1.0f, -1.0f, z));
703e5c31af7Sopenharmony_ci		geometryData.push_back(tcu::Vec3(+1.0f, +1.0f, z));
704e5c31af7Sopenharmony_ci	}
705e5c31af7Sopenharmony_ci
706e5c31af7Sopenharmony_ci	setGeometryCount(1u);
707e5c31af7Sopenharmony_ci
708e5c31af7Sopenharmony_ci	addGeometry(geometryData, trianglesData, geometryFlags);
709e5c31af7Sopenharmony_ci}
710e5c31af7Sopenharmony_ci
711e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructure::setGeometryCount (const size_t geometryCount)
712e5c31af7Sopenharmony_ci{
713e5c31af7Sopenharmony_ci	m_geometriesData.clear();
714e5c31af7Sopenharmony_ci
715e5c31af7Sopenharmony_ci	m_geometriesData.reserve(geometryCount);
716e5c31af7Sopenharmony_ci}
717e5c31af7Sopenharmony_ci
718e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructure::addGeometry (de::SharedPtr<RaytracedGeometryBase>&		raytracedGeometry)
719e5c31af7Sopenharmony_ci{
720e5c31af7Sopenharmony_ci	m_geometriesData.push_back(raytracedGeometry);
721e5c31af7Sopenharmony_ci}
722e5c31af7Sopenharmony_ci
723e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructure::addGeometry (const std::vector<tcu::Vec3>&	geometryData,
724e5c31af7Sopenharmony_ci													const bool						triangles,
725e5c31af7Sopenharmony_ci													const VkGeometryFlagsKHR		geometryFlags,
726e5c31af7Sopenharmony_ci													const VkAccelerationStructureTrianglesOpacityMicromapEXT* opacityGeometryMicromap)
727e5c31af7Sopenharmony_ci{
728e5c31af7Sopenharmony_ci	DE_ASSERT(geometryData.size() > 0);
729e5c31af7Sopenharmony_ci	DE_ASSERT((triangles && geometryData.size() % 3 == 0) || (!triangles && geometryData.size() % 2 == 0));
730e5c31af7Sopenharmony_ci
731e5c31af7Sopenharmony_ci	if (!triangles)
732e5c31af7Sopenharmony_ci		for (size_t posNdx = 0; posNdx < geometryData.size() / 2; ++posNdx)
733e5c31af7Sopenharmony_ci		{
734e5c31af7Sopenharmony_ci			DE_ASSERT(geometryData[2 * posNdx].x() <= geometryData[2 * posNdx + 1].x());
735e5c31af7Sopenharmony_ci			DE_ASSERT(geometryData[2 * posNdx].y() <= geometryData[2 * posNdx + 1].y());
736e5c31af7Sopenharmony_ci			DE_ASSERT(geometryData[2 * posNdx].z() <= geometryData[2 * posNdx + 1].z());
737e5c31af7Sopenharmony_ci		}
738e5c31af7Sopenharmony_ci
739e5c31af7Sopenharmony_ci	de::SharedPtr<RaytracedGeometryBase> geometry = makeRaytracedGeometry(triangles ? VK_GEOMETRY_TYPE_TRIANGLES_KHR : VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
740e5c31af7Sopenharmony_ci	for (auto it = begin(geometryData), eit = end(geometryData); it != eit; ++it)
741e5c31af7Sopenharmony_ci		geometry->addVertex(*it);
742e5c31af7Sopenharmony_ci
743e5c31af7Sopenharmony_ci	geometry->setGeometryFlags(geometryFlags);
744e5c31af7Sopenharmony_ci	if (opacityGeometryMicromap)
745e5c31af7Sopenharmony_ci		geometry->setOpacityMicromap(opacityGeometryMicromap);
746e5c31af7Sopenharmony_ci	addGeometry(geometry);
747e5c31af7Sopenharmony_ci}
748e5c31af7Sopenharmony_ci
749e5c31af7Sopenharmony_ciVkAccelerationStructureBuildSizesInfoKHR BottomLevelAccelerationStructure::getStructureBuildSizes () const
750e5c31af7Sopenharmony_ci{
751e5c31af7Sopenharmony_ci	return
752e5c31af7Sopenharmony_ci	{
753e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR,	//  VkStructureType	sType;
754e5c31af7Sopenharmony_ci		DE_NULL,														//  const void*		pNext;
755e5c31af7Sopenharmony_ci		m_structureSize,												//  VkDeviceSize	accelerationStructureSize;
756e5c31af7Sopenharmony_ci		m_updateScratchSize,											//  VkDeviceSize	updateScratchSize;
757e5c31af7Sopenharmony_ci		m_buildScratchSize												//  VkDeviceSize	buildScratchSize;
758e5c31af7Sopenharmony_ci	};
759e5c31af7Sopenharmony_ci};
760e5c31af7Sopenharmony_ci
761e5c31af7Sopenharmony_ciVkDeviceSize getVertexBufferSize (const std::vector<de::SharedPtr<RaytracedGeometryBase>>&	geometriesData)
762e5c31af7Sopenharmony_ci{
763e5c31af7Sopenharmony_ci	DE_ASSERT(geometriesData.size() != 0);
764e5c31af7Sopenharmony_ci	VkDeviceSize					bufferSizeBytes = 0;
765e5c31af7Sopenharmony_ci	for (size_t geometryNdx = 0; geometryNdx < geometriesData.size(); ++geometryNdx)
766e5c31af7Sopenharmony_ci		bufferSizeBytes += deAlignSize(geometriesData[geometryNdx]->getVertexByteSize(),8);
767e5c31af7Sopenharmony_ci	return bufferSizeBytes;
768e5c31af7Sopenharmony_ci}
769e5c31af7Sopenharmony_ci
770e5c31af7Sopenharmony_ciBufferWithMemory* createVertexBuffer (const DeviceInterface&	vk,
771e5c31af7Sopenharmony_ci									  const VkDevice			device,
772e5c31af7Sopenharmony_ci									  Allocator&				allocator,
773e5c31af7Sopenharmony_ci									  const VkDeviceSize		bufferSizeBytes)
774e5c31af7Sopenharmony_ci{
775e5c31af7Sopenharmony_ci	const VkBufferCreateInfo	bufferCreateInfo	= makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
776e5c31af7Sopenharmony_ci	return new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress);
777e5c31af7Sopenharmony_ci}
778e5c31af7Sopenharmony_ci
779e5c31af7Sopenharmony_ciBufferWithMemory* createVertexBuffer (const DeviceInterface&									vk,
780e5c31af7Sopenharmony_ci									  const VkDevice											device,
781e5c31af7Sopenharmony_ci									  Allocator&												allocator,
782e5c31af7Sopenharmony_ci									  const std::vector<de::SharedPtr<RaytracedGeometryBase>>&	geometriesData)
783e5c31af7Sopenharmony_ci{
784e5c31af7Sopenharmony_ci	return createVertexBuffer(vk, device, allocator, getVertexBufferSize(geometriesData));
785e5c31af7Sopenharmony_ci}
786e5c31af7Sopenharmony_ci
787e5c31af7Sopenharmony_civoid updateVertexBuffer (const DeviceInterface&										vk,
788e5c31af7Sopenharmony_ci						 const VkDevice												device,
789e5c31af7Sopenharmony_ci						 const std::vector<de::SharedPtr<RaytracedGeometryBase>>&	geometriesData,
790e5c31af7Sopenharmony_ci						 BufferWithMemory*											vertexBuffer,
791e5c31af7Sopenharmony_ci						 VkDeviceSize												geometriesOffset = 0)
792e5c31af7Sopenharmony_ci{
793e5c31af7Sopenharmony_ci	const Allocation&				geometryAlloc		= vertexBuffer->getAllocation();
794e5c31af7Sopenharmony_ci	deUint8*						bufferStart			= static_cast<deUint8*>(geometryAlloc.getHostPtr());
795e5c31af7Sopenharmony_ci	VkDeviceSize					bufferOffset		= geometriesOffset;
796e5c31af7Sopenharmony_ci
797e5c31af7Sopenharmony_ci	for (size_t geometryNdx = 0; geometryNdx < geometriesData.size(); ++geometryNdx)
798e5c31af7Sopenharmony_ci	{
799e5c31af7Sopenharmony_ci		const void*					geometryPtr			= geometriesData[geometryNdx]->getVertexPointer();
800e5c31af7Sopenharmony_ci		const size_t				geometryPtrSize		= geometriesData[geometryNdx]->getVertexByteSize();
801e5c31af7Sopenharmony_ci
802e5c31af7Sopenharmony_ci		deMemcpy(&bufferStart[bufferOffset], geometryPtr, geometryPtrSize);
803e5c31af7Sopenharmony_ci
804e5c31af7Sopenharmony_ci		bufferOffset += deAlignSize(geometryPtrSize,8);
805e5c31af7Sopenharmony_ci	}
806e5c31af7Sopenharmony_ci
807e5c31af7Sopenharmony_ci	// Flush the whole allocation. We could flush only the interesting range, but we'd need to be sure both the offset and size
808e5c31af7Sopenharmony_ci	// align to VkPhysicalDeviceLimits::nonCoherentAtomSize, which we are not considering. Also note most code uses Coherent memory
809e5c31af7Sopenharmony_ci	// for the vertex and index buffers, so flushing is actually not needed.
810e5c31af7Sopenharmony_ci	flushAlloc(vk, device, geometryAlloc);
811e5c31af7Sopenharmony_ci}
812e5c31af7Sopenharmony_ci
813e5c31af7Sopenharmony_ciVkDeviceSize getIndexBufferSize (const std::vector<de::SharedPtr<RaytracedGeometryBase>>&	geometriesData)
814e5c31af7Sopenharmony_ci{
815e5c31af7Sopenharmony_ci	DE_ASSERT(!geometriesData.empty());
816e5c31af7Sopenharmony_ci
817e5c31af7Sopenharmony_ci	VkDeviceSize	bufferSizeBytes = 0;
818e5c31af7Sopenharmony_ci	for (size_t geometryNdx = 0; geometryNdx < geometriesData.size(); ++geometryNdx)
819e5c31af7Sopenharmony_ci		if(geometriesData[geometryNdx]->getIndexType() != VK_INDEX_TYPE_NONE_KHR)
820e5c31af7Sopenharmony_ci			bufferSizeBytes += deAlignSize(geometriesData[geometryNdx]->getIndexByteSize(),8);
821e5c31af7Sopenharmony_ci	return bufferSizeBytes;
822e5c31af7Sopenharmony_ci}
823e5c31af7Sopenharmony_ci
824e5c31af7Sopenharmony_ciBufferWithMemory* createIndexBuffer (const DeviceInterface&		vk,
825e5c31af7Sopenharmony_ci									 const VkDevice				device,
826e5c31af7Sopenharmony_ci									 Allocator&					allocator,
827e5c31af7Sopenharmony_ci									 const VkDeviceSize			bufferSizeBytes)
828e5c31af7Sopenharmony_ci{
829e5c31af7Sopenharmony_ci	DE_ASSERT(bufferSizeBytes);
830e5c31af7Sopenharmony_ci	const VkBufferCreateInfo		bufferCreateInfo	= makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
831e5c31af7Sopenharmony_ci	return  new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress);
832e5c31af7Sopenharmony_ci}
833e5c31af7Sopenharmony_ci
834e5c31af7Sopenharmony_ciBufferWithMemory* createIndexBuffer (const DeviceInterface&										vk,
835e5c31af7Sopenharmony_ci									 const VkDevice												device,
836e5c31af7Sopenharmony_ci									 Allocator&													allocator,
837e5c31af7Sopenharmony_ci									 const std::vector<de::SharedPtr<RaytracedGeometryBase>>&	geometriesData)
838e5c31af7Sopenharmony_ci{
839e5c31af7Sopenharmony_ci	const VkDeviceSize bufferSizeBytes = getIndexBufferSize(geometriesData);
840e5c31af7Sopenharmony_ci	return bufferSizeBytes ? createIndexBuffer(vk, device, allocator, bufferSizeBytes) : nullptr;
841e5c31af7Sopenharmony_ci}
842e5c31af7Sopenharmony_ci
843e5c31af7Sopenharmony_civoid updateIndexBuffer (const DeviceInterface&										vk,
844e5c31af7Sopenharmony_ci						const VkDevice												device,
845e5c31af7Sopenharmony_ci						const std::vector<de::SharedPtr<RaytracedGeometryBase>>&	geometriesData,
846e5c31af7Sopenharmony_ci						BufferWithMemory*											indexBuffer,
847e5c31af7Sopenharmony_ci						VkDeviceSize												geometriesOffset)
848e5c31af7Sopenharmony_ci{
849e5c31af7Sopenharmony_ci	const Allocation&				indexAlloc			= indexBuffer->getAllocation();
850e5c31af7Sopenharmony_ci	deUint8*						bufferStart			= static_cast<deUint8*>(indexAlloc.getHostPtr());
851e5c31af7Sopenharmony_ci	VkDeviceSize					bufferOffset		= geometriesOffset;
852e5c31af7Sopenharmony_ci
853e5c31af7Sopenharmony_ci	for (size_t geometryNdx = 0; geometryNdx < geometriesData.size(); ++geometryNdx)
854e5c31af7Sopenharmony_ci	{
855e5c31af7Sopenharmony_ci		if (geometriesData[geometryNdx]->getIndexType() != VK_INDEX_TYPE_NONE_KHR)
856e5c31af7Sopenharmony_ci		{
857e5c31af7Sopenharmony_ci			const void*					indexPtr		= geometriesData[geometryNdx]->getIndexPointer();
858e5c31af7Sopenharmony_ci			const size_t				indexPtrSize	= geometriesData[geometryNdx]->getIndexByteSize();
859e5c31af7Sopenharmony_ci
860e5c31af7Sopenharmony_ci			deMemcpy(&bufferStart[bufferOffset], indexPtr, indexPtrSize);
861e5c31af7Sopenharmony_ci
862e5c31af7Sopenharmony_ci			bufferOffset += deAlignSize(indexPtrSize, 8);
863e5c31af7Sopenharmony_ci		}
864e5c31af7Sopenharmony_ci	}
865e5c31af7Sopenharmony_ci
866e5c31af7Sopenharmony_ci	// Flush the whole allocation. We could flush only the interesting range, but we'd need to be sure both the offset and size
867e5c31af7Sopenharmony_ci	// align to VkPhysicalDeviceLimits::nonCoherentAtomSize, which we are not considering. Also note most code uses Coherent memory
868e5c31af7Sopenharmony_ci	// for the vertex and index buffers, so flushing is actually not needed.
869e5c31af7Sopenharmony_ci	flushAlloc(vk, device, indexAlloc);
870e5c31af7Sopenharmony_ci}
871e5c31af7Sopenharmony_ci
872e5c31af7Sopenharmony_ciclass BottomLevelAccelerationStructureKHR : public BottomLevelAccelerationStructure
873e5c31af7Sopenharmony_ci{
874e5c31af7Sopenharmony_cipublic:
875e5c31af7Sopenharmony_ci	static deUint32											getRequiredAllocationCount						(void);
876e5c31af7Sopenharmony_ci
877e5c31af7Sopenharmony_ci															BottomLevelAccelerationStructureKHR				();
878e5c31af7Sopenharmony_ci															BottomLevelAccelerationStructureKHR				(const BottomLevelAccelerationStructureKHR&		other) = delete;
879e5c31af7Sopenharmony_ci	virtual													~BottomLevelAccelerationStructureKHR			();
880e5c31af7Sopenharmony_ci
881e5c31af7Sopenharmony_ci	void													setBuildType									(const VkAccelerationStructureBuildTypeKHR		buildType) override;
882e5c31af7Sopenharmony_ci	VkAccelerationStructureBuildTypeKHR						getBuildType									() const override;
883e5c31af7Sopenharmony_ci	void													setCreateFlags									(const VkAccelerationStructureCreateFlagsKHR	createFlags) override;
884e5c31af7Sopenharmony_ci	void													setCreateGeneric								(bool											createGeneric) override;
885e5c31af7Sopenharmony_ci	void													setCreationBufferUnbounded						(bool											creationBufferUnbounded) override;
886e5c31af7Sopenharmony_ci	void													setBuildFlags									(const VkBuildAccelerationStructureFlagsKHR		buildFlags) override;
887e5c31af7Sopenharmony_ci	void													setBuildWithoutGeometries						(bool											buildWithoutGeometries) override;
888e5c31af7Sopenharmony_ci	void													setBuildWithoutPrimitives						(bool											buildWithoutPrimitives) override;
889e5c31af7Sopenharmony_ci	void													setDeferredOperation							(const bool										deferredOperation,
890e5c31af7Sopenharmony_ci																											 const deUint32									workerThreadCount) override;
891e5c31af7Sopenharmony_ci	void													setUseArrayOfPointers							(const bool										useArrayOfPointers) override;
892e5c31af7Sopenharmony_ci	void													setUseMaintenance5								(const bool										useMaintenance5) override;
893e5c31af7Sopenharmony_ci	void													setIndirectBuildParameters						(const VkBuffer									indirectBuffer,
894e5c31af7Sopenharmony_ci																											 const VkDeviceSize								indirectBufferOffset,
895e5c31af7Sopenharmony_ci																											 const deUint32									indirectBufferStride) override;
896e5c31af7Sopenharmony_ci	VkBuildAccelerationStructureFlagsKHR					getBuildFlags									() const override;
897e5c31af7Sopenharmony_ci
898e5c31af7Sopenharmony_ci	void													create											(const DeviceInterface&							vk,
899e5c31af7Sopenharmony_ci																											 const VkDevice									device,
900e5c31af7Sopenharmony_ci																											 Allocator&										allocator,
901e5c31af7Sopenharmony_ci																											 VkDeviceSize									structureSize,
902e5c31af7Sopenharmony_ci																											 VkDeviceAddress								deviceAddress			= 0u,
903e5c31af7Sopenharmony_ci																											 const void*									pNext					= DE_NULL,
904e5c31af7Sopenharmony_ci																											 const MemoryRequirement&						addMemoryRequirement	= MemoryRequirement::Any,
905e5c31af7Sopenharmony_ci																											 const VkBuffer									creationBuffer			= VK_NULL_HANDLE,
906e5c31af7Sopenharmony_ci																											 const VkDeviceSize								creationBufferSize		= 0u) override;
907e5c31af7Sopenharmony_ci	void													build											(const DeviceInterface&							vk,
908e5c31af7Sopenharmony_ci																											 const VkDevice									device,
909e5c31af7Sopenharmony_ci																											 const VkCommandBuffer							cmdBuffer,
910e5c31af7Sopenharmony_ci																											 BottomLevelAccelerationStructure*				srcAccelerationStructure = DE_NULL) override;
911e5c31af7Sopenharmony_ci	void													copyFrom										(const DeviceInterface&							vk,
912e5c31af7Sopenharmony_ci																											 const VkDevice									device,
913e5c31af7Sopenharmony_ci																											 const VkCommandBuffer							cmdBuffer,
914e5c31af7Sopenharmony_ci																											 BottomLevelAccelerationStructure*				accelerationStructure,
915e5c31af7Sopenharmony_ci																											 bool											compactCopy) override;
916e5c31af7Sopenharmony_ci
917e5c31af7Sopenharmony_ci	void													serialize										(const DeviceInterface&							vk,
918e5c31af7Sopenharmony_ci																											 const VkDevice									device,
919e5c31af7Sopenharmony_ci																											 const VkCommandBuffer							cmdBuffer,
920e5c31af7Sopenharmony_ci																											 SerialStorage*									storage) override;
921e5c31af7Sopenharmony_ci	void													deserialize										(const DeviceInterface&							vk,
922e5c31af7Sopenharmony_ci																											 const VkDevice									device,
923e5c31af7Sopenharmony_ci																											 const VkCommandBuffer							cmdBuffer,
924e5c31af7Sopenharmony_ci																											 SerialStorage*									storage) override;
925e5c31af7Sopenharmony_ci
926e5c31af7Sopenharmony_ci	const VkAccelerationStructureKHR*						getPtr											(void) const override;
927e5c31af7Sopenharmony_ci	void													updateGeometry									(size_t											geometryIndex,
928e5c31af7Sopenharmony_ci																											 de::SharedPtr<RaytracedGeometryBase>&			raytracedGeometry) override;
929e5c31af7Sopenharmony_ci
930e5c31af7Sopenharmony_ciprotected:
931e5c31af7Sopenharmony_ci	VkAccelerationStructureBuildTypeKHR						m_buildType;
932e5c31af7Sopenharmony_ci	VkAccelerationStructureCreateFlagsKHR					m_createFlags;
933e5c31af7Sopenharmony_ci	bool													m_createGeneric;
934e5c31af7Sopenharmony_ci	bool													m_creationBufferUnbounded;
935e5c31af7Sopenharmony_ci	VkBuildAccelerationStructureFlagsKHR					m_buildFlags;
936e5c31af7Sopenharmony_ci	bool													m_buildWithoutGeometries;
937e5c31af7Sopenharmony_ci	bool													m_buildWithoutPrimitives;
938e5c31af7Sopenharmony_ci	bool													m_deferredOperation;
939e5c31af7Sopenharmony_ci	deUint32												m_workerThreadCount;
940e5c31af7Sopenharmony_ci	bool													m_useArrayOfPointers;
941e5c31af7Sopenharmony_ci	bool													m_useMaintenance5;
942e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>							m_accelerationStructureBuffer;
943e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>							m_vertexBuffer;
944e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>							m_indexBuffer;
945e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>							m_deviceScratchBuffer;
946e5c31af7Sopenharmony_ci	de::UniquePtr<std::vector<deUint8>>						m_hostScratchBuffer;
947e5c31af7Sopenharmony_ci	Move<VkAccelerationStructureKHR>						m_accelerationStructureKHR;
948e5c31af7Sopenharmony_ci	VkBuffer												m_indirectBuffer;
949e5c31af7Sopenharmony_ci	VkDeviceSize											m_indirectBufferOffset;
950e5c31af7Sopenharmony_ci	deUint32												m_indirectBufferStride;
951e5c31af7Sopenharmony_ci
952e5c31af7Sopenharmony_ci	void													prepareGeometries								(const DeviceInterface&												vk,
953e5c31af7Sopenharmony_ci																											 const VkDevice														device,
954e5c31af7Sopenharmony_ci																											 std::vector<VkAccelerationStructureGeometryKHR>&					accelerationStructureGeometriesKHR,
955e5c31af7Sopenharmony_ci																											 std::vector<VkAccelerationStructureGeometryKHR*>&					accelerationStructureGeometriesKHRPointers,
956e5c31af7Sopenharmony_ci																											 std::vector<VkAccelerationStructureBuildRangeInfoKHR>&				accelerationStructureBuildRangeInfoKHR,
957e5c31af7Sopenharmony_ci																											 std::vector<VkAccelerationStructureTrianglesOpacityMicromapEXT>&	accelerationStructureGeometryMicromapsEXT,
958e5c31af7Sopenharmony_ci																											 std::vector<deUint32>&												maxPrimitiveCounts,
959e5c31af7Sopenharmony_ci																											 VkDeviceSize														vertexBufferOffset = 0,
960e5c31af7Sopenharmony_ci																											 VkDeviceSize														indexBufferOffset = 0) const;
961e5c31af7Sopenharmony_ci
962e5c31af7Sopenharmony_ci	virtual BufferWithMemory*								getAccelerationStructureBuffer					() const { return m_accelerationStructureBuffer.get(); }
963e5c31af7Sopenharmony_ci	virtual BufferWithMemory*								getDeviceScratchBuffer							() const { return m_deviceScratchBuffer.get(); }
964e5c31af7Sopenharmony_ci	virtual std::vector<deUint8>*							getHostScratchBuffer							() const { return m_hostScratchBuffer.get(); }
965e5c31af7Sopenharmony_ci	virtual BufferWithMemory*								getVertexBuffer									() const { return m_vertexBuffer.get(); }
966e5c31af7Sopenharmony_ci	virtual BufferWithMemory*								getIndexBuffer									() const { return m_indexBuffer.get(); }
967e5c31af7Sopenharmony_ci
968e5c31af7Sopenharmony_ci	virtual VkDeviceSize									getAccelerationStructureBufferOffset			() const { return 0; }
969e5c31af7Sopenharmony_ci	virtual VkDeviceSize									getDeviceScratchBufferOffset					() const { return 0; }
970e5c31af7Sopenharmony_ci	virtual VkDeviceSize									getVertexBufferOffset							() const { return 0; }
971e5c31af7Sopenharmony_ci	virtual VkDeviceSize									getIndexBufferOffset							() const { return 0; }
972e5c31af7Sopenharmony_ci};
973e5c31af7Sopenharmony_ci
974e5c31af7Sopenharmony_cideUint32 BottomLevelAccelerationStructureKHR::getRequiredAllocationCount (void)
975e5c31af7Sopenharmony_ci{
976e5c31af7Sopenharmony_ci	/*
977e5c31af7Sopenharmony_ci		de::MovePtr<BufferWithMemory>							m_geometryBuffer; // but only when m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR
978e5c31af7Sopenharmony_ci		de::MovePtr<Allocation>									m_accelerationStructureAlloc;
979e5c31af7Sopenharmony_ci		de::MovePtr<BufferWithMemory>							m_deviceScratchBuffer;
980e5c31af7Sopenharmony_ci	*/
981e5c31af7Sopenharmony_ci	return 3u;
982e5c31af7Sopenharmony_ci}
983e5c31af7Sopenharmony_ci
984e5c31af7Sopenharmony_ciBottomLevelAccelerationStructureKHR::~BottomLevelAccelerationStructureKHR ()
985e5c31af7Sopenharmony_ci{
986e5c31af7Sopenharmony_ci}
987e5c31af7Sopenharmony_ci
988e5c31af7Sopenharmony_ciBottomLevelAccelerationStructureKHR::BottomLevelAccelerationStructureKHR ()
989e5c31af7Sopenharmony_ci	: BottomLevelAccelerationStructure	()
990e5c31af7Sopenharmony_ci	, m_buildType						(VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
991e5c31af7Sopenharmony_ci	, m_createFlags						(0u)
992e5c31af7Sopenharmony_ci	, m_createGeneric					(false)
993e5c31af7Sopenharmony_ci	, m_creationBufferUnbounded			(false)
994e5c31af7Sopenharmony_ci	, m_buildFlags						(0u)
995e5c31af7Sopenharmony_ci	, m_buildWithoutGeometries			(false)
996e5c31af7Sopenharmony_ci	, m_buildWithoutPrimitives			(false)
997e5c31af7Sopenharmony_ci	, m_deferredOperation				(false)
998e5c31af7Sopenharmony_ci	, m_workerThreadCount				(0)
999e5c31af7Sopenharmony_ci	, m_useArrayOfPointers				(false)
1000e5c31af7Sopenharmony_ci	, m_accelerationStructureBuffer		(DE_NULL)
1001e5c31af7Sopenharmony_ci	, m_vertexBuffer					(DE_NULL)
1002e5c31af7Sopenharmony_ci	, m_indexBuffer						(DE_NULL)
1003e5c31af7Sopenharmony_ci	, m_deviceScratchBuffer				(DE_NULL)
1004e5c31af7Sopenharmony_ci	, m_hostScratchBuffer				(new std::vector<deUint8>)
1005e5c31af7Sopenharmony_ci	, m_accelerationStructureKHR		()
1006e5c31af7Sopenharmony_ci	, m_indirectBuffer					(DE_NULL)
1007e5c31af7Sopenharmony_ci	, m_indirectBufferOffset			(0)
1008e5c31af7Sopenharmony_ci	, m_indirectBufferStride			(0)
1009e5c31af7Sopenharmony_ci{
1010e5c31af7Sopenharmony_ci}
1011e5c31af7Sopenharmony_ci
1012e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::setBuildType (const VkAccelerationStructureBuildTypeKHR	buildType)
1013e5c31af7Sopenharmony_ci{
1014e5c31af7Sopenharmony_ci	m_buildType = buildType;
1015e5c31af7Sopenharmony_ci}
1016e5c31af7Sopenharmony_ci
1017e5c31af7Sopenharmony_ciVkAccelerationStructureBuildTypeKHR BottomLevelAccelerationStructureKHR::getBuildType () const
1018e5c31af7Sopenharmony_ci{
1019e5c31af7Sopenharmony_ci	return m_buildType;
1020e5c31af7Sopenharmony_ci}
1021e5c31af7Sopenharmony_ci
1022e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::setCreateFlags (const VkAccelerationStructureCreateFlagsKHR	createFlags)
1023e5c31af7Sopenharmony_ci{
1024e5c31af7Sopenharmony_ci	m_createFlags = createFlags;
1025e5c31af7Sopenharmony_ci}
1026e5c31af7Sopenharmony_ci
1027e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::setCreateGeneric (bool createGeneric)
1028e5c31af7Sopenharmony_ci{
1029e5c31af7Sopenharmony_ci	m_createGeneric = createGeneric;
1030e5c31af7Sopenharmony_ci}
1031e5c31af7Sopenharmony_ci
1032e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::setCreationBufferUnbounded (bool creationBufferUnbounded)
1033e5c31af7Sopenharmony_ci{
1034e5c31af7Sopenharmony_ci	m_creationBufferUnbounded = creationBufferUnbounded;
1035e5c31af7Sopenharmony_ci}
1036e5c31af7Sopenharmony_ci
1037e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::setBuildFlags (const VkBuildAccelerationStructureFlagsKHR	buildFlags)
1038e5c31af7Sopenharmony_ci{
1039e5c31af7Sopenharmony_ci	m_buildFlags = buildFlags;
1040e5c31af7Sopenharmony_ci}
1041e5c31af7Sopenharmony_ci
1042e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::setBuildWithoutGeometries (bool buildWithoutGeometries)
1043e5c31af7Sopenharmony_ci{
1044e5c31af7Sopenharmony_ci	m_buildWithoutGeometries = buildWithoutGeometries;
1045e5c31af7Sopenharmony_ci}
1046e5c31af7Sopenharmony_ci
1047e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::setBuildWithoutPrimitives (bool buildWithoutPrimitives)
1048e5c31af7Sopenharmony_ci{
1049e5c31af7Sopenharmony_ci	m_buildWithoutPrimitives = buildWithoutPrimitives;
1050e5c31af7Sopenharmony_ci}
1051e5c31af7Sopenharmony_ci
1052e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::setDeferredOperation (const bool		deferredOperation,
1053e5c31af7Sopenharmony_ci																const deUint32	workerThreadCount)
1054e5c31af7Sopenharmony_ci{
1055e5c31af7Sopenharmony_ci	m_deferredOperation = deferredOperation;
1056e5c31af7Sopenharmony_ci	m_workerThreadCount = workerThreadCount;
1057e5c31af7Sopenharmony_ci}
1058e5c31af7Sopenharmony_ci
1059e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::setUseArrayOfPointers (const bool	useArrayOfPointers)
1060e5c31af7Sopenharmony_ci{
1061e5c31af7Sopenharmony_ci	m_useArrayOfPointers = useArrayOfPointers;
1062e5c31af7Sopenharmony_ci}
1063e5c31af7Sopenharmony_ci
1064e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::setUseMaintenance5(const bool	useMaintenance5)
1065e5c31af7Sopenharmony_ci{
1066e5c31af7Sopenharmony_ci	m_useMaintenance5 = useMaintenance5;
1067e5c31af7Sopenharmony_ci}
1068e5c31af7Sopenharmony_ci
1069e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::setIndirectBuildParameters (const VkBuffer		indirectBuffer,
1070e5c31af7Sopenharmony_ci																	  const VkDeviceSize	indirectBufferOffset,
1071e5c31af7Sopenharmony_ci																	  const deUint32		indirectBufferStride)
1072e5c31af7Sopenharmony_ci{
1073e5c31af7Sopenharmony_ci	m_indirectBuffer		= indirectBuffer;
1074e5c31af7Sopenharmony_ci	m_indirectBufferOffset	= indirectBufferOffset;
1075e5c31af7Sopenharmony_ci	m_indirectBufferStride	= indirectBufferStride;
1076e5c31af7Sopenharmony_ci}
1077e5c31af7Sopenharmony_ci
1078e5c31af7Sopenharmony_ciVkBuildAccelerationStructureFlagsKHR BottomLevelAccelerationStructureKHR::getBuildFlags () const
1079e5c31af7Sopenharmony_ci{
1080e5c31af7Sopenharmony_ci	return m_buildFlags;
1081e5c31af7Sopenharmony_ci}
1082e5c31af7Sopenharmony_ci
1083e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::create (const DeviceInterface&				vk,
1084e5c31af7Sopenharmony_ci												  const VkDevice						device,
1085e5c31af7Sopenharmony_ci												  Allocator&							allocator,
1086e5c31af7Sopenharmony_ci												  VkDeviceSize							structureSize,
1087e5c31af7Sopenharmony_ci												  VkDeviceAddress						deviceAddress,
1088e5c31af7Sopenharmony_ci												  const void*							pNext,
1089e5c31af7Sopenharmony_ci												  const MemoryRequirement&				addMemoryRequirement,
1090e5c31af7Sopenharmony_ci												  const VkBuffer						creationBuffer,
1091e5c31af7Sopenharmony_ci												  const VkDeviceSize					creationBufferSize)
1092e5c31af7Sopenharmony_ci{
1093e5c31af7Sopenharmony_ci	// AS may be built from geometries using vkCmdBuildAccelerationStructuresKHR / vkBuildAccelerationStructuresKHR
1094e5c31af7Sopenharmony_ci	// or may be copied/compacted/deserialized from other AS ( in this case AS does not need geometries, but it needs to know its size before creation ).
1095e5c31af7Sopenharmony_ci	DE_ASSERT(!m_geometriesData.empty() !=  !(structureSize == 0)); // logical xor
1096e5c31af7Sopenharmony_ci
1097e5c31af7Sopenharmony_ci	if (structureSize == 0)
1098e5c31af7Sopenharmony_ci	{
1099e5c31af7Sopenharmony_ci		std::vector<VkAccelerationStructureGeometryKHR>			accelerationStructureGeometriesKHR;
1100e5c31af7Sopenharmony_ci		std::vector<VkAccelerationStructureGeometryKHR*>		accelerationStructureGeometriesKHRPointers;
1101e5c31af7Sopenharmony_ci		std::vector<VkAccelerationStructureBuildRangeInfoKHR>	accelerationStructureBuildRangeInfoKHR;
1102e5c31af7Sopenharmony_ci		std::vector<VkAccelerationStructureTrianglesOpacityMicromapEXT> accelerationStructureGeometryMicromapsEXT;
1103e5c31af7Sopenharmony_ci		std::vector<deUint32>									maxPrimitiveCounts;
1104e5c31af7Sopenharmony_ci		prepareGeometries(vk, device, accelerationStructureGeometriesKHR, accelerationStructureGeometriesKHRPointers, accelerationStructureBuildRangeInfoKHR, accelerationStructureGeometryMicromapsEXT, maxPrimitiveCounts);
1105e5c31af7Sopenharmony_ci
1106e5c31af7Sopenharmony_ci		const VkAccelerationStructureGeometryKHR*				accelerationStructureGeometriesKHRPointer	= accelerationStructureGeometriesKHR.data();
1107e5c31af7Sopenharmony_ci		const VkAccelerationStructureGeometryKHR* const*		accelerationStructureGeometry				= accelerationStructureGeometriesKHRPointers.data();
1108e5c31af7Sopenharmony_ci
1109e5c31af7Sopenharmony_ci		const deUint32											geometryCount								= (m_buildWithoutGeometries
1110e5c31af7Sopenharmony_ci																											? 0u
1111e5c31af7Sopenharmony_ci																											: static_cast<deUint32>(accelerationStructureGeometriesKHR.size()));
1112e5c31af7Sopenharmony_ci		VkAccelerationStructureBuildGeometryInfoKHR	accelerationStructureBuildGeometryInfoKHR	=
1113e5c31af7Sopenharmony_ci		{
1114e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,			//  VkStructureType										sType;
1115e5c31af7Sopenharmony_ci			DE_NULL,																	//  const void*											pNext;
1116e5c31af7Sopenharmony_ci			VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR,							//  VkAccelerationStructureTypeKHR						type;
1117e5c31af7Sopenharmony_ci			m_buildFlags,																//  VkBuildAccelerationStructureFlagsKHR				flags;
1118e5c31af7Sopenharmony_ci			VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR,								//  VkBuildAccelerationStructureModeKHR					mode;
1119e5c31af7Sopenharmony_ci			DE_NULL,																	//  VkAccelerationStructureKHR							srcAccelerationStructure;
1120e5c31af7Sopenharmony_ci			DE_NULL,																	//  VkAccelerationStructureKHR							dstAccelerationStructure;
1121e5c31af7Sopenharmony_ci			geometryCount,																//  deUint32											geometryCount;
1122e5c31af7Sopenharmony_ci			m_useArrayOfPointers ? DE_NULL : accelerationStructureGeometriesKHRPointer,	//  const VkAccelerationStructureGeometryKHR*			pGeometries;
1123e5c31af7Sopenharmony_ci			m_useArrayOfPointers ? accelerationStructureGeometry : DE_NULL,				//  const VkAccelerationStructureGeometryKHR* const*	ppGeometries;
1124e5c31af7Sopenharmony_ci			makeDeviceOrHostAddressKHR(DE_NULL)											//  VkDeviceOrHostAddressKHR							scratchData;
1125e5c31af7Sopenharmony_ci		};
1126e5c31af7Sopenharmony_ci		VkAccelerationStructureBuildSizesInfoKHR sizeInfo =
1127e5c31af7Sopenharmony_ci		{
1128e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR,	//  VkStructureType	sType;
1129e5c31af7Sopenharmony_ci			DE_NULL,														//  const void*		pNext;
1130e5c31af7Sopenharmony_ci			0,																//  VkDeviceSize	accelerationStructureSize;
1131e5c31af7Sopenharmony_ci			0,																//  VkDeviceSize	updateScratchSize;
1132e5c31af7Sopenharmony_ci			0																//  VkDeviceSize	buildScratchSize;
1133e5c31af7Sopenharmony_ci		};
1134e5c31af7Sopenharmony_ci
1135e5c31af7Sopenharmony_ci		vk.getAccelerationStructureBuildSizesKHR(device, m_buildType, &accelerationStructureBuildGeometryInfoKHR, maxPrimitiveCounts.data(), &sizeInfo);
1136e5c31af7Sopenharmony_ci
1137e5c31af7Sopenharmony_ci		m_structureSize		= sizeInfo.accelerationStructureSize;
1138e5c31af7Sopenharmony_ci		m_updateScratchSize	= sizeInfo.updateScratchSize;
1139e5c31af7Sopenharmony_ci		m_buildScratchSize	= sizeInfo.buildScratchSize;
1140e5c31af7Sopenharmony_ci	}
1141e5c31af7Sopenharmony_ci	else
1142e5c31af7Sopenharmony_ci	{
1143e5c31af7Sopenharmony_ci		m_structureSize		= structureSize;
1144e5c31af7Sopenharmony_ci		m_updateScratchSize	= 0u;
1145e5c31af7Sopenharmony_ci		m_buildScratchSize	= 0u;
1146e5c31af7Sopenharmony_ci	}
1147e5c31af7Sopenharmony_ci
1148e5c31af7Sopenharmony_ci	const bool externalCreationBuffer = (creationBuffer != VK_NULL_HANDLE);
1149e5c31af7Sopenharmony_ci
1150e5c31af7Sopenharmony_ci	if (externalCreationBuffer)
1151e5c31af7Sopenharmony_ci	{
1152e5c31af7Sopenharmony_ci		DE_UNREF(creationBufferSize); // For release builds.
1153e5c31af7Sopenharmony_ci		DE_ASSERT(creationBufferSize >= m_structureSize);
1154e5c31af7Sopenharmony_ci	}
1155e5c31af7Sopenharmony_ci
1156e5c31af7Sopenharmony_ci	if (!externalCreationBuffer)
1157e5c31af7Sopenharmony_ci	{
1158e5c31af7Sopenharmony_ci		VkBufferCreateInfo					bufferCreateInfo	= makeBufferCreateInfo(m_structureSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
1159e5c31af7Sopenharmony_ci		VkBufferUsageFlags2CreateInfoKHR	bufferUsageFlags2	= vk::initVulkanStructure();
1160e5c31af7Sopenharmony_ci
1161e5c31af7Sopenharmony_ci		if (m_useMaintenance5)
1162e5c31af7Sopenharmony_ci		{
1163e5c31af7Sopenharmony_ci			bufferUsageFlags2.usage = VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT_KHR;
1164e5c31af7Sopenharmony_ci			bufferCreateInfo.pNext = &bufferUsageFlags2;
1165e5c31af7Sopenharmony_ci			bufferCreateInfo.usage = 0;
1166e5c31af7Sopenharmony_ci		}
1167e5c31af7Sopenharmony_ci
1168e5c31af7Sopenharmony_ci		const MemoryRequirement			memoryRequirement		= addMemoryRequirement | MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress;
1169e5c31af7Sopenharmony_ci		const bool						bindMemOnCreation		= (!m_creationBufferUnbounded);
1170e5c31af7Sopenharmony_ci
1171e5c31af7Sopenharmony_ci		try
1172e5c31af7Sopenharmony_ci		{
1173e5c31af7Sopenharmony_ci			m_accelerationStructureBuffer	= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, (MemoryRequirement::Cached | memoryRequirement), bindMemOnCreation));
1174e5c31af7Sopenharmony_ci		}
1175e5c31af7Sopenharmony_ci		catch (const tcu::NotSupportedError&)
1176e5c31af7Sopenharmony_ci		{
1177e5c31af7Sopenharmony_ci			// retry without Cached flag
1178e5c31af7Sopenharmony_ci			m_accelerationStructureBuffer	= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, memoryRequirement, bindMemOnCreation));
1179e5c31af7Sopenharmony_ci		}
1180e5c31af7Sopenharmony_ci	}
1181e5c31af7Sopenharmony_ci
1182e5c31af7Sopenharmony_ci	const auto createInfoBuffer = (externalCreationBuffer ? creationBuffer : getAccelerationStructureBuffer()->get());
1183e5c31af7Sopenharmony_ci	const auto createInfoOffset = (externalCreationBuffer ? static_cast<VkDeviceSize>(0) : getAccelerationStructureBufferOffset());
1184e5c31af7Sopenharmony_ci	{
1185e5c31af7Sopenharmony_ci		const VkAccelerationStructureTypeKHR		structureType						= (m_createGeneric
1186e5c31af7Sopenharmony_ci																						   ? VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR
1187e5c31af7Sopenharmony_ci																						   : VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR);
1188e5c31af7Sopenharmony_ci		const VkAccelerationStructureCreateInfoKHR	accelerationStructureCreateInfoKHR
1189e5c31af7Sopenharmony_ci		{
1190e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR,						//  VkStructureType											sType;
1191e5c31af7Sopenharmony_ci			pNext,																			//  const void*												pNext;
1192e5c31af7Sopenharmony_ci			m_createFlags,																	//  VkAccelerationStructureCreateFlagsKHR					createFlags;
1193e5c31af7Sopenharmony_ci			createInfoBuffer,																//  VkBuffer												buffer;
1194e5c31af7Sopenharmony_ci			createInfoOffset,																//  VkDeviceSize											offset;
1195e5c31af7Sopenharmony_ci			m_structureSize,																//  VkDeviceSize											size;
1196e5c31af7Sopenharmony_ci			structureType,																	//  VkAccelerationStructureTypeKHR							type;
1197e5c31af7Sopenharmony_ci			deviceAddress																	//  VkDeviceAddress											deviceAddress;
1198e5c31af7Sopenharmony_ci		};
1199e5c31af7Sopenharmony_ci
1200e5c31af7Sopenharmony_ci		m_accelerationStructureKHR	= createAccelerationStructureKHR(vk, device, &accelerationStructureCreateInfoKHR, DE_NULL);
1201e5c31af7Sopenharmony_ci
1202e5c31af7Sopenharmony_ci		// Make sure buffer memory is always bound after creation.
1203e5c31af7Sopenharmony_ci		if (!externalCreationBuffer)
1204e5c31af7Sopenharmony_ci			m_accelerationStructureBuffer->bindMemory();
1205e5c31af7Sopenharmony_ci	}
1206e5c31af7Sopenharmony_ci
1207e5c31af7Sopenharmony_ci	if (m_buildScratchSize > 0u)
1208e5c31af7Sopenharmony_ci	{
1209e5c31af7Sopenharmony_ci		if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1210e5c31af7Sopenharmony_ci		{
1211e5c31af7Sopenharmony_ci			const VkBufferCreateInfo		bufferCreateInfo = makeBufferCreateInfo(m_buildScratchSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
1212e5c31af7Sopenharmony_ci			m_deviceScratchBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
1213e5c31af7Sopenharmony_ci		}
1214e5c31af7Sopenharmony_ci		else
1215e5c31af7Sopenharmony_ci		{
1216e5c31af7Sopenharmony_ci			m_hostScratchBuffer->resize(static_cast<size_t>(m_buildScratchSize));
1217e5c31af7Sopenharmony_ci		}
1218e5c31af7Sopenharmony_ci	}
1219e5c31af7Sopenharmony_ci
1220e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR && !m_geometriesData.empty())
1221e5c31af7Sopenharmony_ci	{
1222e5c31af7Sopenharmony_ci		VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(getVertexBufferSize(m_geometriesData), VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
1223e5c31af7Sopenharmony_ci		VkBufferUsageFlags2CreateInfoKHR bufferUsageFlags2 = vk::initVulkanStructure();
1224e5c31af7Sopenharmony_ci
1225e5c31af7Sopenharmony_ci		if (m_useMaintenance5)
1226e5c31af7Sopenharmony_ci		{
1227e5c31af7Sopenharmony_ci			bufferUsageFlags2.usage = vk::VK_BUFFER_USAGE_2_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT_KHR;
1228e5c31af7Sopenharmony_ci			bufferCreateInfo.pNext = &bufferUsageFlags2;
1229e5c31af7Sopenharmony_ci			bufferCreateInfo.usage = 0;
1230e5c31af7Sopenharmony_ci		}
1231e5c31af7Sopenharmony_ci
1232e5c31af7Sopenharmony_ci		const vk::MemoryRequirement memoryRequirement = MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress;
1233e5c31af7Sopenharmony_ci		m_vertexBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, memoryRequirement));
1234e5c31af7Sopenharmony_ci
1235e5c31af7Sopenharmony_ci		bufferCreateInfo.size = getIndexBufferSize(m_geometriesData);
1236e5c31af7Sopenharmony_ci		if (bufferCreateInfo.size)
1237e5c31af7Sopenharmony_ci			m_indexBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, memoryRequirement));
1238e5c31af7Sopenharmony_ci		else
1239e5c31af7Sopenharmony_ci			m_indexBuffer = de::MovePtr<BufferWithMemory>(nullptr);
1240e5c31af7Sopenharmony_ci	}
1241e5c31af7Sopenharmony_ci}
1242e5c31af7Sopenharmony_ci
1243e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::build (const DeviceInterface&						vk,
1244e5c31af7Sopenharmony_ci												 const VkDevice								device,
1245e5c31af7Sopenharmony_ci												 const VkCommandBuffer						cmdBuffer,
1246e5c31af7Sopenharmony_ci												 BottomLevelAccelerationStructure*          srcAccelerationStructure)
1247e5c31af7Sopenharmony_ci{
1248e5c31af7Sopenharmony_ci	DE_ASSERT(!m_geometriesData.empty());
1249e5c31af7Sopenharmony_ci	DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
1250e5c31af7Sopenharmony_ci	DE_ASSERT(m_buildScratchSize != 0);
1251e5c31af7Sopenharmony_ci
1252e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1253e5c31af7Sopenharmony_ci	{
1254e5c31af7Sopenharmony_ci		updateVertexBuffer(vk, device, m_geometriesData,  getVertexBuffer(), getVertexBufferOffset());
1255e5c31af7Sopenharmony_ci		if(getIndexBuffer() != DE_NULL)
1256e5c31af7Sopenharmony_ci			updateIndexBuffer(vk, device, m_geometriesData, getIndexBuffer(), getIndexBufferOffset());
1257e5c31af7Sopenharmony_ci	}
1258e5c31af7Sopenharmony_ci
1259e5c31af7Sopenharmony_ci	{
1260e5c31af7Sopenharmony_ci		std::vector<VkAccelerationStructureGeometryKHR>			accelerationStructureGeometriesKHR;
1261e5c31af7Sopenharmony_ci		std::vector<VkAccelerationStructureGeometryKHR*>		accelerationStructureGeometriesKHRPointers;
1262e5c31af7Sopenharmony_ci		std::vector<VkAccelerationStructureBuildRangeInfoKHR>	accelerationStructureBuildRangeInfoKHR;
1263e5c31af7Sopenharmony_ci		std::vector<VkAccelerationStructureTrianglesOpacityMicromapEXT> accelerationStructureGeometryMicromapsEXT;
1264e5c31af7Sopenharmony_ci		std::vector<deUint32>									maxPrimitiveCounts;
1265e5c31af7Sopenharmony_ci
1266e5c31af7Sopenharmony_ci		prepareGeometries(vk, device, accelerationStructureGeometriesKHR, accelerationStructureGeometriesKHRPointers,
1267e5c31af7Sopenharmony_ci						  accelerationStructureBuildRangeInfoKHR, accelerationStructureGeometryMicromapsEXT, maxPrimitiveCounts, getVertexBufferOffset(), getIndexBufferOffset());
1268e5c31af7Sopenharmony_ci
1269e5c31af7Sopenharmony_ci		const VkAccelerationStructureGeometryKHR*			accelerationStructureGeometriesKHRPointer	= accelerationStructureGeometriesKHR.data();
1270e5c31af7Sopenharmony_ci		const VkAccelerationStructureGeometryKHR* const*	accelerationStructureGeometry				= accelerationStructureGeometriesKHRPointers.data();
1271e5c31af7Sopenharmony_ci		VkDeviceOrHostAddressKHR							scratchData									= (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1272e5c31af7Sopenharmony_ci																										? makeDeviceOrHostAddressKHR(vk, device, getDeviceScratchBuffer()->get(), getDeviceScratchBufferOffset())
1273e5c31af7Sopenharmony_ci																										: makeDeviceOrHostAddressKHR(getHostScratchBuffer()->data());
1274e5c31af7Sopenharmony_ci		const deUint32										geometryCount								= (m_buildWithoutGeometries
1275e5c31af7Sopenharmony_ci																										? 0u
1276e5c31af7Sopenharmony_ci																										: static_cast<deUint32>(accelerationStructureGeometriesKHR.size()));
1277e5c31af7Sopenharmony_ci
1278e5c31af7Sopenharmony_ci		VkAccelerationStructureKHR				srcStructure									= (srcAccelerationStructure != DE_NULL) ? *(srcAccelerationStructure->getPtr()) : DE_NULL;
1279e5c31af7Sopenharmony_ci		VkBuildAccelerationStructureModeKHR		mode											= (srcAccelerationStructure != DE_NULL) ? VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR : VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
1280e5c31af7Sopenharmony_ci
1281e5c31af7Sopenharmony_ci		VkAccelerationStructureBuildGeometryInfoKHR	accelerationStructureBuildGeometryInfoKHR	=
1282e5c31af7Sopenharmony_ci		{
1283e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,			//  VkStructureType										sType;
1284e5c31af7Sopenharmony_ci			DE_NULL,																	//  const void*											pNext;
1285e5c31af7Sopenharmony_ci			VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR,							//  VkAccelerationStructureTypeKHR						type;
1286e5c31af7Sopenharmony_ci			m_buildFlags,																//  VkBuildAccelerationStructureFlagsKHR				flags;
1287e5c31af7Sopenharmony_ci			mode,								//  VkBuildAccelerationStructureModeKHR					mode;
1288e5c31af7Sopenharmony_ci			srcStructure,																	//  VkAccelerationStructureKHR							srcAccelerationStructure;
1289e5c31af7Sopenharmony_ci			m_accelerationStructureKHR.get(),											//  VkAccelerationStructureKHR							dstAccelerationStructure;
1290e5c31af7Sopenharmony_ci			geometryCount,																//  deUint32											geometryCount;
1291e5c31af7Sopenharmony_ci			m_useArrayOfPointers ? DE_NULL : accelerationStructureGeometriesKHRPointer,	//  const VkAccelerationStructureGeometryKHR*			pGeometries;
1292e5c31af7Sopenharmony_ci			m_useArrayOfPointers ? accelerationStructureGeometry : DE_NULL,				//  const VkAccelerationStructureGeometryKHR* const*	ppGeometries;
1293e5c31af7Sopenharmony_ci			scratchData																	//  VkDeviceOrHostAddressKHR							scratchData;
1294e5c31af7Sopenharmony_ci		};
1295e5c31af7Sopenharmony_ci
1296e5c31af7Sopenharmony_ci		VkAccelerationStructureBuildRangeInfoKHR* accelerationStructureBuildRangeInfoKHRPtr	= accelerationStructureBuildRangeInfoKHR.data();
1297e5c31af7Sopenharmony_ci
1298e5c31af7Sopenharmony_ci		if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1299e5c31af7Sopenharmony_ci		{
1300e5c31af7Sopenharmony_ci			if (m_indirectBuffer == DE_NULL)
1301e5c31af7Sopenharmony_ci				vk.cmdBuildAccelerationStructuresKHR(cmdBuffer, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildRangeInfoKHR**)&accelerationStructureBuildRangeInfoKHRPtr);
1302e5c31af7Sopenharmony_ci			else
1303e5c31af7Sopenharmony_ci			{
1304e5c31af7Sopenharmony_ci				VkDeviceAddress	indirectDeviceAddress	= getBufferDeviceAddress(vk, device, m_indirectBuffer, m_indirectBufferOffset);
1305e5c31af7Sopenharmony_ci				deUint32*		pMaxPrimitiveCounts		= maxPrimitiveCounts.data();
1306e5c31af7Sopenharmony_ci				vk.cmdBuildAccelerationStructuresIndirectKHR(cmdBuffer, 1u, &accelerationStructureBuildGeometryInfoKHR, &indirectDeviceAddress, &m_indirectBufferStride, &pMaxPrimitiveCounts);
1307e5c31af7Sopenharmony_ci			}
1308e5c31af7Sopenharmony_ci		}
1309e5c31af7Sopenharmony_ci		else if (!m_deferredOperation)
1310e5c31af7Sopenharmony_ci		{
1311e5c31af7Sopenharmony_ci			VK_CHECK(vk.buildAccelerationStructuresKHR(device, DE_NULL, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildRangeInfoKHR**)&accelerationStructureBuildRangeInfoKHRPtr));
1312e5c31af7Sopenharmony_ci		}
1313e5c31af7Sopenharmony_ci		else
1314e5c31af7Sopenharmony_ci		{
1315e5c31af7Sopenharmony_ci			const auto deferredOperationPtr	= createDeferredOperationKHR(vk, device);
1316e5c31af7Sopenharmony_ci			const auto deferredOperation	= deferredOperationPtr.get();
1317e5c31af7Sopenharmony_ci
1318e5c31af7Sopenharmony_ci			VkResult result = vk.buildAccelerationStructuresKHR(device, deferredOperation, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildRangeInfoKHR**)&accelerationStructureBuildRangeInfoKHRPtr);
1319e5c31af7Sopenharmony_ci
1320e5c31af7Sopenharmony_ci			DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
1321e5c31af7Sopenharmony_ci
1322e5c31af7Sopenharmony_ci			finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
1323e5c31af7Sopenharmony_ci		}
1324e5c31af7Sopenharmony_ci	}
1325e5c31af7Sopenharmony_ci
1326e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1327e5c31af7Sopenharmony_ci	{
1328e5c31af7Sopenharmony_ci		const VkAccessFlags		accessMasks	= VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
1329e5c31af7Sopenharmony_ci		const VkMemoryBarrier	memBarrier	= makeMemoryBarrier(accessMasks, accessMasks);
1330e5c31af7Sopenharmony_ci
1331e5c31af7Sopenharmony_ci		cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier);
1332e5c31af7Sopenharmony_ci	}
1333e5c31af7Sopenharmony_ci}
1334e5c31af7Sopenharmony_ci
1335e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::copyFrom (const DeviceInterface&						vk,
1336e5c31af7Sopenharmony_ci													const VkDevice								device,
1337e5c31af7Sopenharmony_ci													const VkCommandBuffer						cmdBuffer,
1338e5c31af7Sopenharmony_ci													BottomLevelAccelerationStructure*			accelerationStructure,
1339e5c31af7Sopenharmony_ci													bool										compactCopy)
1340e5c31af7Sopenharmony_ci{
1341e5c31af7Sopenharmony_ci	DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
1342e5c31af7Sopenharmony_ci	DE_ASSERT(accelerationStructure != DE_NULL);
1343e5c31af7Sopenharmony_ci
1344e5c31af7Sopenharmony_ci	VkCopyAccelerationStructureInfoKHR copyAccelerationStructureInfo =
1345e5c31af7Sopenharmony_ci	{
1346e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR,															// VkStructureType						sType;
1347e5c31af7Sopenharmony_ci		DE_NULL,																										// const void*							pNext;
1348e5c31af7Sopenharmony_ci		*(accelerationStructure->getPtr()),																				// VkAccelerationStructureKHR			src;
1349e5c31af7Sopenharmony_ci		*(getPtr()),																									// VkAccelerationStructureKHR			dst;
1350e5c31af7Sopenharmony_ci		compactCopy ? VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR : VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR	// VkCopyAccelerationStructureModeKHR	mode;
1351e5c31af7Sopenharmony_ci	};
1352e5c31af7Sopenharmony_ci
1353e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1354e5c31af7Sopenharmony_ci	{
1355e5c31af7Sopenharmony_ci		vk.cmdCopyAccelerationStructureKHR(cmdBuffer, &copyAccelerationStructureInfo);
1356e5c31af7Sopenharmony_ci	}
1357e5c31af7Sopenharmony_ci	else if (!m_deferredOperation)
1358e5c31af7Sopenharmony_ci	{
1359e5c31af7Sopenharmony_ci		VK_CHECK(vk.copyAccelerationStructureKHR(device, DE_NULL, &copyAccelerationStructureInfo));
1360e5c31af7Sopenharmony_ci	}
1361e5c31af7Sopenharmony_ci	else
1362e5c31af7Sopenharmony_ci	{
1363e5c31af7Sopenharmony_ci		const auto deferredOperationPtr	= createDeferredOperationKHR(vk, device);
1364e5c31af7Sopenharmony_ci		const auto deferredOperation	= deferredOperationPtr.get();
1365e5c31af7Sopenharmony_ci
1366e5c31af7Sopenharmony_ci		VkResult result = vk.copyAccelerationStructureKHR(device, deferredOperation, &copyAccelerationStructureInfo);
1367e5c31af7Sopenharmony_ci
1368e5c31af7Sopenharmony_ci		DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
1369e5c31af7Sopenharmony_ci
1370e5c31af7Sopenharmony_ci		finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
1371e5c31af7Sopenharmony_ci	}
1372e5c31af7Sopenharmony_ci
1373e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1374e5c31af7Sopenharmony_ci	{
1375e5c31af7Sopenharmony_ci		const VkAccessFlags		accessMasks	= VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
1376e5c31af7Sopenharmony_ci		const VkMemoryBarrier	memBarrier	= makeMemoryBarrier(accessMasks, accessMasks);
1377e5c31af7Sopenharmony_ci
1378e5c31af7Sopenharmony_ci		cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier);
1379e5c31af7Sopenharmony_ci	}
1380e5c31af7Sopenharmony_ci}
1381e5c31af7Sopenharmony_ci
1382e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::serialize (const DeviceInterface&		vk,
1383e5c31af7Sopenharmony_ci													 const VkDevice				device,
1384e5c31af7Sopenharmony_ci													 const VkCommandBuffer		cmdBuffer,
1385e5c31af7Sopenharmony_ci													 SerialStorage*				storage)
1386e5c31af7Sopenharmony_ci{
1387e5c31af7Sopenharmony_ci	DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
1388e5c31af7Sopenharmony_ci	DE_ASSERT(storage != DE_NULL);
1389e5c31af7Sopenharmony_ci
1390e5c31af7Sopenharmony_ci	const VkCopyAccelerationStructureToMemoryInfoKHR	copyAccelerationStructureInfo	=
1391e5c31af7Sopenharmony_ci	{
1392e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR,	// VkStructureType						sType;
1393e5c31af7Sopenharmony_ci		DE_NULL,															// const void*							pNext;
1394e5c31af7Sopenharmony_ci		*(getPtr()),														// VkAccelerationStructureKHR			src;
1395e5c31af7Sopenharmony_ci		storage->getAddress(vk, device, m_buildType),						// VkDeviceOrHostAddressKHR				dst;
1396e5c31af7Sopenharmony_ci		VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR					// VkCopyAccelerationStructureModeKHR	mode;
1397e5c31af7Sopenharmony_ci	};
1398e5c31af7Sopenharmony_ci
1399e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1400e5c31af7Sopenharmony_ci	{
1401e5c31af7Sopenharmony_ci		vk.cmdCopyAccelerationStructureToMemoryKHR(cmdBuffer, &copyAccelerationStructureInfo);
1402e5c31af7Sopenharmony_ci	}
1403e5c31af7Sopenharmony_ci	else if (!m_deferredOperation)
1404e5c31af7Sopenharmony_ci	{
1405e5c31af7Sopenharmony_ci		VK_CHECK(vk.copyAccelerationStructureToMemoryKHR(device, DE_NULL, &copyAccelerationStructureInfo));
1406e5c31af7Sopenharmony_ci	}
1407e5c31af7Sopenharmony_ci	else
1408e5c31af7Sopenharmony_ci	{
1409e5c31af7Sopenharmony_ci		const auto deferredOperationPtr	= createDeferredOperationKHR(vk, device);
1410e5c31af7Sopenharmony_ci		const auto deferredOperation	= deferredOperationPtr.get();
1411e5c31af7Sopenharmony_ci
1412e5c31af7Sopenharmony_ci		const VkResult result = vk.copyAccelerationStructureToMemoryKHR(device, deferredOperation, &copyAccelerationStructureInfo);
1413e5c31af7Sopenharmony_ci
1414e5c31af7Sopenharmony_ci		DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
1415e5c31af7Sopenharmony_ci
1416e5c31af7Sopenharmony_ci		finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
1417e5c31af7Sopenharmony_ci	}
1418e5c31af7Sopenharmony_ci}
1419e5c31af7Sopenharmony_ci
1420e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::deserialize (const DeviceInterface&	vk,
1421e5c31af7Sopenharmony_ci													   const VkDevice			device,
1422e5c31af7Sopenharmony_ci													   const VkCommandBuffer	cmdBuffer,
1423e5c31af7Sopenharmony_ci													   SerialStorage*			storage)
1424e5c31af7Sopenharmony_ci{
1425e5c31af7Sopenharmony_ci	DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
1426e5c31af7Sopenharmony_ci	DE_ASSERT(storage != DE_NULL);
1427e5c31af7Sopenharmony_ci
1428e5c31af7Sopenharmony_ci	const VkCopyMemoryToAccelerationStructureInfoKHR	copyAccelerationStructureInfo	=
1429e5c31af7Sopenharmony_ci	{
1430e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR,	// VkStructureType							sType;
1431e5c31af7Sopenharmony_ci		DE_NULL,															// const void*								pNext;
1432e5c31af7Sopenharmony_ci		storage->getAddressConst(vk, device, m_buildType),					// VkDeviceOrHostAddressConstKHR			src;
1433e5c31af7Sopenharmony_ci		*(getPtr()),														// VkAccelerationStructureKHR				dst;
1434e5c31af7Sopenharmony_ci		VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR					// VkCopyAccelerationStructureModeKHR		mode;
1435e5c31af7Sopenharmony_ci	};
1436e5c31af7Sopenharmony_ci
1437e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1438e5c31af7Sopenharmony_ci	{
1439e5c31af7Sopenharmony_ci		vk.cmdCopyMemoryToAccelerationStructureKHR(cmdBuffer, &copyAccelerationStructureInfo);
1440e5c31af7Sopenharmony_ci	}
1441e5c31af7Sopenharmony_ci	else if (!m_deferredOperation)
1442e5c31af7Sopenharmony_ci	{
1443e5c31af7Sopenharmony_ci		VK_CHECK(vk.copyMemoryToAccelerationStructureKHR(device, DE_NULL, &copyAccelerationStructureInfo));
1444e5c31af7Sopenharmony_ci	}
1445e5c31af7Sopenharmony_ci	else
1446e5c31af7Sopenharmony_ci	{
1447e5c31af7Sopenharmony_ci		const auto deferredOperationPtr	= createDeferredOperationKHR(vk, device);
1448e5c31af7Sopenharmony_ci		const auto deferredOperation	= deferredOperationPtr.get();
1449e5c31af7Sopenharmony_ci
1450e5c31af7Sopenharmony_ci		const VkResult result = vk.copyMemoryToAccelerationStructureKHR(device, deferredOperation, &copyAccelerationStructureInfo);
1451e5c31af7Sopenharmony_ci
1452e5c31af7Sopenharmony_ci		DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
1453e5c31af7Sopenharmony_ci
1454e5c31af7Sopenharmony_ci		finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
1455e5c31af7Sopenharmony_ci	}
1456e5c31af7Sopenharmony_ci
1457e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1458e5c31af7Sopenharmony_ci	{
1459e5c31af7Sopenharmony_ci		const VkAccessFlags		accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
1460e5c31af7Sopenharmony_ci		const VkMemoryBarrier	memBarrier = makeMemoryBarrier(accessMasks, accessMasks);
1461e5c31af7Sopenharmony_ci
1462e5c31af7Sopenharmony_ci		cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier);
1463e5c31af7Sopenharmony_ci	}
1464e5c31af7Sopenharmony_ci}
1465e5c31af7Sopenharmony_ci
1466e5c31af7Sopenharmony_ciconst VkAccelerationStructureKHR* BottomLevelAccelerationStructureKHR::getPtr (void) const
1467e5c31af7Sopenharmony_ci{
1468e5c31af7Sopenharmony_ci	return &m_accelerationStructureKHR.get();
1469e5c31af7Sopenharmony_ci}
1470e5c31af7Sopenharmony_ci
1471e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::prepareGeometries (const DeviceInterface&												vk,
1472e5c31af7Sopenharmony_ci															 const VkDevice														device,
1473e5c31af7Sopenharmony_ci															 std::vector<VkAccelerationStructureGeometryKHR>&					accelerationStructureGeometriesKHR,
1474e5c31af7Sopenharmony_ci															 std::vector<VkAccelerationStructureGeometryKHR*>&					accelerationStructureGeometriesKHRPointers,
1475e5c31af7Sopenharmony_ci															 std::vector<VkAccelerationStructureBuildRangeInfoKHR>&				accelerationStructureBuildRangeInfoKHR,
1476e5c31af7Sopenharmony_ci															 std::vector<VkAccelerationStructureTrianglesOpacityMicromapEXT>&	accelerationStructureGeometryMicromapsEXT,
1477e5c31af7Sopenharmony_ci															 std::vector<deUint32>&												maxPrimitiveCounts,
1478e5c31af7Sopenharmony_ci															 VkDeviceSize														vertexBufferOffset,
1479e5c31af7Sopenharmony_ci															 VkDeviceSize														indexBufferOffset) const
1480e5c31af7Sopenharmony_ci{
1481e5c31af7Sopenharmony_ci	accelerationStructureGeometriesKHR.resize(m_geometriesData.size());
1482e5c31af7Sopenharmony_ci	accelerationStructureGeometriesKHRPointers.resize(m_geometriesData.size());
1483e5c31af7Sopenharmony_ci	accelerationStructureBuildRangeInfoKHR.resize(m_geometriesData.size());
1484e5c31af7Sopenharmony_ci	accelerationStructureGeometryMicromapsEXT.resize(m_geometriesData.size());
1485e5c31af7Sopenharmony_ci	maxPrimitiveCounts.resize(m_geometriesData.size());
1486e5c31af7Sopenharmony_ci
1487e5c31af7Sopenharmony_ci	for (size_t geometryNdx = 0; geometryNdx < m_geometriesData.size(); ++geometryNdx)
1488e5c31af7Sopenharmony_ci	{
1489e5c31af7Sopenharmony_ci		const de::SharedPtr<RaytracedGeometryBase>&				geometryData = m_geometriesData[geometryNdx];
1490e5c31af7Sopenharmony_ci		VkDeviceOrHostAddressConstKHR							vertexData, indexData;
1491e5c31af7Sopenharmony_ci		if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
1492e5c31af7Sopenharmony_ci		{
1493e5c31af7Sopenharmony_ci			if (getVertexBuffer() != DE_NULL)
1494e5c31af7Sopenharmony_ci			{
1495e5c31af7Sopenharmony_ci				vertexData			= makeDeviceOrHostAddressConstKHR(vk, device, getVertexBuffer()->get(), vertexBufferOffset);
1496e5c31af7Sopenharmony_ci				if (m_indirectBuffer == DE_NULL )
1497e5c31af7Sopenharmony_ci				{
1498e5c31af7Sopenharmony_ci					vertexBufferOffset	+= deAlignSize(geometryData->getVertexByteSize(), 8);
1499e5c31af7Sopenharmony_ci				}
1500e5c31af7Sopenharmony_ci			}
1501e5c31af7Sopenharmony_ci			else
1502e5c31af7Sopenharmony_ci				vertexData			= makeDeviceOrHostAddressConstKHR(DE_NULL);
1503e5c31af7Sopenharmony_ci
1504e5c31af7Sopenharmony_ci			if (getIndexBuffer() != DE_NULL &&  geometryData->getIndexType() != VK_INDEX_TYPE_NONE_KHR)
1505e5c31af7Sopenharmony_ci			{
1506e5c31af7Sopenharmony_ci				indexData			= makeDeviceOrHostAddressConstKHR(vk, device, getIndexBuffer()->get(), indexBufferOffset);
1507e5c31af7Sopenharmony_ci				indexBufferOffset	+= deAlignSize(geometryData->getIndexByteSize(), 8);
1508e5c31af7Sopenharmony_ci			}
1509e5c31af7Sopenharmony_ci			else
1510e5c31af7Sopenharmony_ci				indexData = makeDeviceOrHostAddressConstKHR(DE_NULL);
1511e5c31af7Sopenharmony_ci		}
1512e5c31af7Sopenharmony_ci		else
1513e5c31af7Sopenharmony_ci		{
1514e5c31af7Sopenharmony_ci			vertexData = makeDeviceOrHostAddressConstKHR(geometryData->getVertexPointer());
1515e5c31af7Sopenharmony_ci			if (geometryData->getIndexType() != VK_INDEX_TYPE_NONE_KHR)
1516e5c31af7Sopenharmony_ci				indexData = makeDeviceOrHostAddressConstKHR(geometryData->getIndexPointer());
1517e5c31af7Sopenharmony_ci			else
1518e5c31af7Sopenharmony_ci				indexData = makeDeviceOrHostAddressConstKHR(DE_NULL);
1519e5c31af7Sopenharmony_ci		}
1520e5c31af7Sopenharmony_ci
1521e5c31af7Sopenharmony_ci		VkAccelerationStructureGeometryTrianglesDataKHR	accelerationStructureGeometryTrianglesDataKHR =
1522e5c31af7Sopenharmony_ci		{
1523e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR,	//  VkStructureType					sType;
1524e5c31af7Sopenharmony_ci			DE_NULL,																//  const void*						pNext;
1525e5c31af7Sopenharmony_ci			geometryData->getVertexFormat(),										//  VkFormat						vertexFormat;
1526e5c31af7Sopenharmony_ci			vertexData,																//  VkDeviceOrHostAddressConstKHR	vertexData;
1527e5c31af7Sopenharmony_ci			geometryData->getVertexStride(),										//  VkDeviceSize					vertexStride;
1528e5c31af7Sopenharmony_ci			static_cast<deUint32>(geometryData->getVertexCount()),					//  uint32_t						maxVertex;
1529e5c31af7Sopenharmony_ci			geometryData->getIndexType(),											//  VkIndexType						indexType;
1530e5c31af7Sopenharmony_ci			indexData,																//  VkDeviceOrHostAddressConstKHR	indexData;
1531e5c31af7Sopenharmony_ci			makeDeviceOrHostAddressConstKHR(DE_NULL),								//  VkDeviceOrHostAddressConstKHR	transformData;
1532e5c31af7Sopenharmony_ci		};
1533e5c31af7Sopenharmony_ci
1534e5c31af7Sopenharmony_ci		if (geometryData->getHasOpacityMicromap())
1535e5c31af7Sopenharmony_ci			accelerationStructureGeometryTrianglesDataKHR.pNext = &geometryData->getOpacityMicromap();
1536e5c31af7Sopenharmony_ci
1537e5c31af7Sopenharmony_ci		const VkAccelerationStructureGeometryAabbsDataKHR		accelerationStructureGeometryAabbsDataKHR =
1538e5c31af7Sopenharmony_ci		{
1539e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR,	//  VkStructureType					sType;
1540e5c31af7Sopenharmony_ci			DE_NULL,															//  const void*						pNext;
1541e5c31af7Sopenharmony_ci			vertexData,															//  VkDeviceOrHostAddressConstKHR	data;
1542e5c31af7Sopenharmony_ci			geometryData->getAABBStride()										//  VkDeviceSize					stride;
1543e5c31af7Sopenharmony_ci		};
1544e5c31af7Sopenharmony_ci		const VkAccelerationStructureGeometryDataKHR			geometry = (geometryData->isTrianglesType())
1545e5c31af7Sopenharmony_ci																		 ? makeVkAccelerationStructureGeometryDataKHR(accelerationStructureGeometryTrianglesDataKHR)
1546e5c31af7Sopenharmony_ci																		 : makeVkAccelerationStructureGeometryDataKHR(accelerationStructureGeometryAabbsDataKHR);
1547e5c31af7Sopenharmony_ci		const VkAccelerationStructureGeometryKHR				accelerationStructureGeometryKHR =
1548e5c31af7Sopenharmony_ci		{
1549e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR,	//  VkStructureType							sType;
1550e5c31af7Sopenharmony_ci			DE_NULL,												//  const void*								pNext;
1551e5c31af7Sopenharmony_ci			geometryData->getGeometryType(),						//  VkGeometryTypeKHR						geometryType;
1552e5c31af7Sopenharmony_ci			geometry,												//  VkAccelerationStructureGeometryDataKHR	geometry;
1553e5c31af7Sopenharmony_ci			geometryData->getGeometryFlags()						//  VkGeometryFlagsKHR						flags;
1554e5c31af7Sopenharmony_ci		};
1555e5c31af7Sopenharmony_ci
1556e5c31af7Sopenharmony_ci		const deUint32 primitiveCount = (m_buildWithoutPrimitives ? 0u : geometryData->getPrimitiveCount());
1557e5c31af7Sopenharmony_ci
1558e5c31af7Sopenharmony_ci		const VkAccelerationStructureBuildRangeInfoKHR			accelerationStructureBuildRangeInfosKHR =
1559e5c31af7Sopenharmony_ci		{
1560e5c31af7Sopenharmony_ci			primitiveCount,	//  deUint32	primitiveCount;
1561e5c31af7Sopenharmony_ci			0,				//  deUint32	primitiveOffset;
1562e5c31af7Sopenharmony_ci			0,				//  deUint32	firstVertex;
1563e5c31af7Sopenharmony_ci			0				//  deUint32	firstTransform;
1564e5c31af7Sopenharmony_ci		};
1565e5c31af7Sopenharmony_ci
1566e5c31af7Sopenharmony_ci		accelerationStructureGeometriesKHR[geometryNdx]			= accelerationStructureGeometryKHR;
1567e5c31af7Sopenharmony_ci		accelerationStructureGeometriesKHRPointers[geometryNdx]	= &accelerationStructureGeometriesKHR[geometryNdx];
1568e5c31af7Sopenharmony_ci		accelerationStructureBuildRangeInfoKHR[geometryNdx]		= accelerationStructureBuildRangeInfosKHR;
1569e5c31af7Sopenharmony_ci		maxPrimitiveCounts[geometryNdx]							= geometryData->getPrimitiveCount();
1570e5c31af7Sopenharmony_ci	}
1571e5c31af7Sopenharmony_ci}
1572e5c31af7Sopenharmony_ci
1573e5c31af7Sopenharmony_cideUint32 BottomLevelAccelerationStructure::getRequiredAllocationCount (void)
1574e5c31af7Sopenharmony_ci{
1575e5c31af7Sopenharmony_ci	return BottomLevelAccelerationStructureKHR::getRequiredAllocationCount();
1576e5c31af7Sopenharmony_ci}
1577e5c31af7Sopenharmony_ci
1578e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructure::createAndBuild (const DeviceInterface&	vk,
1579e5c31af7Sopenharmony_ci													   const VkDevice			device,
1580e5c31af7Sopenharmony_ci													   const VkCommandBuffer	cmdBuffer,
1581e5c31af7Sopenharmony_ci													   Allocator&				allocator,
1582e5c31af7Sopenharmony_ci													   VkDeviceAddress			deviceAddress)
1583e5c31af7Sopenharmony_ci{
1584e5c31af7Sopenharmony_ci	create(vk, device, allocator, 0u, deviceAddress);
1585e5c31af7Sopenharmony_ci	build(vk, device, cmdBuffer);
1586e5c31af7Sopenharmony_ci}
1587e5c31af7Sopenharmony_ci
1588e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructure::createAndCopyFrom (const DeviceInterface&				vk,
1589e5c31af7Sopenharmony_ci														  const VkDevice						device,
1590e5c31af7Sopenharmony_ci														  const VkCommandBuffer					cmdBuffer,
1591e5c31af7Sopenharmony_ci														  Allocator&							allocator,
1592e5c31af7Sopenharmony_ci														  BottomLevelAccelerationStructure*		accelerationStructure,
1593e5c31af7Sopenharmony_ci														  VkDeviceSize							compactCopySize,
1594e5c31af7Sopenharmony_ci														  VkDeviceAddress						deviceAddress)
1595e5c31af7Sopenharmony_ci{
1596e5c31af7Sopenharmony_ci	DE_ASSERT(accelerationStructure != NULL);
1597e5c31af7Sopenharmony_ci	VkDeviceSize copiedSize = compactCopySize > 0u ? compactCopySize : accelerationStructure->getStructureBuildSizes().accelerationStructureSize;
1598e5c31af7Sopenharmony_ci	DE_ASSERT(copiedSize != 0u);
1599e5c31af7Sopenharmony_ci
1600e5c31af7Sopenharmony_ci	create(vk, device, allocator, copiedSize, deviceAddress);
1601e5c31af7Sopenharmony_ci	copyFrom(vk, device, cmdBuffer, accelerationStructure, compactCopySize > 0u);
1602e5c31af7Sopenharmony_ci}
1603e5c31af7Sopenharmony_ci
1604e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructure::createAndDeserializeFrom (const DeviceInterface& vk,
1605e5c31af7Sopenharmony_ci																 const VkDevice								device,
1606e5c31af7Sopenharmony_ci																 const VkCommandBuffer						cmdBuffer,
1607e5c31af7Sopenharmony_ci																 Allocator&									allocator,
1608e5c31af7Sopenharmony_ci																 SerialStorage*								storage,
1609e5c31af7Sopenharmony_ci																 VkDeviceAddress							deviceAddress )
1610e5c31af7Sopenharmony_ci{
1611e5c31af7Sopenharmony_ci	DE_ASSERT(storage != NULL);
1612e5c31af7Sopenharmony_ci	DE_ASSERT(storage->getStorageSize() >= SerialStorage::SERIAL_STORAGE_SIZE_MIN);
1613e5c31af7Sopenharmony_ci	create(vk, device, allocator, storage->getDeserializedSize(), deviceAddress);
1614e5c31af7Sopenharmony_ci	deserialize(vk, device, cmdBuffer, storage);
1615e5c31af7Sopenharmony_ci}
1616e5c31af7Sopenharmony_ci
1617e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructureKHR::updateGeometry (size_t									geometryIndex,
1618e5c31af7Sopenharmony_ci														  de::SharedPtr<RaytracedGeometryBase>&	raytracedGeometry)
1619e5c31af7Sopenharmony_ci{
1620e5c31af7Sopenharmony_ci	DE_ASSERT(geometryIndex < m_geometriesData.size());
1621e5c31af7Sopenharmony_ci	m_geometriesData[geometryIndex] = raytracedGeometry;
1622e5c31af7Sopenharmony_ci}
1623e5c31af7Sopenharmony_ci
1624e5c31af7Sopenharmony_cide::MovePtr<BottomLevelAccelerationStructure> makeBottomLevelAccelerationStructure ()
1625e5c31af7Sopenharmony_ci{
1626e5c31af7Sopenharmony_ci	return de::MovePtr<BottomLevelAccelerationStructure>(new BottomLevelAccelerationStructureKHR);
1627e5c31af7Sopenharmony_ci}
1628e5c31af7Sopenharmony_ci
1629e5c31af7Sopenharmony_ci// Forward declaration
1630e5c31af7Sopenharmony_cistruct BottomLevelAccelerationStructurePoolImpl;
1631e5c31af7Sopenharmony_ci
1632e5c31af7Sopenharmony_ciclass BottomLevelAccelerationStructurePoolMember : public BottomLevelAccelerationStructureKHR
1633e5c31af7Sopenharmony_ci{
1634e5c31af7Sopenharmony_cipublic:
1635e5c31af7Sopenharmony_ci	friend class BottomLevelAccelerationStructurePool;
1636e5c31af7Sopenharmony_ci
1637e5c31af7Sopenharmony_ci								BottomLevelAccelerationStructurePoolMember	(BottomLevelAccelerationStructurePoolImpl& pool);
1638e5c31af7Sopenharmony_ci								BottomLevelAccelerationStructurePoolMember	(const BottomLevelAccelerationStructurePoolMember&) = delete;
1639e5c31af7Sopenharmony_ci								BottomLevelAccelerationStructurePoolMember	(BottomLevelAccelerationStructurePoolMember&&) = delete;
1640e5c31af7Sopenharmony_ci	virtual						~BottomLevelAccelerationStructurePoolMember	() = default;
1641e5c31af7Sopenharmony_ci
1642e5c31af7Sopenharmony_ci	virtual void				create										(const DeviceInterface&,
1643e5c31af7Sopenharmony_ci																			 const VkDevice,
1644e5c31af7Sopenharmony_ci																			 Allocator&,
1645e5c31af7Sopenharmony_ci																			 VkDeviceSize,
1646e5c31af7Sopenharmony_ci																			 VkDeviceAddress,
1647e5c31af7Sopenharmony_ci																			 const void*,
1648e5c31af7Sopenharmony_ci																			 const MemoryRequirement&,
1649e5c31af7Sopenharmony_ci																			 const VkBuffer,
1650e5c31af7Sopenharmony_ci																			 const VkDeviceSize) override
1651e5c31af7Sopenharmony_ci								{
1652e5c31af7Sopenharmony_ci									DE_ASSERT(0); // Silent this method
1653e5c31af7Sopenharmony_ci								}
1654e5c31af7Sopenharmony_ci	virtual auto				computeBuildSize							(const DeviceInterface&	vk,
1655e5c31af7Sopenharmony_ci																			 const VkDevice			device,
1656e5c31af7Sopenharmony_ci																			 const VkDeviceSize		strSize) const
1657e5c31af7Sopenharmony_ci																			 //              accStrSize,updateScratch, buildScratch, vertexSize,   indexSize
1658e5c31af7Sopenharmony_ci																			 -> std::tuple<VkDeviceSize, VkDeviceSize, VkDeviceSize, VkDeviceSize, VkDeviceSize>;
1659e5c31af7Sopenharmony_ciprotected:
1660e5c31af7Sopenharmony_ci	struct Info;
1661e5c31af7Sopenharmony_ci	virtual void				preCreateSetSizesAndOffsets					(const Info&			info,
1662e5c31af7Sopenharmony_ci																			 const VkDeviceSize		accStrSize,
1663e5c31af7Sopenharmony_ci																			 const VkDeviceSize		updateScratchSize,
1664e5c31af7Sopenharmony_ci																			 const VkDeviceSize		buildScratchSize);
1665e5c31af7Sopenharmony_ci	virtual void				createAccellerationStructure				(const DeviceInterface&	vk,
1666e5c31af7Sopenharmony_ci																			 const VkDevice			device,
1667e5c31af7Sopenharmony_ci																			 VkDeviceAddress		deviceAddress);
1668e5c31af7Sopenharmony_ci
1669e5c31af7Sopenharmony_ci	virtual BufferWithMemory*	getAccelerationStructureBuffer				() const override;
1670e5c31af7Sopenharmony_ci	virtual BufferWithMemory*	getDeviceScratchBuffer						() const override;
1671e5c31af7Sopenharmony_ci	virtual std::vector<deUint8>*	getHostScratchBuffer					() const override;
1672e5c31af7Sopenharmony_ci	virtual BufferWithMemory*	getVertexBuffer								() const override;
1673e5c31af7Sopenharmony_ci	virtual BufferWithMemory*	getIndexBuffer								() const override;
1674e5c31af7Sopenharmony_ci
1675e5c31af7Sopenharmony_ci	virtual VkDeviceSize		getAccelerationStructureBufferOffset		() const override { return m_info.accStrOffset; }
1676e5c31af7Sopenharmony_ci	virtual VkDeviceSize		getDeviceScratchBufferOffset				() const override { return m_info.buildScratchBuffOffset; }
1677e5c31af7Sopenharmony_ci	virtual VkDeviceSize		getVertexBufferOffset						() const override { return m_info.vertBuffOffset; }
1678e5c31af7Sopenharmony_ci	virtual VkDeviceSize		getIndexBufferOffset						() const override { return m_info.indexBuffOffset; }
1679e5c31af7Sopenharmony_ci
1680e5c31af7Sopenharmony_ci	BottomLevelAccelerationStructurePoolImpl&	m_pool;
1681e5c31af7Sopenharmony_ci
1682e5c31af7Sopenharmony_ci	struct Info
1683e5c31af7Sopenharmony_ci	{
1684e5c31af7Sopenharmony_ci		deUint32				accStrIndex;
1685e5c31af7Sopenharmony_ci		VkDeviceSize			accStrOffset;
1686e5c31af7Sopenharmony_ci		deUint32				vertBuffIndex;
1687e5c31af7Sopenharmony_ci		VkDeviceSize			vertBuffOffset;
1688e5c31af7Sopenharmony_ci		deUint32				indexBuffIndex;
1689e5c31af7Sopenharmony_ci		VkDeviceSize			indexBuffOffset;
1690e5c31af7Sopenharmony_ci		deUint32				buildScratchBuffIndex;
1691e5c31af7Sopenharmony_ci		VkDeviceSize			buildScratchBuffOffset;
1692e5c31af7Sopenharmony_ci	}											m_info;
1693e5c31af7Sopenharmony_ci};
1694e5c31af7Sopenharmony_ci
1695e5c31af7Sopenharmony_citemplate<class X> inline X negz (const X&)
1696e5c31af7Sopenharmony_ci{
1697e5c31af7Sopenharmony_ci	return (~static_cast<X>(0));
1698e5c31af7Sopenharmony_ci}
1699e5c31af7Sopenharmony_citemplate<class X> inline bool isnegz (const X& x)
1700e5c31af7Sopenharmony_ci{
1701e5c31af7Sopenharmony_ci	return x == negz(x);
1702e5c31af7Sopenharmony_ci}
1703e5c31af7Sopenharmony_citemplate<class Y> inline auto make_unsigned(const Y& y) -> typename std::make_unsigned<Y>::type
1704e5c31af7Sopenharmony_ci{
1705e5c31af7Sopenharmony_ci	return static_cast<typename std::make_unsigned<Y>::type>(y);
1706e5c31af7Sopenharmony_ci}
1707e5c31af7Sopenharmony_ci
1708e5c31af7Sopenharmony_ciBottomLevelAccelerationStructurePoolMember::BottomLevelAccelerationStructurePoolMember	(BottomLevelAccelerationStructurePoolImpl& pool)
1709e5c31af7Sopenharmony_ci	: m_pool	(pool)
1710e5c31af7Sopenharmony_ci	, m_info	{}
1711e5c31af7Sopenharmony_ci{
1712e5c31af7Sopenharmony_ci}
1713e5c31af7Sopenharmony_ci
1714e5c31af7Sopenharmony_cistruct BottomLevelAccelerationStructurePoolImpl
1715e5c31af7Sopenharmony_ci{
1716e5c31af7Sopenharmony_ci	BottomLevelAccelerationStructurePoolImpl (BottomLevelAccelerationStructurePoolImpl&&) = delete;
1717e5c31af7Sopenharmony_ci	BottomLevelAccelerationStructurePoolImpl (const BottomLevelAccelerationStructurePoolImpl&) = delete;
1718e5c31af7Sopenharmony_ci	BottomLevelAccelerationStructurePoolImpl (BottomLevelAccelerationStructurePool& pool);
1719e5c31af7Sopenharmony_ci
1720e5c31af7Sopenharmony_ci	BottomLevelAccelerationStructurePool&			m_pool;
1721e5c31af7Sopenharmony_ci	std::vector<de::SharedPtr<BufferWithMemory>>	m_accellerationStructureBuffers;
1722e5c31af7Sopenharmony_ci	de::SharedPtr<BufferWithMemory>					m_deviceScratchBuffer;
1723e5c31af7Sopenharmony_ci	de::UniquePtr<std::vector<deUint8>>				m_hostScratchBuffer;
1724e5c31af7Sopenharmony_ci	std::vector<de::SharedPtr<BufferWithMemory>>	m_vertexBuffers;
1725e5c31af7Sopenharmony_ci	std::vector<de::SharedPtr<BufferWithMemory>>	m_indexBuffers;
1726e5c31af7Sopenharmony_ci};
1727e5c31af7Sopenharmony_ciBottomLevelAccelerationStructurePoolImpl::BottomLevelAccelerationStructurePoolImpl (BottomLevelAccelerationStructurePool& pool)
1728e5c31af7Sopenharmony_ci	: m_pool							(pool)
1729e5c31af7Sopenharmony_ci	, m_accellerationStructureBuffers	()
1730e5c31af7Sopenharmony_ci	, m_deviceScratchBuffer				()
1731e5c31af7Sopenharmony_ci	, m_hostScratchBuffer				(new std::vector<deUint8>)
1732e5c31af7Sopenharmony_ci	, m_vertexBuffers					()
1733e5c31af7Sopenharmony_ci	, m_indexBuffers					()
1734e5c31af7Sopenharmony_ci{
1735e5c31af7Sopenharmony_ci}
1736e5c31af7Sopenharmony_ciBufferWithMemory* BottomLevelAccelerationStructurePoolMember::getAccelerationStructureBuffer () const
1737e5c31af7Sopenharmony_ci{
1738e5c31af7Sopenharmony_ci	BufferWithMemory* result = nullptr;
1739e5c31af7Sopenharmony_ci	if (m_pool.m_accellerationStructureBuffers.size())
1740e5c31af7Sopenharmony_ci	{
1741e5c31af7Sopenharmony_ci		DE_ASSERT(!isnegz(m_info.accStrIndex));
1742e5c31af7Sopenharmony_ci		result = m_pool.m_accellerationStructureBuffers[m_info.accStrIndex].get();
1743e5c31af7Sopenharmony_ci	}
1744e5c31af7Sopenharmony_ci	return result;
1745e5c31af7Sopenharmony_ci}
1746e5c31af7Sopenharmony_ciBufferWithMemory* BottomLevelAccelerationStructurePoolMember::getDeviceScratchBuffer () const
1747e5c31af7Sopenharmony_ci{
1748e5c31af7Sopenharmony_ci	DE_ASSERT(m_info.buildScratchBuffIndex == 0);
1749e5c31af7Sopenharmony_ci	return m_pool.m_deviceScratchBuffer.get();
1750e5c31af7Sopenharmony_ci}
1751e5c31af7Sopenharmony_cistd::vector<deUint8>* BottomLevelAccelerationStructurePoolMember::getHostScratchBuffer () const
1752e5c31af7Sopenharmony_ci{
1753e5c31af7Sopenharmony_ci	return this->m_buildScratchSize ? m_pool.m_hostScratchBuffer.get() : nullptr;
1754e5c31af7Sopenharmony_ci}
1755e5c31af7Sopenharmony_ci
1756e5c31af7Sopenharmony_ciBufferWithMemory* BottomLevelAccelerationStructurePoolMember::getVertexBuffer () const
1757e5c31af7Sopenharmony_ci{
1758e5c31af7Sopenharmony_ci	BufferWithMemory* result = nullptr;
1759e5c31af7Sopenharmony_ci	if (m_pool.m_vertexBuffers.size())
1760e5c31af7Sopenharmony_ci	{
1761e5c31af7Sopenharmony_ci		DE_ASSERT(!isnegz(m_info.vertBuffIndex));
1762e5c31af7Sopenharmony_ci		result = m_pool.m_vertexBuffers[m_info.vertBuffIndex].get();
1763e5c31af7Sopenharmony_ci	}
1764e5c31af7Sopenharmony_ci	return result;
1765e5c31af7Sopenharmony_ci}
1766e5c31af7Sopenharmony_ciBufferWithMemory* BottomLevelAccelerationStructurePoolMember::getIndexBuffer () const
1767e5c31af7Sopenharmony_ci{
1768e5c31af7Sopenharmony_ci	BufferWithMemory* result = nullptr;
1769e5c31af7Sopenharmony_ci	if (m_pool.m_indexBuffers.size())
1770e5c31af7Sopenharmony_ci	{
1771e5c31af7Sopenharmony_ci		DE_ASSERT(!isnegz(m_info.indexBuffIndex));
1772e5c31af7Sopenharmony_ci		result = m_pool.m_indexBuffers[m_info.indexBuffIndex].get();
1773e5c31af7Sopenharmony_ci	}
1774e5c31af7Sopenharmony_ci	return result;
1775e5c31af7Sopenharmony_ci}
1776e5c31af7Sopenharmony_ci
1777e5c31af7Sopenharmony_cistruct BottomLevelAccelerationStructurePool::Impl : BottomLevelAccelerationStructurePoolImpl
1778e5c31af7Sopenharmony_ci{
1779e5c31af7Sopenharmony_ci	friend class BottomLevelAccelerationStructurePool;
1780e5c31af7Sopenharmony_ci	friend class BottomLevelAccelerationStructurePoolMember;
1781e5c31af7Sopenharmony_ci
1782e5c31af7Sopenharmony_ci	Impl (BottomLevelAccelerationStructurePool& pool)
1783e5c31af7Sopenharmony_ci		: BottomLevelAccelerationStructurePoolImpl(pool) { }
1784e5c31af7Sopenharmony_ci};
1785e5c31af7Sopenharmony_ci
1786e5c31af7Sopenharmony_ciBottomLevelAccelerationStructurePool::BottomLevelAccelerationStructurePool ()
1787e5c31af7Sopenharmony_ci	: m_batchStructCount	(4)
1788e5c31af7Sopenharmony_ci	, m_batchGeomCount		(0)
1789e5c31af7Sopenharmony_ci	, m_infos				()
1790e5c31af7Sopenharmony_ci	, m_structs				()
1791e5c31af7Sopenharmony_ci	, m_createOnce			(false)
1792e5c31af7Sopenharmony_ci	, m_tryCachedMemory		(true)
1793e5c31af7Sopenharmony_ci	, m_structsBuffSize		(0)
1794e5c31af7Sopenharmony_ci	, m_updatesScratchSize	(0)
1795e5c31af7Sopenharmony_ci	, m_buildsScratchSize	(0)
1796e5c31af7Sopenharmony_ci	, m_verticesSize		(0)
1797e5c31af7Sopenharmony_ci	, m_indicesSize			(0)
1798e5c31af7Sopenharmony_ci	, m_impl				(new Impl(*this))
1799e5c31af7Sopenharmony_ci{
1800e5c31af7Sopenharmony_ci}
1801e5c31af7Sopenharmony_ci
1802e5c31af7Sopenharmony_ciBottomLevelAccelerationStructurePool::~BottomLevelAccelerationStructurePool()
1803e5c31af7Sopenharmony_ci{
1804e5c31af7Sopenharmony_ci	delete m_impl;
1805e5c31af7Sopenharmony_ci}
1806e5c31af7Sopenharmony_ci
1807e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructurePool::batchStructCount (const deUint32& value)
1808e5c31af7Sopenharmony_ci{
1809e5c31af7Sopenharmony_ci	DE_ASSERT(value >= 1); m_batchStructCount = value;
1810e5c31af7Sopenharmony_ci}
1811e5c31af7Sopenharmony_ci
1812e5c31af7Sopenharmony_ciauto BottomLevelAccelerationStructurePool::add (VkDeviceSize		structureSize,
1813e5c31af7Sopenharmony_ci												VkDeviceAddress		deviceAddress) -> BottomLevelAccelerationStructurePool::BlasPtr
1814e5c31af7Sopenharmony_ci{
1815e5c31af7Sopenharmony_ci	// Prevent a programmer from calling this method after batchCreate(...) method has been called.
1816e5c31af7Sopenharmony_ci	if (m_createOnce) DE_ASSERT(0);
1817e5c31af7Sopenharmony_ci
1818e5c31af7Sopenharmony_ci	auto blas = new BottomLevelAccelerationStructurePoolMember(*m_impl);
1819e5c31af7Sopenharmony_ci	m_infos.push_back({structureSize, deviceAddress});
1820e5c31af7Sopenharmony_ci	m_structs.emplace_back(blas);
1821e5c31af7Sopenharmony_ci	return m_structs.back();
1822e5c31af7Sopenharmony_ci}
1823e5c31af7Sopenharmony_ci
1824e5c31af7Sopenharmony_civoid adjustBatchCount (const DeviceInterface&		vkd,
1825e5c31af7Sopenharmony_ci					   const VkDevice				device,
1826e5c31af7Sopenharmony_ci					   const std::vector<BottomLevelAccelerationStructurePool::BlasPtr>& structs,
1827e5c31af7Sopenharmony_ci					   const std::vector<BottomLevelAccelerationStructurePool::BlasInfo>& infos,
1828e5c31af7Sopenharmony_ci					   const VkDeviceSize			maxBufferSize,
1829e5c31af7Sopenharmony_ci					   deUint32						(&result)[4])
1830e5c31af7Sopenharmony_ci{
1831e5c31af7Sopenharmony_ci	tcu::Vector<VkDeviceSize, 4>	sizes(0);
1832e5c31af7Sopenharmony_ci	tcu::Vector<VkDeviceSize, 4>	sums(0);
1833e5c31af7Sopenharmony_ci	tcu::Vector<deUint32, 4>		tmps(0);
1834e5c31af7Sopenharmony_ci	tcu::Vector<deUint32, 4>		batches(0);
1835e5c31af7Sopenharmony_ci
1836e5c31af7Sopenharmony_ci	VkDeviceSize	updateScratchSize = 0;	static_cast<void>(updateScratchSize);	// not used yet, disabled for future implementation
1837e5c31af7Sopenharmony_ci
1838e5c31af7Sopenharmony_ci	auto updateIf = [&](deUint32 c)
1839e5c31af7Sopenharmony_ci	{
1840e5c31af7Sopenharmony_ci		if (sums[c] + sizes[c] <= maxBufferSize)
1841e5c31af7Sopenharmony_ci		{
1842e5c31af7Sopenharmony_ci			sums[c] += sizes[c];
1843e5c31af7Sopenharmony_ci			tmps[c] += 1;
1844e5c31af7Sopenharmony_ci
1845e5c31af7Sopenharmony_ci			batches[c] = std::max(tmps[c], batches[c]);
1846e5c31af7Sopenharmony_ci		}
1847e5c31af7Sopenharmony_ci		else
1848e5c31af7Sopenharmony_ci		{
1849e5c31af7Sopenharmony_ci			sums[c] = 0;
1850e5c31af7Sopenharmony_ci			tmps[c] = 0;
1851e5c31af7Sopenharmony_ci		}
1852e5c31af7Sopenharmony_ci	};
1853e5c31af7Sopenharmony_ci
1854e5c31af7Sopenharmony_ci	const deUint32	maxIter	= static_cast<deUint32>(structs.size());
1855e5c31af7Sopenharmony_ci	for (deUint32 i = 0; i < maxIter; ++i)
1856e5c31af7Sopenharmony_ci	{
1857e5c31af7Sopenharmony_ci		auto& str = *dynamic_cast<BottomLevelAccelerationStructurePoolMember*>(structs[i].get());
1858e5c31af7Sopenharmony_ci		std::tie(sizes[0], updateScratchSize, sizes[1], sizes[2], sizes[3]) = str.computeBuildSize(vkd, device, infos[i].structureSize);
1859e5c31af7Sopenharmony_ci
1860e5c31af7Sopenharmony_ci		updateIf(0);
1861e5c31af7Sopenharmony_ci		updateIf(1);
1862e5c31af7Sopenharmony_ci		updateIf(2);
1863e5c31af7Sopenharmony_ci		updateIf(3);
1864e5c31af7Sopenharmony_ci	}
1865e5c31af7Sopenharmony_ci
1866e5c31af7Sopenharmony_ci	result[0] = std::max(batches[0], 1u);
1867e5c31af7Sopenharmony_ci	result[1] = std::max(batches[1], 1u);
1868e5c31af7Sopenharmony_ci	result[2] = std::max(batches[2], 1u);
1869e5c31af7Sopenharmony_ci	result[3] = std::max(batches[3], 1u);
1870e5c31af7Sopenharmony_ci}
1871e5c31af7Sopenharmony_ci
1872e5c31af7Sopenharmony_cisize_t BottomLevelAccelerationStructurePool::getAllocationCount () const
1873e5c31af7Sopenharmony_ci{
1874e5c31af7Sopenharmony_ci	return m_impl->m_accellerationStructureBuffers.size()
1875e5c31af7Sopenharmony_ci			+ m_impl->m_vertexBuffers.size()
1876e5c31af7Sopenharmony_ci			+ m_impl->m_indexBuffers.size()
1877e5c31af7Sopenharmony_ci			+ 1 /* for scratch buffer */;
1878e5c31af7Sopenharmony_ci}
1879e5c31af7Sopenharmony_ci
1880e5c31af7Sopenharmony_cisize_t BottomLevelAccelerationStructurePool::getAllocationCount (const DeviceInterface&		vk,
1881e5c31af7Sopenharmony_ci																 const VkDevice				device,
1882e5c31af7Sopenharmony_ci																 const VkDeviceSize			maxBufferSize) const
1883e5c31af7Sopenharmony_ci{
1884e5c31af7Sopenharmony_ci	DE_ASSERT(m_structs.size() != 0);
1885e5c31af7Sopenharmony_ci
1886e5c31af7Sopenharmony_ci	std::map<deUint32, VkDeviceSize>	accStrSizes;
1887e5c31af7Sopenharmony_ci	std::map<deUint32, VkDeviceSize>	vertBuffSizes;
1888e5c31af7Sopenharmony_ci	std::map<deUint32, VkDeviceSize>	indexBuffSizes;
1889e5c31af7Sopenharmony_ci	std::map<deUint32, VkDeviceSize>	scratchBuffSizes;
1890e5c31af7Sopenharmony_ci
1891e5c31af7Sopenharmony_ci	const deUint32	allStructsCount		= structCount();
1892e5c31af7Sopenharmony_ci
1893e5c31af7Sopenharmony_ci	deUint32		batchStructCount	= m_batchStructCount;
1894e5c31af7Sopenharmony_ci	deUint32		batchScratchCount	= m_batchStructCount;
1895e5c31af7Sopenharmony_ci	deUint32		batchVertexCount	= m_batchGeomCount ? m_batchGeomCount : m_batchStructCount;
1896e5c31af7Sopenharmony_ci	deUint32		batchIndexCount		= batchVertexCount;
1897e5c31af7Sopenharmony_ci
1898e5c31af7Sopenharmony_ci	if (!isnegz(maxBufferSize))
1899e5c31af7Sopenharmony_ci	{
1900e5c31af7Sopenharmony_ci		deUint32	batches[4];
1901e5c31af7Sopenharmony_ci		adjustBatchCount(vk, device, m_structs, m_infos, maxBufferSize, batches);
1902e5c31af7Sopenharmony_ci		batchStructCount	= batches[0];
1903e5c31af7Sopenharmony_ci		batchScratchCount	= batches[1];
1904e5c31af7Sopenharmony_ci		batchVertexCount	= batches[2];
1905e5c31af7Sopenharmony_ci		batchIndexCount		= batches[3];
1906e5c31af7Sopenharmony_ci	}
1907e5c31af7Sopenharmony_ci
1908e5c31af7Sopenharmony_ci	deUint32		iStr				= 0;
1909e5c31af7Sopenharmony_ci	deUint32		iScratch			= 0;
1910e5c31af7Sopenharmony_ci	deUint32		iVertex				= 0;
1911e5c31af7Sopenharmony_ci	deUint32		iIndex				= 0;
1912e5c31af7Sopenharmony_ci
1913e5c31af7Sopenharmony_ci	VkDeviceSize	strSize				= 0;
1914e5c31af7Sopenharmony_ci	VkDeviceSize	updateScratchSize	= 0;
1915e5c31af7Sopenharmony_ci	VkDeviceSize	buildScratchSize	= 0;
1916e5c31af7Sopenharmony_ci	VkDeviceSize	vertexSize			= 0;
1917e5c31af7Sopenharmony_ci	VkDeviceSize	indexSize			= 0;
1918e5c31af7Sopenharmony_ci
1919e5c31af7Sopenharmony_ci	for (; iStr < allStructsCount; ++iStr)
1920e5c31af7Sopenharmony_ci	{
1921e5c31af7Sopenharmony_ci		auto& str = *dynamic_cast<BottomLevelAccelerationStructurePoolMember*>(m_structs[iStr].get());
1922e5c31af7Sopenharmony_ci		std::tie(strSize, updateScratchSize, buildScratchSize, vertexSize, indexSize) = str.computeBuildSize(vk, device, m_infos[iStr].structureSize);
1923e5c31af7Sopenharmony_ci
1924e5c31af7Sopenharmony_ci		{
1925e5c31af7Sopenharmony_ci			const VkDeviceSize	alignedStrSize	= deAlign64(strSize, 256);
1926e5c31af7Sopenharmony_ci			const deUint32		accStrIndex		= (iStr / batchStructCount);
1927e5c31af7Sopenharmony_ci			accStrSizes[accStrIndex]	+= alignedStrSize;
1928e5c31af7Sopenharmony_ci		}
1929e5c31af7Sopenharmony_ci
1930e5c31af7Sopenharmony_ci		if (buildScratchSize != 0)
1931e5c31af7Sopenharmony_ci		{
1932e5c31af7Sopenharmony_ci			const VkDeviceSize	alignedBuilsScratchSize	= deAlign64(buildScratchSize, 256);
1933e5c31af7Sopenharmony_ci			const deUint32		scratchBuffIndex		= (iScratch/ batchScratchCount);
1934e5c31af7Sopenharmony_ci			scratchBuffSizes[scratchBuffIndex]	+= alignedBuilsScratchSize;
1935e5c31af7Sopenharmony_ci			iScratch							+= 1;
1936e5c31af7Sopenharmony_ci		}
1937e5c31af7Sopenharmony_ci
1938e5c31af7Sopenharmony_ci		if (vertexSize != 0)
1939e5c31af7Sopenharmony_ci		{
1940e5c31af7Sopenharmony_ci			const VkDeviceSize	alignedVertBuffSize	= deAlign64(vertexSize, 8);
1941e5c31af7Sopenharmony_ci			const deUint32		vertBuffIndex		= (iVertex / batchVertexCount);
1942e5c31af7Sopenharmony_ci			vertBuffSizes[vertBuffIndex]	+= alignedVertBuffSize;
1943e5c31af7Sopenharmony_ci			iVertex							+= 1;
1944e5c31af7Sopenharmony_ci		}
1945e5c31af7Sopenharmony_ci
1946e5c31af7Sopenharmony_ci		if (indexSize != 0)
1947e5c31af7Sopenharmony_ci		{
1948e5c31af7Sopenharmony_ci			const VkDeviceSize	alignedIndexBuffSize	= deAlign64(indexSize, 8);
1949e5c31af7Sopenharmony_ci			const deUint32		indexBuffIndex			= (iIndex / batchIndexCount);
1950e5c31af7Sopenharmony_ci			indexBuffSizes[indexBuffIndex]	+= alignedIndexBuffSize;
1951e5c31af7Sopenharmony_ci			iIndex							+= 1;
1952e5c31af7Sopenharmony_ci		}
1953e5c31af7Sopenharmony_ci	}
1954e5c31af7Sopenharmony_ci
1955e5c31af7Sopenharmony_ci	return accStrSizes.size()
1956e5c31af7Sopenharmony_ci			+ vertBuffSizes.size()
1957e5c31af7Sopenharmony_ci			+ indexBuffSizes.size()
1958e5c31af7Sopenharmony_ci			+ scratchBuffSizes.size();
1959e5c31af7Sopenharmony_ci}
1960e5c31af7Sopenharmony_ci
1961e5c31af7Sopenharmony_citcu::Vector<VkDeviceSize, 4> BottomLevelAccelerationStructurePool::getAllocationSizes (const DeviceInterface&		vk,
1962e5c31af7Sopenharmony_ci																					   const VkDevice				device) const
1963e5c31af7Sopenharmony_ci{
1964e5c31af7Sopenharmony_ci	if (m_structsBuffSize)
1965e5c31af7Sopenharmony_ci	{
1966e5c31af7Sopenharmony_ci		return tcu::Vector<VkDeviceSize, 4>(m_structsBuffSize, m_buildsScratchSize, m_verticesSize, m_indicesSize);
1967e5c31af7Sopenharmony_ci	}
1968e5c31af7Sopenharmony_ci
1969e5c31af7Sopenharmony_ci	VkDeviceSize strSize				= 0;
1970e5c31af7Sopenharmony_ci	VkDeviceSize updateScratchSize		= 0;	static_cast<void>(updateScratchSize);		// not used yet, disabled for future implementation
1971e5c31af7Sopenharmony_ci	VkDeviceSize buildScratchSize		= 0;
1972e5c31af7Sopenharmony_ci	VkDeviceSize vertexSize				= 0;
1973e5c31af7Sopenharmony_ci	VkDeviceSize indexSize				= 0;
1974e5c31af7Sopenharmony_ci	VkDeviceSize sumStrSize				= 0;
1975e5c31af7Sopenharmony_ci	VkDeviceSize sumUpdateScratchSize	= 0;	static_cast<void>(sumUpdateScratchSize);	// not used yet, disabled for future implementation
1976e5c31af7Sopenharmony_ci	VkDeviceSize sumBuildScratchSize	= 0;
1977e5c31af7Sopenharmony_ci	VkDeviceSize sumVertexSize			= 0;
1978e5c31af7Sopenharmony_ci	VkDeviceSize sumIndexSize			= 0;
1979e5c31af7Sopenharmony_ci	for (size_t i = 0; i < structCount(); ++i)
1980e5c31af7Sopenharmony_ci	{
1981e5c31af7Sopenharmony_ci		auto& str = *dynamic_cast<BottomLevelAccelerationStructurePoolMember*>(m_structs[i].get());
1982e5c31af7Sopenharmony_ci		std::tie(strSize, updateScratchSize, buildScratchSize, vertexSize, indexSize) = str.computeBuildSize(vk, device, m_infos[i].structureSize);
1983e5c31af7Sopenharmony_ci		sumStrSize				+= deAlign64(strSize, 256);
1984e5c31af7Sopenharmony_ci		//sumUpdateScratchSize	+= deAlign64(updateScratchSize, 256);	not used yet, disabled for future implementation
1985e5c31af7Sopenharmony_ci		sumBuildScratchSize		+= deAlign64(buildScratchSize, 256);
1986e5c31af7Sopenharmony_ci		sumVertexSize			+= deAlign64(vertexSize, 8);
1987e5c31af7Sopenharmony_ci		sumIndexSize			+= deAlign64(indexSize, 8);
1988e5c31af7Sopenharmony_ci	}
1989e5c31af7Sopenharmony_ci	return tcu::Vector<VkDeviceSize, 4>(sumStrSize, sumBuildScratchSize, sumVertexSize, sumIndexSize);
1990e5c31af7Sopenharmony_ci}
1991e5c31af7Sopenharmony_ci
1992e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructurePool::batchCreate (const DeviceInterface&		vkd,
1993e5c31af7Sopenharmony_ci														const VkDevice				device,
1994e5c31af7Sopenharmony_ci														Allocator&					allocator)
1995e5c31af7Sopenharmony_ci{
1996e5c31af7Sopenharmony_ci	batchCreateAdjust(vkd, device, allocator, negz<VkDeviceSize>(0));
1997e5c31af7Sopenharmony_ci}
1998e5c31af7Sopenharmony_ci
1999e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructurePool::batchCreateAdjust (const DeviceInterface&	vkd,
2000e5c31af7Sopenharmony_ci															  const VkDevice			device,
2001e5c31af7Sopenharmony_ci															  Allocator&				allocator,
2002e5c31af7Sopenharmony_ci															  const VkDeviceSize		maxBufferSize)
2003e5c31af7Sopenharmony_ci{
2004e5c31af7Sopenharmony_ci	// Prevent a programmer from calling this method more than once.
2005e5c31af7Sopenharmony_ci	if (m_createOnce) DE_ASSERT(0);
2006e5c31af7Sopenharmony_ci
2007e5c31af7Sopenharmony_ci	m_createOnce = true;
2008e5c31af7Sopenharmony_ci	DE_ASSERT(m_structs.size() != 0);
2009e5c31af7Sopenharmony_ci
2010e5c31af7Sopenharmony_ci	auto createAccellerationStructureBuffer = [&](VkDeviceSize bufferSize) -> typename std::add_pointer<BufferWithMemory>::type
2011e5c31af7Sopenharmony_ci	{
2012e5c31af7Sopenharmony_ci		BufferWithMemory* res = nullptr;
2013e5c31af7Sopenharmony_ci		const VkBufferCreateInfo bci = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
2014e5c31af7Sopenharmony_ci
2015e5c31af7Sopenharmony_ci		if (m_tryCachedMemory) try
2016e5c31af7Sopenharmony_ci		{
2017e5c31af7Sopenharmony_ci			res = new BufferWithMemory(vkd, device, allocator, bci, MemoryRequirement::Cached | MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress);
2018e5c31af7Sopenharmony_ci		}
2019e5c31af7Sopenharmony_ci		catch (const tcu::NotSupportedError&)
2020e5c31af7Sopenharmony_ci		{
2021e5c31af7Sopenharmony_ci			res = nullptr;
2022e5c31af7Sopenharmony_ci		}
2023e5c31af7Sopenharmony_ci
2024e5c31af7Sopenharmony_ci		return (nullptr != res)
2025e5c31af7Sopenharmony_ci				? res
2026e5c31af7Sopenharmony_ci				: (new BufferWithMemory(vkd, device, allocator, bci, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
2027e5c31af7Sopenharmony_ci	};
2028e5c31af7Sopenharmony_ci
2029e5c31af7Sopenharmony_ci	auto createDeviceScratchBuffer = [&](VkDeviceSize bufferSize) -> de::SharedPtr<BufferWithMemory>
2030e5c31af7Sopenharmony_ci	{
2031e5c31af7Sopenharmony_ci		const VkBufferCreateInfo bci = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
2032e5c31af7Sopenharmony_ci		BufferWithMemory* p = new BufferWithMemory(vkd, device, allocator, bci, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress);
2033e5c31af7Sopenharmony_ci		return de::SharedPtr<BufferWithMemory>(p);
2034e5c31af7Sopenharmony_ci	};
2035e5c31af7Sopenharmony_ci
2036e5c31af7Sopenharmony_ci	std::map<deUint32, VkDeviceSize>	accStrSizes;
2037e5c31af7Sopenharmony_ci	std::map<deUint32, VkDeviceSize>	vertBuffSizes;
2038e5c31af7Sopenharmony_ci	std::map<deUint32, VkDeviceSize>	indexBuffSizes;
2039e5c31af7Sopenharmony_ci
2040e5c31af7Sopenharmony_ci	const deUint32	allStructsCount		= structCount();
2041e5c31af7Sopenharmony_ci	deUint32		iterKey				= 0;
2042e5c31af7Sopenharmony_ci
2043e5c31af7Sopenharmony_ci	deUint32		batchStructCount	= m_batchStructCount;
2044e5c31af7Sopenharmony_ci	deUint32		batchVertexCount	= m_batchGeomCount ? m_batchGeomCount : m_batchStructCount;
2045e5c31af7Sopenharmony_ci	deUint32		batchIndexCount		= batchVertexCount;
2046e5c31af7Sopenharmony_ci
2047e5c31af7Sopenharmony_ci	if (!isnegz(maxBufferSize))
2048e5c31af7Sopenharmony_ci	{
2049e5c31af7Sopenharmony_ci		deUint32	batches[4];
2050e5c31af7Sopenharmony_ci		adjustBatchCount(vkd, device, m_structs, m_infos, maxBufferSize, batches);
2051e5c31af7Sopenharmony_ci		batchStructCount	= batches[0];
2052e5c31af7Sopenharmony_ci		// batches[1]: batchScratchCount
2053e5c31af7Sopenharmony_ci		batchVertexCount	= batches[2];
2054e5c31af7Sopenharmony_ci		batchIndexCount		= batches[3];
2055e5c31af7Sopenharmony_ci	}
2056e5c31af7Sopenharmony_ci
2057e5c31af7Sopenharmony_ci	deUint32		iStr				= 0;
2058e5c31af7Sopenharmony_ci	deUint32		iVertex				= 0;
2059e5c31af7Sopenharmony_ci	deUint32		iIndex				= 0;
2060e5c31af7Sopenharmony_ci
2061e5c31af7Sopenharmony_ci	VkDeviceSize	strSize				= 0;
2062e5c31af7Sopenharmony_ci	VkDeviceSize	updateScratchSize	= 0;
2063e5c31af7Sopenharmony_ci	VkDeviceSize	buildScratchSize	= 0;
2064e5c31af7Sopenharmony_ci	VkDeviceSize	maxBuildScratchSize	= 0;
2065e5c31af7Sopenharmony_ci	VkDeviceSize	vertexSize			= 0;
2066e5c31af7Sopenharmony_ci	VkDeviceSize	indexSize			= 0;
2067e5c31af7Sopenharmony_ci
2068e5c31af7Sopenharmony_ci	VkDeviceSize	strOffset			= 0;
2069e5c31af7Sopenharmony_ci	VkDeviceSize	vertexOffset		= 0;
2070e5c31af7Sopenharmony_ci	VkDeviceSize	indexOffset			= 0;
2071e5c31af7Sopenharmony_ci
2072e5c31af7Sopenharmony_ci	deUint32		hostStructCount		= 0;
2073e5c31af7Sopenharmony_ci	deUint32		deviceStructCount	= 0;
2074e5c31af7Sopenharmony_ci
2075e5c31af7Sopenharmony_ci	for (; iStr < allStructsCount; ++iStr)
2076e5c31af7Sopenharmony_ci	{
2077e5c31af7Sopenharmony_ci		BottomLevelAccelerationStructurePoolMember::Info info{};
2078e5c31af7Sopenharmony_ci		auto& str = *dynamic_cast<BottomLevelAccelerationStructurePoolMember*>(m_structs[iStr].get());
2079e5c31af7Sopenharmony_ci		std::tie(strSize, updateScratchSize, buildScratchSize, vertexSize, indexSize) = str.computeBuildSize(vkd, device, m_infos[iStr].structureSize);
2080e5c31af7Sopenharmony_ci
2081e5c31af7Sopenharmony_ci		++(str.getBuildType() == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR ? hostStructCount : deviceStructCount);
2082e5c31af7Sopenharmony_ci
2083e5c31af7Sopenharmony_ci		{
2084e5c31af7Sopenharmony_ci			const VkDeviceSize	alignedStrSize	= deAlign64(strSize, 256);
2085e5c31af7Sopenharmony_ci			const deUint32		accStrIndex		= (iStr / batchStructCount);
2086e5c31af7Sopenharmony_ci			if (iStr != 0 && (iStr % batchStructCount) == 0)
2087e5c31af7Sopenharmony_ci			{
2088e5c31af7Sopenharmony_ci				strOffset				= 0;
2089e5c31af7Sopenharmony_ci			}
2090e5c31af7Sopenharmony_ci
2091e5c31af7Sopenharmony_ci			info.accStrIndex			= accStrIndex;
2092e5c31af7Sopenharmony_ci			info.accStrOffset			= strOffset;
2093e5c31af7Sopenharmony_ci			accStrSizes[accStrIndex]	+= alignedStrSize;
2094e5c31af7Sopenharmony_ci			strOffset					+= alignedStrSize;
2095e5c31af7Sopenharmony_ci			m_structsBuffSize			+= alignedStrSize;
2096e5c31af7Sopenharmony_ci		}
2097e5c31af7Sopenharmony_ci
2098e5c31af7Sopenharmony_ci		if (buildScratchSize != 0)
2099e5c31af7Sopenharmony_ci		{
2100e5c31af7Sopenharmony_ci			maxBuildScratchSize = std::max(maxBuildScratchSize, make_unsigned(deAlign64(buildScratchSize, 256u)));
2101e5c31af7Sopenharmony_ci
2102e5c31af7Sopenharmony_ci			info.buildScratchBuffIndex		= 0;
2103e5c31af7Sopenharmony_ci			info.buildScratchBuffOffset		= 0;
2104e5c31af7Sopenharmony_ci		}
2105e5c31af7Sopenharmony_ci
2106e5c31af7Sopenharmony_ci		if (vertexSize != 0)
2107e5c31af7Sopenharmony_ci		{
2108e5c31af7Sopenharmony_ci			const VkDeviceSize	alignedVertBuffSize	= deAlign64(vertexSize, 8);
2109e5c31af7Sopenharmony_ci			const deUint32		vertBuffIndex		= (iVertex / batchVertexCount);
2110e5c31af7Sopenharmony_ci			if (iVertex != 0 && (iVertex % batchVertexCount) == 0)
2111e5c31af7Sopenharmony_ci			{
2112e5c31af7Sopenharmony_ci				vertexOffset				= 0;
2113e5c31af7Sopenharmony_ci			}
2114e5c31af7Sopenharmony_ci
2115e5c31af7Sopenharmony_ci			info.vertBuffIndex				= vertBuffIndex;
2116e5c31af7Sopenharmony_ci			info.vertBuffOffset				= vertexOffset;
2117e5c31af7Sopenharmony_ci			vertBuffSizes[vertBuffIndex]	+= alignedVertBuffSize;
2118e5c31af7Sopenharmony_ci			vertexOffset					+= alignedVertBuffSize;
2119e5c31af7Sopenharmony_ci			m_verticesSize					+= alignedVertBuffSize;
2120e5c31af7Sopenharmony_ci			iVertex							+= 1;
2121e5c31af7Sopenharmony_ci		}
2122e5c31af7Sopenharmony_ci
2123e5c31af7Sopenharmony_ci		if (indexSize != 0)
2124e5c31af7Sopenharmony_ci		{
2125e5c31af7Sopenharmony_ci			const VkDeviceSize	alignedIndexBuffSize	= deAlign64(indexSize, 8);
2126e5c31af7Sopenharmony_ci			const deUint32		indexBuffIndex			= (iIndex / batchIndexCount);
2127e5c31af7Sopenharmony_ci			if (iIndex != 0 && (iIndex % batchIndexCount) == 0)
2128e5c31af7Sopenharmony_ci			{
2129e5c31af7Sopenharmony_ci				indexOffset					= 0;
2130e5c31af7Sopenharmony_ci			}
2131e5c31af7Sopenharmony_ci
2132e5c31af7Sopenharmony_ci			info.indexBuffIndex				= indexBuffIndex;
2133e5c31af7Sopenharmony_ci			info.indexBuffOffset			= indexOffset;
2134e5c31af7Sopenharmony_ci			indexBuffSizes[indexBuffIndex]	+= alignedIndexBuffSize;
2135e5c31af7Sopenharmony_ci			indexOffset						+= alignedIndexBuffSize;
2136e5c31af7Sopenharmony_ci			m_indicesSize					+= alignedIndexBuffSize;
2137e5c31af7Sopenharmony_ci			iIndex							+= 1;
2138e5c31af7Sopenharmony_ci		}
2139e5c31af7Sopenharmony_ci
2140e5c31af7Sopenharmony_ci		str.preCreateSetSizesAndOffsets(info, strSize, updateScratchSize, buildScratchSize);
2141e5c31af7Sopenharmony_ci	}
2142e5c31af7Sopenharmony_ci
2143e5c31af7Sopenharmony_ci	for (iterKey = 0; iterKey < static_cast<deUint32>(accStrSizes.size()); ++iterKey)
2144e5c31af7Sopenharmony_ci	{
2145e5c31af7Sopenharmony_ci		m_impl->m_accellerationStructureBuffers.emplace_back(createAccellerationStructureBuffer(accStrSizes.at(iterKey)));
2146e5c31af7Sopenharmony_ci	}
2147e5c31af7Sopenharmony_ci	for (iterKey = 0; iterKey < static_cast<deUint32>(vertBuffSizes.size()); ++iterKey)
2148e5c31af7Sopenharmony_ci	{
2149e5c31af7Sopenharmony_ci		m_impl->m_vertexBuffers.emplace_back(createVertexBuffer(vkd, device, allocator, vertBuffSizes.at(iterKey)));
2150e5c31af7Sopenharmony_ci	}
2151e5c31af7Sopenharmony_ci	for (iterKey = 0; iterKey < static_cast<deUint32>(indexBuffSizes.size()); ++iterKey)
2152e5c31af7Sopenharmony_ci	{
2153e5c31af7Sopenharmony_ci		m_impl->m_indexBuffers.emplace_back(createIndexBuffer(vkd, device, allocator, indexBuffSizes.at(iterKey)));
2154e5c31af7Sopenharmony_ci	}
2155e5c31af7Sopenharmony_ci
2156e5c31af7Sopenharmony_ci	if (maxBuildScratchSize)
2157e5c31af7Sopenharmony_ci	{
2158e5c31af7Sopenharmony_ci		if (hostStructCount)	m_impl->m_hostScratchBuffer->resize(static_cast<size_t>(maxBuildScratchSize));
2159e5c31af7Sopenharmony_ci		if (deviceStructCount)	m_impl->m_deviceScratchBuffer = createDeviceScratchBuffer(maxBuildScratchSize);
2160e5c31af7Sopenharmony_ci
2161e5c31af7Sopenharmony_ci		m_buildsScratchSize = maxBuildScratchSize;
2162e5c31af7Sopenharmony_ci	}
2163e5c31af7Sopenharmony_ci
2164e5c31af7Sopenharmony_ci	for (iterKey = 0; iterKey < allStructsCount; ++iterKey)
2165e5c31af7Sopenharmony_ci	{
2166e5c31af7Sopenharmony_ci		auto& str = *dynamic_cast<BottomLevelAccelerationStructurePoolMember*>(m_structs[iterKey].get());
2167e5c31af7Sopenharmony_ci		str.createAccellerationStructure(vkd, device, m_infos[iterKey].deviceAddress);
2168e5c31af7Sopenharmony_ci	}
2169e5c31af7Sopenharmony_ci}
2170e5c31af7Sopenharmony_ci
2171e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructurePool::batchBuild (const DeviceInterface&	vk,
2172e5c31af7Sopenharmony_ci													   const VkDevice			device,
2173e5c31af7Sopenharmony_ci													   VkCommandBuffer			cmdBuffer)
2174e5c31af7Sopenharmony_ci{
2175e5c31af7Sopenharmony_ci	for (const auto& str : m_structs)
2176e5c31af7Sopenharmony_ci	{
2177e5c31af7Sopenharmony_ci		str->build(vk, device, cmdBuffer);
2178e5c31af7Sopenharmony_ci	}
2179e5c31af7Sopenharmony_ci}
2180e5c31af7Sopenharmony_ci
2181e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructurePool::batchBuild (const DeviceInterface&	vk,
2182e5c31af7Sopenharmony_ci													   const VkDevice			device,
2183e5c31af7Sopenharmony_ci													   VkCommandPool			cmdPool,
2184e5c31af7Sopenharmony_ci													   VkQueue					queue,
2185e5c31af7Sopenharmony_ci													   qpWatchDog*				watchDog)
2186e5c31af7Sopenharmony_ci{
2187e5c31af7Sopenharmony_ci	const deUint32			limit	= 10000u;
2188e5c31af7Sopenharmony_ci	const deUint32			count	= structCount();
2189e5c31af7Sopenharmony_ci	std::vector<BlasPtr>	buildingOnDevice;
2190e5c31af7Sopenharmony_ci
2191e5c31af7Sopenharmony_ci	auto buildOnDevice = [&]() -> void
2192e5c31af7Sopenharmony_ci	{
2193e5c31af7Sopenharmony_ci		Move<VkCommandBuffer>	cmd = allocateCommandBuffer(vk, device, cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2194e5c31af7Sopenharmony_ci
2195e5c31af7Sopenharmony_ci		beginCommandBuffer(vk, *cmd, 0u);
2196e5c31af7Sopenharmony_ci			for (const auto& str : buildingOnDevice)
2197e5c31af7Sopenharmony_ci				str->build(vk, device, *cmd);
2198e5c31af7Sopenharmony_ci		endCommandBuffer(vk, *cmd);
2199e5c31af7Sopenharmony_ci
2200e5c31af7Sopenharmony_ci		submitCommandsAndWait(vk, device, queue, *cmd);
2201e5c31af7Sopenharmony_ci		vk.resetCommandPool(device, cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
2202e5c31af7Sopenharmony_ci	};
2203e5c31af7Sopenharmony_ci
2204e5c31af7Sopenharmony_ci	buildingOnDevice.reserve(limit);
2205e5c31af7Sopenharmony_ci	for (deUint32 i = 0; i < count; ++i)
2206e5c31af7Sopenharmony_ci	{
2207e5c31af7Sopenharmony_ci		auto str = m_structs[i];
2208e5c31af7Sopenharmony_ci
2209e5c31af7Sopenharmony_ci		if (str->getBuildType() == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR)
2210e5c31af7Sopenharmony_ci			str->build(vk, device, DE_NULL);
2211e5c31af7Sopenharmony_ci		else
2212e5c31af7Sopenharmony_ci			buildingOnDevice.emplace_back(str);
2213e5c31af7Sopenharmony_ci
2214e5c31af7Sopenharmony_ci		if ( buildingOnDevice.size() == limit || (count - 1) == i)
2215e5c31af7Sopenharmony_ci		{
2216e5c31af7Sopenharmony_ci			buildOnDevice();
2217e5c31af7Sopenharmony_ci			buildingOnDevice.clear();
2218e5c31af7Sopenharmony_ci		}
2219e5c31af7Sopenharmony_ci
2220e5c31af7Sopenharmony_ci		if ((i % WATCHDOG_INTERVAL) == 0 && watchDog)
2221e5c31af7Sopenharmony_ci			qpWatchDog_touch(watchDog);
2222e5c31af7Sopenharmony_ci	}
2223e5c31af7Sopenharmony_ci}
2224e5c31af7Sopenharmony_ci
2225e5c31af7Sopenharmony_ciauto BottomLevelAccelerationStructurePoolMember::computeBuildSize (const DeviceInterface&	vk,
2226e5c31af7Sopenharmony_ci																   const VkDevice			device,
2227e5c31af7Sopenharmony_ci																   const VkDeviceSize		strSize) const
2228e5c31af7Sopenharmony_ci																   //              accStrSize,updateScratch,buildScratch, vertexSize, indexSize
2229e5c31af7Sopenharmony_ci																   -> std::tuple<VkDeviceSize, VkDeviceSize,VkDeviceSize,VkDeviceSize,VkDeviceSize>
2230e5c31af7Sopenharmony_ci{
2231e5c31af7Sopenharmony_ci	DE_ASSERT(!m_geometriesData.empty() !=  !(strSize == 0)); // logical xor
2232e5c31af7Sopenharmony_ci
2233e5c31af7Sopenharmony_ci	std::tuple<VkDeviceSize,VkDeviceSize,VkDeviceSize,VkDeviceSize,VkDeviceSize> result(deAlign64(strSize, 256), 0, 0, 0, 0);
2234e5c31af7Sopenharmony_ci
2235e5c31af7Sopenharmony_ci	if (!m_geometriesData.empty())
2236e5c31af7Sopenharmony_ci	{
2237e5c31af7Sopenharmony_ci		std::vector<VkAccelerationStructureGeometryKHR>			accelerationStructureGeometriesKHR;
2238e5c31af7Sopenharmony_ci		std::vector<VkAccelerationStructureGeometryKHR*>		accelerationStructureGeometriesKHRPointers;
2239e5c31af7Sopenharmony_ci		std::vector<VkAccelerationStructureBuildRangeInfoKHR>	accelerationStructureBuildRangeInfoKHR;
2240e5c31af7Sopenharmony_ci		std::vector<VkAccelerationStructureTrianglesOpacityMicromapEXT> accelerationStructureGeometryMicromapsEXT;
2241e5c31af7Sopenharmony_ci		std::vector<deUint32>									maxPrimitiveCounts;
2242e5c31af7Sopenharmony_ci		prepareGeometries(vk, device, accelerationStructureGeometriesKHR, accelerationStructureGeometriesKHRPointers, accelerationStructureBuildRangeInfoKHR, accelerationStructureGeometryMicromapsEXT, maxPrimitiveCounts);
2243e5c31af7Sopenharmony_ci
2244e5c31af7Sopenharmony_ci		const VkAccelerationStructureGeometryKHR*				accelerationStructureGeometriesKHRPointer	= accelerationStructureGeometriesKHR.data();
2245e5c31af7Sopenharmony_ci		const VkAccelerationStructureGeometryKHR* const*		accelerationStructureGeometry				= accelerationStructureGeometriesKHRPointers.data();
2246e5c31af7Sopenharmony_ci
2247e5c31af7Sopenharmony_ci		VkAccelerationStructureBuildGeometryInfoKHR	accelerationStructureBuildGeometryInfoKHR	=
2248e5c31af7Sopenharmony_ci		{
2249e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,			//  VkStructureType										sType;
2250e5c31af7Sopenharmony_ci			DE_NULL,																	//  const void*											pNext;
2251e5c31af7Sopenharmony_ci			VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR,							//  VkAccelerationStructureTypeKHR						type;
2252e5c31af7Sopenharmony_ci			m_buildFlags,																//  VkBuildAccelerationStructureFlagsKHR				flags;
2253e5c31af7Sopenharmony_ci			VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR,								//  VkBuildAccelerationStructureModeKHR					mode;
2254e5c31af7Sopenharmony_ci			DE_NULL,																	//  VkAccelerationStructureKHR							srcAccelerationStructure;
2255e5c31af7Sopenharmony_ci			DE_NULL,																	//  VkAccelerationStructureKHR							dstAccelerationStructure;
2256e5c31af7Sopenharmony_ci			static_cast<deUint32>(accelerationStructureGeometriesKHR.size()),			//  deUint32											geometryCount;
2257e5c31af7Sopenharmony_ci			m_useArrayOfPointers ? DE_NULL : accelerationStructureGeometriesKHRPointer,	//  const VkAccelerationStructureGeometryKHR*			pGeometries;
2258e5c31af7Sopenharmony_ci			m_useArrayOfPointers ? accelerationStructureGeometry : DE_NULL,				//  const VkAccelerationStructureGeometryKHR* const*	ppGeometries;
2259e5c31af7Sopenharmony_ci			makeDeviceOrHostAddressKHR(DE_NULL)											//  VkDeviceOrHostAddressKHR							scratchData;
2260e5c31af7Sopenharmony_ci		};
2261e5c31af7Sopenharmony_ci
2262e5c31af7Sopenharmony_ci		VkAccelerationStructureBuildSizesInfoKHR sizeInfo =
2263e5c31af7Sopenharmony_ci		{
2264e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR,	//  VkStructureType	sType;
2265e5c31af7Sopenharmony_ci			DE_NULL,														//  const void*		pNext;
2266e5c31af7Sopenharmony_ci			0,																//  VkDeviceSize	accelerationStructureSize;
2267e5c31af7Sopenharmony_ci			0,																//  VkDeviceSize	updateScratchSize;
2268e5c31af7Sopenharmony_ci			0																//  VkDeviceSize	buildScratchSize;
2269e5c31af7Sopenharmony_ci		};
2270e5c31af7Sopenharmony_ci
2271e5c31af7Sopenharmony_ci		vk.getAccelerationStructureBuildSizesKHR(device, m_buildType, &accelerationStructureBuildGeometryInfoKHR, maxPrimitiveCounts.data(), &sizeInfo);
2272e5c31af7Sopenharmony_ci
2273e5c31af7Sopenharmony_ci		std::get<0>(result) = sizeInfo.accelerationStructureSize;
2274e5c31af7Sopenharmony_ci		std::get<1>(result) = sizeInfo.updateScratchSize;
2275e5c31af7Sopenharmony_ci		std::get<2>(result) = sizeInfo.buildScratchSize;
2276e5c31af7Sopenharmony_ci		std::get<3>(result) = getVertexBufferSize(m_geometriesData);
2277e5c31af7Sopenharmony_ci		std::get<4>(result) = getIndexBufferSize(m_geometriesData);
2278e5c31af7Sopenharmony_ci	}
2279e5c31af7Sopenharmony_ci
2280e5c31af7Sopenharmony_ci	return result;
2281e5c31af7Sopenharmony_ci}
2282e5c31af7Sopenharmony_ci
2283e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructurePoolMember::preCreateSetSizesAndOffsets (const Info&			info,
2284e5c31af7Sopenharmony_ci																			  const VkDeviceSize	accStrSize,
2285e5c31af7Sopenharmony_ci																			  const VkDeviceSize	updateScratchSize,
2286e5c31af7Sopenharmony_ci																			  const VkDeviceSize	buildScratchSize)
2287e5c31af7Sopenharmony_ci{
2288e5c31af7Sopenharmony_ci	m_info				= info;
2289e5c31af7Sopenharmony_ci	m_structureSize		= accStrSize;
2290e5c31af7Sopenharmony_ci	m_updateScratchSize	= updateScratchSize;
2291e5c31af7Sopenharmony_ci	m_buildScratchSize	= buildScratchSize;
2292e5c31af7Sopenharmony_ci}
2293e5c31af7Sopenharmony_ci
2294e5c31af7Sopenharmony_civoid BottomLevelAccelerationStructurePoolMember::createAccellerationStructure (const DeviceInterface&	vk,
2295e5c31af7Sopenharmony_ci																			   const VkDevice			device,
2296e5c31af7Sopenharmony_ci																			   VkDeviceAddress			deviceAddress)
2297e5c31af7Sopenharmony_ci{
2298e5c31af7Sopenharmony_ci	const VkAccelerationStructureTypeKHR		structureType						= (m_createGeneric
2299e5c31af7Sopenharmony_ci																					   ? VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR
2300e5c31af7Sopenharmony_ci																					   : VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR);
2301e5c31af7Sopenharmony_ci	const VkAccelerationStructureCreateInfoKHR	accelerationStructureCreateInfoKHR
2302e5c31af7Sopenharmony_ci	{
2303e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR,						//  VkStructureType											sType;
2304e5c31af7Sopenharmony_ci		DE_NULL,																		//  const void*												pNext;
2305e5c31af7Sopenharmony_ci		m_createFlags,																	//  VkAccelerationStructureCreateFlagsKHR					createFlags;
2306e5c31af7Sopenharmony_ci		getAccelerationStructureBuffer()->get(),										//  VkBuffer												buffer;
2307e5c31af7Sopenharmony_ci		getAccelerationStructureBufferOffset(),											//  VkDeviceSize											offset;
2308e5c31af7Sopenharmony_ci		m_structureSize,																//  VkDeviceSize											size;
2309e5c31af7Sopenharmony_ci		structureType,																	//  VkAccelerationStructureTypeKHR							type;
2310e5c31af7Sopenharmony_ci		deviceAddress																	//  VkDeviceAddress											deviceAddress;
2311e5c31af7Sopenharmony_ci	};
2312e5c31af7Sopenharmony_ci
2313e5c31af7Sopenharmony_ci	m_accelerationStructureKHR	= createAccelerationStructureKHR(vk, device, &accelerationStructureCreateInfoKHR, DE_NULL);
2314e5c31af7Sopenharmony_ci}
2315e5c31af7Sopenharmony_ci
2316e5c31af7Sopenharmony_ciTopLevelAccelerationStructure::~TopLevelAccelerationStructure ()
2317e5c31af7Sopenharmony_ci{
2318e5c31af7Sopenharmony_ci}
2319e5c31af7Sopenharmony_ci
2320e5c31af7Sopenharmony_ciTopLevelAccelerationStructure::TopLevelAccelerationStructure ()
2321e5c31af7Sopenharmony_ci	: m_structureSize		(0u)
2322e5c31af7Sopenharmony_ci	, m_updateScratchSize	(0u)
2323e5c31af7Sopenharmony_ci	, m_buildScratchSize	(0u)
2324e5c31af7Sopenharmony_ci{
2325e5c31af7Sopenharmony_ci}
2326e5c31af7Sopenharmony_ci
2327e5c31af7Sopenharmony_civoid TopLevelAccelerationStructure::setInstanceCount (const size_t instanceCount)
2328e5c31af7Sopenharmony_ci{
2329e5c31af7Sopenharmony_ci	m_bottomLevelInstances.reserve(instanceCount);
2330e5c31af7Sopenharmony_ci	m_instanceData.reserve(instanceCount);
2331e5c31af7Sopenharmony_ci}
2332e5c31af7Sopenharmony_ci
2333e5c31af7Sopenharmony_civoid TopLevelAccelerationStructure::addInstance (de::SharedPtr<BottomLevelAccelerationStructure>	bottomLevelStructure,
2334e5c31af7Sopenharmony_ci												 const VkTransformMatrixKHR&						matrix,
2335e5c31af7Sopenharmony_ci												 deUint32											instanceCustomIndex,
2336e5c31af7Sopenharmony_ci												 deUint32											mask,
2337e5c31af7Sopenharmony_ci												 deUint32											instanceShaderBindingTableRecordOffset,
2338e5c31af7Sopenharmony_ci												 VkGeometryInstanceFlagsKHR							flags)
2339e5c31af7Sopenharmony_ci{
2340e5c31af7Sopenharmony_ci	m_bottomLevelInstances.push_back(bottomLevelStructure);
2341e5c31af7Sopenharmony_ci	m_instanceData.push_back(InstanceData(matrix, instanceCustomIndex, mask, instanceShaderBindingTableRecordOffset, flags));
2342e5c31af7Sopenharmony_ci}
2343e5c31af7Sopenharmony_ci
2344e5c31af7Sopenharmony_ciVkAccelerationStructureBuildSizesInfoKHR TopLevelAccelerationStructure::getStructureBuildSizes () const
2345e5c31af7Sopenharmony_ci{
2346e5c31af7Sopenharmony_ci	return
2347e5c31af7Sopenharmony_ci	{
2348e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR,	//  VkStructureType	sType;
2349e5c31af7Sopenharmony_ci		DE_NULL,														//  const void*		pNext;
2350e5c31af7Sopenharmony_ci		m_structureSize,												//  VkDeviceSize	accelerationStructureSize;
2351e5c31af7Sopenharmony_ci		m_updateScratchSize,											//  VkDeviceSize	updateScratchSize;
2352e5c31af7Sopenharmony_ci		m_buildScratchSize												//  VkDeviceSize	buildScratchSize;
2353e5c31af7Sopenharmony_ci	};
2354e5c31af7Sopenharmony_ci}
2355e5c31af7Sopenharmony_ci
2356e5c31af7Sopenharmony_civoid TopLevelAccelerationStructure::createAndBuild (const DeviceInterface&	vk,
2357e5c31af7Sopenharmony_ci													const VkDevice			device,
2358e5c31af7Sopenharmony_ci													const VkCommandBuffer	cmdBuffer,
2359e5c31af7Sopenharmony_ci													Allocator&				allocator,
2360e5c31af7Sopenharmony_ci													VkDeviceAddress			deviceAddress)
2361e5c31af7Sopenharmony_ci{
2362e5c31af7Sopenharmony_ci	create(vk, device, allocator, 0u, deviceAddress);
2363e5c31af7Sopenharmony_ci	build(vk, device, cmdBuffer);
2364e5c31af7Sopenharmony_ci}
2365e5c31af7Sopenharmony_ci
2366e5c31af7Sopenharmony_civoid TopLevelAccelerationStructure::createAndCopyFrom (const DeviceInterface&				vk,
2367e5c31af7Sopenharmony_ci													   const VkDevice						device,
2368e5c31af7Sopenharmony_ci													   const VkCommandBuffer				cmdBuffer,
2369e5c31af7Sopenharmony_ci													   Allocator&							allocator,
2370e5c31af7Sopenharmony_ci													   TopLevelAccelerationStructure*		accelerationStructure,
2371e5c31af7Sopenharmony_ci													   VkDeviceSize							compactCopySize,
2372e5c31af7Sopenharmony_ci													   VkDeviceAddress						deviceAddress)
2373e5c31af7Sopenharmony_ci{
2374e5c31af7Sopenharmony_ci	DE_ASSERT(accelerationStructure != NULL);
2375e5c31af7Sopenharmony_ci	VkDeviceSize copiedSize = compactCopySize > 0u ? compactCopySize : accelerationStructure->getStructureBuildSizes().accelerationStructureSize;
2376e5c31af7Sopenharmony_ci	DE_ASSERT(copiedSize != 0u);
2377e5c31af7Sopenharmony_ci
2378e5c31af7Sopenharmony_ci	create(vk, device, allocator, copiedSize, deviceAddress);
2379e5c31af7Sopenharmony_ci	copyFrom(vk, device, cmdBuffer, accelerationStructure, compactCopySize > 0u);
2380e5c31af7Sopenharmony_ci}
2381e5c31af7Sopenharmony_ci
2382e5c31af7Sopenharmony_civoid TopLevelAccelerationStructure::createAndDeserializeFrom (const DeviceInterface&					vk,
2383e5c31af7Sopenharmony_ci															  const VkDevice							device,
2384e5c31af7Sopenharmony_ci															  const VkCommandBuffer						cmdBuffer,
2385e5c31af7Sopenharmony_ci															  Allocator&								allocator,
2386e5c31af7Sopenharmony_ci															  SerialStorage*							storage,
2387e5c31af7Sopenharmony_ci															  VkDeviceAddress							deviceAddress)
2388e5c31af7Sopenharmony_ci{
2389e5c31af7Sopenharmony_ci	DE_ASSERT(storage != NULL);
2390e5c31af7Sopenharmony_ci	DE_ASSERT(storage->getStorageSize() >= SerialStorage::SERIAL_STORAGE_SIZE_MIN);
2391e5c31af7Sopenharmony_ci	create(vk, device, allocator, storage->getDeserializedSize(), deviceAddress);
2392e5c31af7Sopenharmony_ci	if (storage->hasDeepFormat()) createAndDeserializeBottoms(vk, device, cmdBuffer, allocator, storage);
2393e5c31af7Sopenharmony_ci	deserialize(vk, device, cmdBuffer, storage);
2394e5c31af7Sopenharmony_ci}
2395e5c31af7Sopenharmony_ci
2396e5c31af7Sopenharmony_ciBufferWithMemory* createInstanceBuffer (const DeviceInterface&											vk,
2397e5c31af7Sopenharmony_ci										const VkDevice													device,
2398e5c31af7Sopenharmony_ci										Allocator&														allocator,
2399e5c31af7Sopenharmony_ci										std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >	bottomLevelInstances,
2400e5c31af7Sopenharmony_ci										std::vector<InstanceData>										instanceData,
2401e5c31af7Sopenharmony_ci										const bool														tryCachedMemory)
2402e5c31af7Sopenharmony_ci{
2403e5c31af7Sopenharmony_ci	DE_ASSERT(bottomLevelInstances.size() != 0);
2404e5c31af7Sopenharmony_ci	DE_ASSERT(bottomLevelInstances.size() == instanceData.size());
2405e5c31af7Sopenharmony_ci	DE_UNREF(instanceData);
2406e5c31af7Sopenharmony_ci
2407e5c31af7Sopenharmony_ci	BufferWithMemory*			result				= nullptr;
2408e5c31af7Sopenharmony_ci	const VkDeviceSize			bufferSizeBytes		= bottomLevelInstances.size() * sizeof(VkAccelerationStructureInstanceKHR);
2409e5c31af7Sopenharmony_ci	const VkBufferCreateInfo	bufferCreateInfo	= makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
2410e5c31af7Sopenharmony_ci	if (tryCachedMemory) try
2411e5c31af7Sopenharmony_ci	{
2412e5c31af7Sopenharmony_ci		result = new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::Cached | MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress);
2413e5c31af7Sopenharmony_ci	}
2414e5c31af7Sopenharmony_ci	catch (const tcu::NotSupportedError&)
2415e5c31af7Sopenharmony_ci	{
2416e5c31af7Sopenharmony_ci		result = nullptr;
2417e5c31af7Sopenharmony_ci	}
2418e5c31af7Sopenharmony_ci	return result
2419e5c31af7Sopenharmony_ci			? result
2420e5c31af7Sopenharmony_ci			: new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress);
2421e5c31af7Sopenharmony_ci}
2422e5c31af7Sopenharmony_ci
2423e5c31af7Sopenharmony_civoid updateSingleInstance (const DeviceInterface&					vk,
2424e5c31af7Sopenharmony_ci						   const VkDevice							device,
2425e5c31af7Sopenharmony_ci						   const BottomLevelAccelerationStructure&	bottomLevelAccelerationStructure,
2426e5c31af7Sopenharmony_ci						   const InstanceData&						instanceData,
2427e5c31af7Sopenharmony_ci						   deUint8*									bufferLocation,
2428e5c31af7Sopenharmony_ci						   VkAccelerationStructureBuildTypeKHR		buildType,
2429e5c31af7Sopenharmony_ci						   bool										inactiveInstances)
2430e5c31af7Sopenharmony_ci{
2431e5c31af7Sopenharmony_ci	const VkAccelerationStructureKHR accelerationStructureKHR = *bottomLevelAccelerationStructure.getPtr();
2432e5c31af7Sopenharmony_ci
2433e5c31af7Sopenharmony_ci	// This part needs to be fixed once a new version of the VkAccelerationStructureInstanceKHR will be added to vkStructTypes.inl
2434e5c31af7Sopenharmony_ci	VkDeviceAddress accelerationStructureAddress;
2435e5c31af7Sopenharmony_ci	if (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2436e5c31af7Sopenharmony_ci	{
2437e5c31af7Sopenharmony_ci		VkAccelerationStructureDeviceAddressInfoKHR asDeviceAddressInfo =
2438e5c31af7Sopenharmony_ci		{
2439e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR,	// VkStructureType				sType;
2440e5c31af7Sopenharmony_ci			DE_NULL,															// const void*					pNext;
2441e5c31af7Sopenharmony_ci			accelerationStructureKHR											// VkAccelerationStructureKHR	accelerationStructure;
2442e5c31af7Sopenharmony_ci		};
2443e5c31af7Sopenharmony_ci		accelerationStructureAddress = vk.getAccelerationStructureDeviceAddressKHR(device, &asDeviceAddressInfo);
2444e5c31af7Sopenharmony_ci	}
2445e5c31af7Sopenharmony_ci
2446e5c31af7Sopenharmony_ci	deUint64 structureReference;
2447e5c31af7Sopenharmony_ci	if (inactiveInstances)
2448e5c31af7Sopenharmony_ci	{
2449e5c31af7Sopenharmony_ci		// Instances will be marked inactive by making their references VK_NULL_HANDLE or having address zero.
2450e5c31af7Sopenharmony_ci		structureReference = 0ull;
2451e5c31af7Sopenharmony_ci	}
2452e5c31af7Sopenharmony_ci	else
2453e5c31af7Sopenharmony_ci	{
2454e5c31af7Sopenharmony_ci		structureReference	= (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2455e5c31af7Sopenharmony_ci							? deUint64(accelerationStructureAddress)
2456e5c31af7Sopenharmony_ci							: deUint64(accelerationStructureKHR.getInternal());
2457e5c31af7Sopenharmony_ci	}
2458e5c31af7Sopenharmony_ci
2459e5c31af7Sopenharmony_ci	VkAccelerationStructureInstanceKHR	accelerationStructureInstanceKHR = makeVkAccelerationStructureInstanceKHR
2460e5c31af7Sopenharmony_ci	(
2461e5c31af7Sopenharmony_ci		instanceData.matrix,									//  VkTransformMatrixKHR		transform;
2462e5c31af7Sopenharmony_ci		instanceData.instanceCustomIndex,						//  deUint32					instanceCustomIndex:24;
2463e5c31af7Sopenharmony_ci		instanceData.mask,										//  deUint32					mask:8;
2464e5c31af7Sopenharmony_ci		instanceData.instanceShaderBindingTableRecordOffset,	//  deUint32					instanceShaderBindingTableRecordOffset:24;
2465e5c31af7Sopenharmony_ci		instanceData.flags,										//  VkGeometryInstanceFlagsKHR	flags:8;
2466e5c31af7Sopenharmony_ci		structureReference										//  deUint64					accelerationStructureReference;
2467e5c31af7Sopenharmony_ci	);
2468e5c31af7Sopenharmony_ci
2469e5c31af7Sopenharmony_ci	deMemcpy(bufferLocation, &accelerationStructureInstanceKHR, sizeof(VkAccelerationStructureInstanceKHR));
2470e5c31af7Sopenharmony_ci}
2471e5c31af7Sopenharmony_ci
2472e5c31af7Sopenharmony_civoid updateInstanceBuffer (const DeviceInterface&												vk,
2473e5c31af7Sopenharmony_ci						   const VkDevice														device,
2474e5c31af7Sopenharmony_ci						   const std::vector<de::SharedPtr<BottomLevelAccelerationStructure>>&	bottomLevelInstances,
2475e5c31af7Sopenharmony_ci						   const std::vector<InstanceData>&										instanceData,
2476e5c31af7Sopenharmony_ci						   const BufferWithMemory*												instanceBuffer,
2477e5c31af7Sopenharmony_ci						   VkAccelerationStructureBuildTypeKHR									buildType,
2478e5c31af7Sopenharmony_ci						   bool																	inactiveInstances)
2479e5c31af7Sopenharmony_ci{
2480e5c31af7Sopenharmony_ci	DE_ASSERT(bottomLevelInstances.size() != 0);
2481e5c31af7Sopenharmony_ci	DE_ASSERT(bottomLevelInstances.size() == instanceData.size());
2482e5c31af7Sopenharmony_ci
2483e5c31af7Sopenharmony_ci	auto&			instancesAlloc		= instanceBuffer->getAllocation();
2484e5c31af7Sopenharmony_ci	auto			bufferStart			= reinterpret_cast<deUint8*>(instancesAlloc.getHostPtr());
2485e5c31af7Sopenharmony_ci	VkDeviceSize	bufferOffset		= 0ull;
2486e5c31af7Sopenharmony_ci
2487e5c31af7Sopenharmony_ci	for (size_t instanceNdx = 0; instanceNdx < bottomLevelInstances.size(); ++instanceNdx)
2488e5c31af7Sopenharmony_ci	{
2489e5c31af7Sopenharmony_ci		const auto& blas = *bottomLevelInstances[instanceNdx];
2490e5c31af7Sopenharmony_ci		updateSingleInstance(vk, device, blas, instanceData[instanceNdx], bufferStart + bufferOffset, buildType, inactiveInstances);
2491e5c31af7Sopenharmony_ci		bufferOffset += sizeof(VkAccelerationStructureInstanceKHR);
2492e5c31af7Sopenharmony_ci	}
2493e5c31af7Sopenharmony_ci
2494e5c31af7Sopenharmony_ci	flushMappedMemoryRange(vk, device, instancesAlloc.getMemory(), instancesAlloc.getOffset(), VK_WHOLE_SIZE);
2495e5c31af7Sopenharmony_ci}
2496e5c31af7Sopenharmony_ci
2497e5c31af7Sopenharmony_ciclass TopLevelAccelerationStructureKHR : public TopLevelAccelerationStructure
2498e5c31af7Sopenharmony_ci{
2499e5c31af7Sopenharmony_cipublic:
2500e5c31af7Sopenharmony_ci	static deUint32											getRequiredAllocationCount							(void);
2501e5c31af7Sopenharmony_ci
2502e5c31af7Sopenharmony_ci															TopLevelAccelerationStructureKHR					();
2503e5c31af7Sopenharmony_ci															TopLevelAccelerationStructureKHR					(const TopLevelAccelerationStructureKHR&		other) = delete;
2504e5c31af7Sopenharmony_ci	virtual													~TopLevelAccelerationStructureKHR					();
2505e5c31af7Sopenharmony_ci
2506e5c31af7Sopenharmony_ci	void													setBuildType										(const VkAccelerationStructureBuildTypeKHR		buildType) override;
2507e5c31af7Sopenharmony_ci	void													setCreateFlags										(const VkAccelerationStructureCreateFlagsKHR	createFlags) override;
2508e5c31af7Sopenharmony_ci	void													setCreateGeneric									(bool											createGeneric) override;
2509e5c31af7Sopenharmony_ci	void													setCreationBufferUnbounded							(bool											creationBufferUnbounded) override;
2510e5c31af7Sopenharmony_ci	void													setBuildFlags										(const VkBuildAccelerationStructureFlagsKHR		buildFlags) override;
2511e5c31af7Sopenharmony_ci	void													setBuildWithoutPrimitives							(bool											buildWithoutPrimitives) override;
2512e5c31af7Sopenharmony_ci	void													setInactiveInstances								(bool											inactiveInstances) override;
2513e5c31af7Sopenharmony_ci	void													setDeferredOperation								(const bool										deferredOperation,
2514e5c31af7Sopenharmony_ci																												 const deUint32									workerThreadCount) override;
2515e5c31af7Sopenharmony_ci	void													setUseArrayOfPointers								(const bool										useArrayOfPointers) override;
2516e5c31af7Sopenharmony_ci	void													setIndirectBuildParameters							(const VkBuffer									indirectBuffer,
2517e5c31af7Sopenharmony_ci																												 const VkDeviceSize								indirectBufferOffset,
2518e5c31af7Sopenharmony_ci																												 const deUint32									indirectBufferStride) override;
2519e5c31af7Sopenharmony_ci	void													setUsePPGeometries									(const bool										usePPGeometries) override;
2520e5c31af7Sopenharmony_ci	void													setTryCachedMemory									(const bool										tryCachedMemory) override;
2521e5c31af7Sopenharmony_ci	VkBuildAccelerationStructureFlagsKHR					getBuildFlags										() const override;
2522e5c31af7Sopenharmony_ci
2523e5c31af7Sopenharmony_ci	void													getCreationSizes									(const DeviceInterface&							vk,
2524e5c31af7Sopenharmony_ci																												 const VkDevice									device,
2525e5c31af7Sopenharmony_ci																												 const VkDeviceSize								structureSize,
2526e5c31af7Sopenharmony_ci																												 CreationSizes&									sizes) override;
2527e5c31af7Sopenharmony_ci	void													create												(const DeviceInterface&							vk,
2528e5c31af7Sopenharmony_ci																												 const VkDevice									device,
2529e5c31af7Sopenharmony_ci																												 Allocator&										allocator,
2530e5c31af7Sopenharmony_ci																												 VkDeviceSize									structureSize,
2531e5c31af7Sopenharmony_ci																												 VkDeviceAddress								deviceAddress			= 0u,
2532e5c31af7Sopenharmony_ci																												 const void*									pNext					= DE_NULL,
2533e5c31af7Sopenharmony_ci																												 const MemoryRequirement&						addMemoryRequirement	= MemoryRequirement::Any,
2534e5c31af7Sopenharmony_ci																												 const VkBuffer									creationBuffer			= VK_NULL_HANDLE,
2535e5c31af7Sopenharmony_ci																												 const VkDeviceSize								creationBufferSize		= 0u) override;
2536e5c31af7Sopenharmony_ci	void													build												(const DeviceInterface&							vk,
2537e5c31af7Sopenharmony_ci																												 const VkDevice									device,
2538e5c31af7Sopenharmony_ci																												 const VkCommandBuffer							cmdBuffer,
2539e5c31af7Sopenharmony_ci																												 TopLevelAccelerationStructure*					srcAccelerationStructure = DE_NULL) override;
2540e5c31af7Sopenharmony_ci	void													copyFrom											(const DeviceInterface&							vk,
2541e5c31af7Sopenharmony_ci																												 const VkDevice									device,
2542e5c31af7Sopenharmony_ci																												 const VkCommandBuffer							cmdBuffer,
2543e5c31af7Sopenharmony_ci																												 TopLevelAccelerationStructure*					accelerationStructure,
2544e5c31af7Sopenharmony_ci																												 bool											compactCopy) override;
2545e5c31af7Sopenharmony_ci	void													serialize											(const DeviceInterface&							vk,
2546e5c31af7Sopenharmony_ci																												 const VkDevice									device,
2547e5c31af7Sopenharmony_ci																												 const VkCommandBuffer							cmdBuffer,
2548e5c31af7Sopenharmony_ci																												 SerialStorage*									storage) override;
2549e5c31af7Sopenharmony_ci	void													deserialize											(const DeviceInterface&							vk,
2550e5c31af7Sopenharmony_ci																												 const VkDevice									device,
2551e5c31af7Sopenharmony_ci																												 const VkCommandBuffer							cmdBuffer,
2552e5c31af7Sopenharmony_ci																												 SerialStorage*									storage) override;
2553e5c31af7Sopenharmony_ci
2554e5c31af7Sopenharmony_ci	std::vector<VkDeviceSize>								getSerializingSizes									(const DeviceInterface&							vk,
2555e5c31af7Sopenharmony_ci																												 const VkDevice									device,
2556e5c31af7Sopenharmony_ci																												 const VkQueue									queue,
2557e5c31af7Sopenharmony_ci																												 const deUint32									queueFamilyIndex) override;
2558e5c31af7Sopenharmony_ci
2559e5c31af7Sopenharmony_ci	std::vector<deUint64>									getSerializingAddresses								(const DeviceInterface&							vk,
2560e5c31af7Sopenharmony_ci																												 const VkDevice									device) const override;
2561e5c31af7Sopenharmony_ci
2562e5c31af7Sopenharmony_ci
2563e5c31af7Sopenharmony_ci	const VkAccelerationStructureKHR*						getPtr												(void) const override;
2564e5c31af7Sopenharmony_ci
2565e5c31af7Sopenharmony_ci	void													updateInstanceMatrix								(const DeviceInterface&							vk,
2566e5c31af7Sopenharmony_ci																												 const VkDevice									device,
2567e5c31af7Sopenharmony_ci																												 size_t											instanceIndex,
2568e5c31af7Sopenharmony_ci																												 const VkTransformMatrixKHR&					matrix) override;
2569e5c31af7Sopenharmony_ci
2570e5c31af7Sopenharmony_ciprotected:
2571e5c31af7Sopenharmony_ci	VkAccelerationStructureBuildTypeKHR						m_buildType;
2572e5c31af7Sopenharmony_ci	VkAccelerationStructureCreateFlagsKHR					m_createFlags;
2573e5c31af7Sopenharmony_ci	bool													m_createGeneric;
2574e5c31af7Sopenharmony_ci	bool													m_creationBufferUnbounded;
2575e5c31af7Sopenharmony_ci	VkBuildAccelerationStructureFlagsKHR					m_buildFlags;
2576e5c31af7Sopenharmony_ci	bool													m_buildWithoutPrimitives;
2577e5c31af7Sopenharmony_ci	bool													m_inactiveInstances;
2578e5c31af7Sopenharmony_ci	bool													m_deferredOperation;
2579e5c31af7Sopenharmony_ci	deUint32												m_workerThreadCount;
2580e5c31af7Sopenharmony_ci	bool													m_useArrayOfPointers;
2581e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>							m_accelerationStructureBuffer;
2582e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>							m_instanceBuffer;
2583e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>							m_instanceAddressBuffer;
2584e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>							m_deviceScratchBuffer;
2585e5c31af7Sopenharmony_ci	std::vector<deUint8>									m_hostScratchBuffer;
2586e5c31af7Sopenharmony_ci	Move<VkAccelerationStructureKHR>						m_accelerationStructureKHR;
2587e5c31af7Sopenharmony_ci	VkBuffer												m_indirectBuffer;
2588e5c31af7Sopenharmony_ci	VkDeviceSize											m_indirectBufferOffset;
2589e5c31af7Sopenharmony_ci	deUint32												m_indirectBufferStride;
2590e5c31af7Sopenharmony_ci	bool													m_usePPGeometries;
2591e5c31af7Sopenharmony_ci	bool													m_tryCachedMemory;
2592e5c31af7Sopenharmony_ci
2593e5c31af7Sopenharmony_ci
2594e5c31af7Sopenharmony_ci	void													prepareInstances									(const DeviceInterface&							vk,
2595e5c31af7Sopenharmony_ci																												 const VkDevice									device,
2596e5c31af7Sopenharmony_ci																												 VkAccelerationStructureGeometryKHR&			accelerationStructureGeometryKHR,
2597e5c31af7Sopenharmony_ci																												 std::vector<deUint32>&							maxPrimitiveCounts);
2598e5c31af7Sopenharmony_ci
2599e5c31af7Sopenharmony_ci	void													serializeBottoms									(const DeviceInterface&							vk,
2600e5c31af7Sopenharmony_ci																												 const VkDevice									device,
2601e5c31af7Sopenharmony_ci																												 const VkCommandBuffer							cmdBuffer,
2602e5c31af7Sopenharmony_ci																												 SerialStorage*									storage,
2603e5c31af7Sopenharmony_ci																												 VkDeferredOperationKHR							deferredOperation);
2604e5c31af7Sopenharmony_ci
2605e5c31af7Sopenharmony_ci	void													createAndDeserializeBottoms							(const DeviceInterface&							vk,
2606e5c31af7Sopenharmony_ci																												 const VkDevice									device,
2607e5c31af7Sopenharmony_ci																												 const VkCommandBuffer							cmdBuffer,
2608e5c31af7Sopenharmony_ci																												 Allocator&										allocator,
2609e5c31af7Sopenharmony_ci																												 SerialStorage*									storage) override;
2610e5c31af7Sopenharmony_ci};
2611e5c31af7Sopenharmony_ci
2612e5c31af7Sopenharmony_cideUint32 TopLevelAccelerationStructureKHR::getRequiredAllocationCount (void)
2613e5c31af7Sopenharmony_ci{
2614e5c31af7Sopenharmony_ci	/*
2615e5c31af7Sopenharmony_ci		de::MovePtr<BufferWithMemory>							m_instanceBuffer;
2616e5c31af7Sopenharmony_ci		de::MovePtr<Allocation>									m_accelerationStructureAlloc;
2617e5c31af7Sopenharmony_ci		de::MovePtr<BufferWithMemory>							m_deviceScratchBuffer;
2618e5c31af7Sopenharmony_ci	*/
2619e5c31af7Sopenharmony_ci	return 3u;
2620e5c31af7Sopenharmony_ci}
2621e5c31af7Sopenharmony_ci
2622e5c31af7Sopenharmony_ciTopLevelAccelerationStructureKHR::TopLevelAccelerationStructureKHR ()
2623e5c31af7Sopenharmony_ci	: TopLevelAccelerationStructure	()
2624e5c31af7Sopenharmony_ci	, m_buildType					(VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2625e5c31af7Sopenharmony_ci	, m_createFlags					(0u)
2626e5c31af7Sopenharmony_ci	, m_createGeneric				(false)
2627e5c31af7Sopenharmony_ci	, m_creationBufferUnbounded		(false)
2628e5c31af7Sopenharmony_ci	, m_buildFlags					(0u)
2629e5c31af7Sopenharmony_ci	, m_buildWithoutPrimitives		(false)
2630e5c31af7Sopenharmony_ci	, m_inactiveInstances			(false)
2631e5c31af7Sopenharmony_ci	, m_deferredOperation			(false)
2632e5c31af7Sopenharmony_ci	, m_workerThreadCount			(0)
2633e5c31af7Sopenharmony_ci	, m_useArrayOfPointers			(false)
2634e5c31af7Sopenharmony_ci	, m_accelerationStructureBuffer	(DE_NULL)
2635e5c31af7Sopenharmony_ci	, m_instanceBuffer				(DE_NULL)
2636e5c31af7Sopenharmony_ci	, m_instanceAddressBuffer		(DE_NULL)
2637e5c31af7Sopenharmony_ci	, m_deviceScratchBuffer			(DE_NULL)
2638e5c31af7Sopenharmony_ci	, m_accelerationStructureKHR	()
2639e5c31af7Sopenharmony_ci	, m_indirectBuffer				(DE_NULL)
2640e5c31af7Sopenharmony_ci	, m_indirectBufferOffset		(0)
2641e5c31af7Sopenharmony_ci	, m_indirectBufferStride		(0)
2642e5c31af7Sopenharmony_ci	, m_usePPGeometries				(false)
2643e5c31af7Sopenharmony_ci	, m_tryCachedMemory				(true)
2644e5c31af7Sopenharmony_ci{
2645e5c31af7Sopenharmony_ci}
2646e5c31af7Sopenharmony_ci
2647e5c31af7Sopenharmony_ciTopLevelAccelerationStructureKHR::~TopLevelAccelerationStructureKHR ()
2648e5c31af7Sopenharmony_ci{
2649e5c31af7Sopenharmony_ci}
2650e5c31af7Sopenharmony_ci
2651e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::setBuildType (const VkAccelerationStructureBuildTypeKHR	buildType)
2652e5c31af7Sopenharmony_ci{
2653e5c31af7Sopenharmony_ci	m_buildType = buildType;
2654e5c31af7Sopenharmony_ci}
2655e5c31af7Sopenharmony_ci
2656e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::setCreateFlags (const VkAccelerationStructureCreateFlagsKHR	createFlags)
2657e5c31af7Sopenharmony_ci{
2658e5c31af7Sopenharmony_ci	m_createFlags = createFlags;
2659e5c31af7Sopenharmony_ci}
2660e5c31af7Sopenharmony_ci
2661e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::setCreateGeneric (bool createGeneric)
2662e5c31af7Sopenharmony_ci{
2663e5c31af7Sopenharmony_ci	m_createGeneric = createGeneric;
2664e5c31af7Sopenharmony_ci}
2665e5c31af7Sopenharmony_ci
2666e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::setCreationBufferUnbounded (bool creationBufferUnbounded)
2667e5c31af7Sopenharmony_ci{
2668e5c31af7Sopenharmony_ci	m_creationBufferUnbounded = creationBufferUnbounded;
2669e5c31af7Sopenharmony_ci}
2670e5c31af7Sopenharmony_ci
2671e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::setInactiveInstances (bool inactiveInstances)
2672e5c31af7Sopenharmony_ci{
2673e5c31af7Sopenharmony_ci	m_inactiveInstances = inactiveInstances;
2674e5c31af7Sopenharmony_ci}
2675e5c31af7Sopenharmony_ci
2676e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::setBuildFlags (const VkBuildAccelerationStructureFlagsKHR	buildFlags)
2677e5c31af7Sopenharmony_ci{
2678e5c31af7Sopenharmony_ci	m_buildFlags = buildFlags;
2679e5c31af7Sopenharmony_ci}
2680e5c31af7Sopenharmony_ci
2681e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::setBuildWithoutPrimitives (bool buildWithoutPrimitives)
2682e5c31af7Sopenharmony_ci{
2683e5c31af7Sopenharmony_ci	m_buildWithoutPrimitives = buildWithoutPrimitives;
2684e5c31af7Sopenharmony_ci}
2685e5c31af7Sopenharmony_ci
2686e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::setDeferredOperation (const bool		deferredOperation,
2687e5c31af7Sopenharmony_ci															 const deUint32	workerThreadCount)
2688e5c31af7Sopenharmony_ci{
2689e5c31af7Sopenharmony_ci	m_deferredOperation = deferredOperation;
2690e5c31af7Sopenharmony_ci	m_workerThreadCount = workerThreadCount;
2691e5c31af7Sopenharmony_ci}
2692e5c31af7Sopenharmony_ci
2693e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::setUseArrayOfPointers (const bool	useArrayOfPointers)
2694e5c31af7Sopenharmony_ci{
2695e5c31af7Sopenharmony_ci	m_useArrayOfPointers = useArrayOfPointers;
2696e5c31af7Sopenharmony_ci}
2697e5c31af7Sopenharmony_ci
2698e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::setUsePPGeometries (const bool usePPGeometries)
2699e5c31af7Sopenharmony_ci{
2700e5c31af7Sopenharmony_ci	m_usePPGeometries = usePPGeometries;
2701e5c31af7Sopenharmony_ci}
2702e5c31af7Sopenharmony_ci
2703e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::setTryCachedMemory (const bool tryCachedMemory)
2704e5c31af7Sopenharmony_ci{
2705e5c31af7Sopenharmony_ci	m_tryCachedMemory = tryCachedMemory;
2706e5c31af7Sopenharmony_ci}
2707e5c31af7Sopenharmony_ci
2708e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::setIndirectBuildParameters (const VkBuffer		indirectBuffer,
2709e5c31af7Sopenharmony_ci																   const VkDeviceSize	indirectBufferOffset,
2710e5c31af7Sopenharmony_ci																   const deUint32		indirectBufferStride)
2711e5c31af7Sopenharmony_ci{
2712e5c31af7Sopenharmony_ci	m_indirectBuffer		= indirectBuffer;
2713e5c31af7Sopenharmony_ci	m_indirectBufferOffset	= indirectBufferOffset;
2714e5c31af7Sopenharmony_ci	m_indirectBufferStride	= indirectBufferStride;
2715e5c31af7Sopenharmony_ci}
2716e5c31af7Sopenharmony_ci
2717e5c31af7Sopenharmony_ciVkBuildAccelerationStructureFlagsKHR TopLevelAccelerationStructureKHR::getBuildFlags () const
2718e5c31af7Sopenharmony_ci{
2719e5c31af7Sopenharmony_ci	return m_buildFlags;
2720e5c31af7Sopenharmony_ci}
2721e5c31af7Sopenharmony_ci
2722e5c31af7Sopenharmony_ciVkDeviceSize TopLevelAccelerationStructure::CreationSizes::sum () const
2723e5c31af7Sopenharmony_ci{
2724e5c31af7Sopenharmony_ci	return structure + updateScratch + buildScratch + instancePointers + instancesBuffer;
2725e5c31af7Sopenharmony_ci}
2726e5c31af7Sopenharmony_ci
2727e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::getCreationSizes (const DeviceInterface&	vk,
2728e5c31af7Sopenharmony_ci														 const VkDevice			device,
2729e5c31af7Sopenharmony_ci														 const VkDeviceSize		structureSize,
2730e5c31af7Sopenharmony_ci														 CreationSizes&			sizes)
2731e5c31af7Sopenharmony_ci{
2732e5c31af7Sopenharmony_ci	// AS may be built from geometries using vkCmdBuildAccelerationStructureKHR / vkBuildAccelerationStructureKHR
2733e5c31af7Sopenharmony_ci	// or may be copied/compacted/deserialized from other AS ( in this case AS does not need geometries, but it needs to know its size before creation ).
2734e5c31af7Sopenharmony_ci	DE_ASSERT(!m_bottomLevelInstances.empty() != !(structureSize == 0)); // logical xor
2735e5c31af7Sopenharmony_ci
2736e5c31af7Sopenharmony_ci	if (structureSize == 0)
2737e5c31af7Sopenharmony_ci	{
2738e5c31af7Sopenharmony_ci		VkAccelerationStructureGeometryKHR		accelerationStructureGeometryKHR;
2739e5c31af7Sopenharmony_ci		const auto								accelerationStructureGeometryKHRPtr = &accelerationStructureGeometryKHR;
2740e5c31af7Sopenharmony_ci		std::vector<deUint32>					maxPrimitiveCounts;
2741e5c31af7Sopenharmony_ci		prepareInstances(vk, device, accelerationStructureGeometryKHR, maxPrimitiveCounts);
2742e5c31af7Sopenharmony_ci
2743e5c31af7Sopenharmony_ci		VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfoKHR		=
2744e5c31af7Sopenharmony_ci		{
2745e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,						//  VkStructureType										sType;
2746e5c31af7Sopenharmony_ci			DE_NULL,																				//  const void*											pNext;
2747e5c31af7Sopenharmony_ci			VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR,											//  VkAccelerationStructureTypeKHR						type;
2748e5c31af7Sopenharmony_ci			m_buildFlags,																			//  VkBuildAccelerationStructureFlagsKHR				flags;
2749e5c31af7Sopenharmony_ci			VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR,											//  VkBuildAccelerationStructureModeKHR					mode;
2750e5c31af7Sopenharmony_ci			DE_NULL,																				//  VkAccelerationStructureKHR							srcAccelerationStructure;
2751e5c31af7Sopenharmony_ci			DE_NULL,																				//  VkAccelerationStructureKHR							dstAccelerationStructure;
2752e5c31af7Sopenharmony_ci			1u,																						//  deUint32											geometryCount;
2753e5c31af7Sopenharmony_ci			(m_usePPGeometries ? nullptr : &accelerationStructureGeometryKHR),						//  const VkAccelerationStructureGeometryKHR*			pGeometries;
2754e5c31af7Sopenharmony_ci			(m_usePPGeometries ? &accelerationStructureGeometryKHRPtr : nullptr),					//  const VkAccelerationStructureGeometryKHR* const*	ppGeometries;
2755e5c31af7Sopenharmony_ci			makeDeviceOrHostAddressKHR(DE_NULL)														//  VkDeviceOrHostAddressKHR							scratchData;
2756e5c31af7Sopenharmony_ci		};
2757e5c31af7Sopenharmony_ci
2758e5c31af7Sopenharmony_ci		VkAccelerationStructureBuildSizesInfoKHR	sizeInfo =
2759e5c31af7Sopenharmony_ci		{
2760e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR,	//  VkStructureType	sType;
2761e5c31af7Sopenharmony_ci			DE_NULL,														//  const void*		pNext;
2762e5c31af7Sopenharmony_ci			0,																//  VkDeviceSize	accelerationStructureSize;
2763e5c31af7Sopenharmony_ci			0,																//  VkDeviceSize	updateScratchSize;
2764e5c31af7Sopenharmony_ci			0																//  VkDeviceSize	buildScratchSize;
2765e5c31af7Sopenharmony_ci		};
2766e5c31af7Sopenharmony_ci
2767e5c31af7Sopenharmony_ci		vk.getAccelerationStructureBuildSizesKHR(device, m_buildType, &accelerationStructureBuildGeometryInfoKHR, maxPrimitiveCounts.data(), &sizeInfo);
2768e5c31af7Sopenharmony_ci
2769e5c31af7Sopenharmony_ci		sizes.structure		= sizeInfo.accelerationStructureSize;
2770e5c31af7Sopenharmony_ci		sizes.updateScratch	= sizeInfo.updateScratchSize;
2771e5c31af7Sopenharmony_ci		sizes.buildScratch	= sizeInfo.buildScratchSize;
2772e5c31af7Sopenharmony_ci	}
2773e5c31af7Sopenharmony_ci	else
2774e5c31af7Sopenharmony_ci	{
2775e5c31af7Sopenharmony_ci		sizes.structure		= structureSize;
2776e5c31af7Sopenharmony_ci		sizes.updateScratch	= 0u;
2777e5c31af7Sopenharmony_ci		sizes.buildScratch	= 0u;
2778e5c31af7Sopenharmony_ci	}
2779e5c31af7Sopenharmony_ci
2780e5c31af7Sopenharmony_ci	sizes.instancePointers	= 0u;
2781e5c31af7Sopenharmony_ci	if (m_useArrayOfPointers)
2782e5c31af7Sopenharmony_ci	{
2783e5c31af7Sopenharmony_ci		const size_t	pointerSize = (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) ? sizeof(VkDeviceOrHostAddressConstKHR::deviceAddress) : sizeof(VkDeviceOrHostAddressConstKHR::hostAddress);
2784e5c31af7Sopenharmony_ci		sizes.instancePointers		= static_cast<VkDeviceSize>(m_bottomLevelInstances.size() * pointerSize);
2785e5c31af7Sopenharmony_ci	}
2786e5c31af7Sopenharmony_ci
2787e5c31af7Sopenharmony_ci	sizes.instancesBuffer = m_bottomLevelInstances.empty() ? 0u : m_bottomLevelInstances.size() * sizeof(VkAccelerationStructureInstanceKHR);
2788e5c31af7Sopenharmony_ci}
2789e5c31af7Sopenharmony_ci
2790e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::create (const DeviceInterface&				vk,
2791e5c31af7Sopenharmony_ci											   const VkDevice						device,
2792e5c31af7Sopenharmony_ci											   Allocator&							allocator,
2793e5c31af7Sopenharmony_ci											   VkDeviceSize							structureSize,
2794e5c31af7Sopenharmony_ci											   VkDeviceAddress						deviceAddress,
2795e5c31af7Sopenharmony_ci											   const void*							pNext,
2796e5c31af7Sopenharmony_ci											   const MemoryRequirement&				addMemoryRequirement,
2797e5c31af7Sopenharmony_ci											   const VkBuffer						creationBuffer,
2798e5c31af7Sopenharmony_ci											   const VkDeviceSize					creationBufferSize)
2799e5c31af7Sopenharmony_ci{
2800e5c31af7Sopenharmony_ci	// AS may be built from geometries using vkCmdBuildAccelerationStructureKHR / vkBuildAccelerationStructureKHR
2801e5c31af7Sopenharmony_ci	// or may be copied/compacted/deserialized from other AS ( in this case AS does not need geometries, but it needs to know its size before creation ).
2802e5c31af7Sopenharmony_ci	DE_ASSERT(!m_bottomLevelInstances.empty() != !(structureSize == 0)); // logical xor
2803e5c31af7Sopenharmony_ci
2804e5c31af7Sopenharmony_ci	if (structureSize == 0)
2805e5c31af7Sopenharmony_ci	{
2806e5c31af7Sopenharmony_ci		VkAccelerationStructureGeometryKHR		accelerationStructureGeometryKHR;
2807e5c31af7Sopenharmony_ci		const auto								accelerationStructureGeometryKHRPtr = &accelerationStructureGeometryKHR;
2808e5c31af7Sopenharmony_ci		std::vector<deUint32>					maxPrimitiveCounts;
2809e5c31af7Sopenharmony_ci		prepareInstances(vk, device, accelerationStructureGeometryKHR, maxPrimitiveCounts);
2810e5c31af7Sopenharmony_ci
2811e5c31af7Sopenharmony_ci		VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfoKHR		=
2812e5c31af7Sopenharmony_ci		{
2813e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,						//  VkStructureType										sType;
2814e5c31af7Sopenharmony_ci			DE_NULL,																				//  const void*											pNext;
2815e5c31af7Sopenharmony_ci			VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR,											//  VkAccelerationStructureTypeKHR						type;
2816e5c31af7Sopenharmony_ci			m_buildFlags,																			//  VkBuildAccelerationStructureFlagsKHR				flags;
2817e5c31af7Sopenharmony_ci			VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR,											//  VkBuildAccelerationStructureModeKHR					mode;
2818e5c31af7Sopenharmony_ci			DE_NULL,																				//  VkAccelerationStructureKHR							srcAccelerationStructure;
2819e5c31af7Sopenharmony_ci			DE_NULL,																				//  VkAccelerationStructureKHR							dstAccelerationStructure;
2820e5c31af7Sopenharmony_ci			1u,																						//  deUint32											geometryCount;
2821e5c31af7Sopenharmony_ci			(m_usePPGeometries ? nullptr : &accelerationStructureGeometryKHR),						//  const VkAccelerationStructureGeometryKHR*			pGeometries;
2822e5c31af7Sopenharmony_ci			(m_usePPGeometries ? &accelerationStructureGeometryKHRPtr : nullptr),					//  const VkAccelerationStructureGeometryKHR* const*	ppGeometries;
2823e5c31af7Sopenharmony_ci			makeDeviceOrHostAddressKHR(DE_NULL)														//  VkDeviceOrHostAddressKHR							scratchData;
2824e5c31af7Sopenharmony_ci		};
2825e5c31af7Sopenharmony_ci
2826e5c31af7Sopenharmony_ci		VkAccelerationStructureBuildSizesInfoKHR	sizeInfo =
2827e5c31af7Sopenharmony_ci		{
2828e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR,	//  VkStructureType	sType;
2829e5c31af7Sopenharmony_ci			DE_NULL,														//  const void*		pNext;
2830e5c31af7Sopenharmony_ci			0,																//  VkDeviceSize	accelerationStructureSize;
2831e5c31af7Sopenharmony_ci			0,																//  VkDeviceSize	updateScratchSize;
2832e5c31af7Sopenharmony_ci			0																//  VkDeviceSize	buildScratchSize;
2833e5c31af7Sopenharmony_ci		};
2834e5c31af7Sopenharmony_ci
2835e5c31af7Sopenharmony_ci		vk.getAccelerationStructureBuildSizesKHR(device, m_buildType, &accelerationStructureBuildGeometryInfoKHR, maxPrimitiveCounts.data(), &sizeInfo);
2836e5c31af7Sopenharmony_ci
2837e5c31af7Sopenharmony_ci		m_structureSize		= sizeInfo.accelerationStructureSize;
2838e5c31af7Sopenharmony_ci		m_updateScratchSize	= sizeInfo.updateScratchSize;
2839e5c31af7Sopenharmony_ci		m_buildScratchSize	= sizeInfo.buildScratchSize;
2840e5c31af7Sopenharmony_ci	}
2841e5c31af7Sopenharmony_ci	else
2842e5c31af7Sopenharmony_ci	{
2843e5c31af7Sopenharmony_ci		m_structureSize		= structureSize;
2844e5c31af7Sopenharmony_ci		m_updateScratchSize	= 0u;
2845e5c31af7Sopenharmony_ci		m_buildScratchSize	= 0u;
2846e5c31af7Sopenharmony_ci	}
2847e5c31af7Sopenharmony_ci
2848e5c31af7Sopenharmony_ci	const bool externalCreationBuffer = (creationBuffer != VK_NULL_HANDLE);
2849e5c31af7Sopenharmony_ci
2850e5c31af7Sopenharmony_ci	if (externalCreationBuffer)
2851e5c31af7Sopenharmony_ci	{
2852e5c31af7Sopenharmony_ci		DE_UNREF(creationBufferSize); // For release builds.
2853e5c31af7Sopenharmony_ci		DE_ASSERT(creationBufferSize >= m_structureSize);
2854e5c31af7Sopenharmony_ci	}
2855e5c31af7Sopenharmony_ci
2856e5c31af7Sopenharmony_ci	if (!externalCreationBuffer)
2857e5c31af7Sopenharmony_ci	{
2858e5c31af7Sopenharmony_ci		const VkBufferCreateInfo	bufferCreateInfo	= makeBufferCreateInfo(m_structureSize, VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
2859e5c31af7Sopenharmony_ci		const MemoryRequirement		memoryRequirement	= addMemoryRequirement | MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress;
2860e5c31af7Sopenharmony_ci		const bool					bindMemOnCreation	= (!m_creationBufferUnbounded);
2861e5c31af7Sopenharmony_ci
2862e5c31af7Sopenharmony_ci		try
2863e5c31af7Sopenharmony_ci		{
2864e5c31af7Sopenharmony_ci			m_accelerationStructureBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, (MemoryRequirement::Cached | memoryRequirement), bindMemOnCreation));
2865e5c31af7Sopenharmony_ci		}
2866e5c31af7Sopenharmony_ci		catch (const tcu::NotSupportedError&)
2867e5c31af7Sopenharmony_ci		{
2868e5c31af7Sopenharmony_ci			// retry without Cached flag
2869e5c31af7Sopenharmony_ci			m_accelerationStructureBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, memoryRequirement, bindMemOnCreation));
2870e5c31af7Sopenharmony_ci		}
2871e5c31af7Sopenharmony_ci	}
2872e5c31af7Sopenharmony_ci
2873e5c31af7Sopenharmony_ci	const auto createInfoBuffer = (externalCreationBuffer ? creationBuffer : m_accelerationStructureBuffer->get());
2874e5c31af7Sopenharmony_ci	{
2875e5c31af7Sopenharmony_ci		const VkAccelerationStructureTypeKHR		structureType						= (m_createGeneric
2876e5c31af7Sopenharmony_ci																						   ? VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR
2877e5c31af7Sopenharmony_ci																						   : VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR);
2878e5c31af7Sopenharmony_ci		const VkAccelerationStructureCreateInfoKHR	accelerationStructureCreateInfoKHR	=
2879e5c31af7Sopenharmony_ci		{
2880e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR,	//  VkStructureType											sType;
2881e5c31af7Sopenharmony_ci			pNext,														//  const void*												pNext;
2882e5c31af7Sopenharmony_ci			m_createFlags,												//  VkAccelerationStructureCreateFlagsKHR					createFlags;
2883e5c31af7Sopenharmony_ci			createInfoBuffer,											//  VkBuffer												buffer;
2884e5c31af7Sopenharmony_ci			0u,															//  VkDeviceSize											offset;
2885e5c31af7Sopenharmony_ci			m_structureSize,											//  VkDeviceSize											size;
2886e5c31af7Sopenharmony_ci			structureType,												//  VkAccelerationStructureTypeKHR							type;
2887e5c31af7Sopenharmony_ci			deviceAddress												//  VkDeviceAddress											deviceAddress;
2888e5c31af7Sopenharmony_ci		};
2889e5c31af7Sopenharmony_ci
2890e5c31af7Sopenharmony_ci		m_accelerationStructureKHR	= createAccelerationStructureKHR(vk, device, &accelerationStructureCreateInfoKHR, DE_NULL);
2891e5c31af7Sopenharmony_ci
2892e5c31af7Sopenharmony_ci		// Make sure buffer memory is always bound after creation.
2893e5c31af7Sopenharmony_ci		if (!externalCreationBuffer)
2894e5c31af7Sopenharmony_ci			m_accelerationStructureBuffer->bindMemory();
2895e5c31af7Sopenharmony_ci	}
2896e5c31af7Sopenharmony_ci
2897e5c31af7Sopenharmony_ci	if (m_buildScratchSize > 0u)
2898e5c31af7Sopenharmony_ci	{
2899e5c31af7Sopenharmony_ci		if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2900e5c31af7Sopenharmony_ci		{
2901e5c31af7Sopenharmony_ci			const VkBufferCreateInfo		bufferCreateInfo	= makeBufferCreateInfo(m_buildScratchSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
2902e5c31af7Sopenharmony_ci			m_deviceScratchBuffer								= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
2903e5c31af7Sopenharmony_ci		}
2904e5c31af7Sopenharmony_ci		else
2905e5c31af7Sopenharmony_ci		{
2906e5c31af7Sopenharmony_ci			m_hostScratchBuffer.resize(static_cast<size_t>(m_buildScratchSize));
2907e5c31af7Sopenharmony_ci		}
2908e5c31af7Sopenharmony_ci	}
2909e5c31af7Sopenharmony_ci
2910e5c31af7Sopenharmony_ci	if (m_useArrayOfPointers)
2911e5c31af7Sopenharmony_ci	{
2912e5c31af7Sopenharmony_ci		const size_t				pointerSize = (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) ? sizeof(VkDeviceOrHostAddressConstKHR::deviceAddress) : sizeof(VkDeviceOrHostAddressConstKHR::hostAddress);
2913e5c31af7Sopenharmony_ci		const VkBufferCreateInfo	bufferCreateInfo = makeBufferCreateInfo(static_cast<VkDeviceSize>(m_bottomLevelInstances.size() * pointerSize), VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
2914e5c31af7Sopenharmony_ci		m_instanceAddressBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress));
2915e5c31af7Sopenharmony_ci	}
2916e5c31af7Sopenharmony_ci
2917e5c31af7Sopenharmony_ci	if(!m_bottomLevelInstances.empty())
2918e5c31af7Sopenharmony_ci		m_instanceBuffer = de::MovePtr<BufferWithMemory>(createInstanceBuffer(vk, device, allocator, m_bottomLevelInstances, m_instanceData, m_tryCachedMemory));
2919e5c31af7Sopenharmony_ci}
2920e5c31af7Sopenharmony_ci
2921e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::updateInstanceMatrix (const DeviceInterface& vk, const VkDevice device, size_t instanceIndex, const VkTransformMatrixKHR& matrix)
2922e5c31af7Sopenharmony_ci{
2923e5c31af7Sopenharmony_ci	DE_ASSERT(instanceIndex < m_bottomLevelInstances.size());
2924e5c31af7Sopenharmony_ci	DE_ASSERT(instanceIndex < m_instanceData.size());
2925e5c31af7Sopenharmony_ci
2926e5c31af7Sopenharmony_ci	const auto&		blas			= *m_bottomLevelInstances[instanceIndex];
2927e5c31af7Sopenharmony_ci	auto&			instanceData	= m_instanceData[instanceIndex];
2928e5c31af7Sopenharmony_ci	auto&			instancesAlloc	= m_instanceBuffer->getAllocation();
2929e5c31af7Sopenharmony_ci	auto			bufferStart		= reinterpret_cast<deUint8*>(instancesAlloc.getHostPtr());
2930e5c31af7Sopenharmony_ci	VkDeviceSize	bufferOffset	= sizeof(VkAccelerationStructureInstanceKHR) * instanceIndex;
2931e5c31af7Sopenharmony_ci
2932e5c31af7Sopenharmony_ci	instanceData.matrix = matrix;
2933e5c31af7Sopenharmony_ci	updateSingleInstance(vk, device, blas, instanceData, bufferStart + bufferOffset, m_buildType, m_inactiveInstances);
2934e5c31af7Sopenharmony_ci	flushMappedMemoryRange(vk, device, instancesAlloc.getMemory(), instancesAlloc.getOffset(), VK_WHOLE_SIZE);
2935e5c31af7Sopenharmony_ci}
2936e5c31af7Sopenharmony_ci
2937e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::build (const DeviceInterface&			vk,
2938e5c31af7Sopenharmony_ci											  const VkDevice					device,
2939e5c31af7Sopenharmony_ci											  const VkCommandBuffer				cmdBuffer,
2940e5c31af7Sopenharmony_ci											  TopLevelAccelerationStructure*	srcAccelerationStructure)
2941e5c31af7Sopenharmony_ci{
2942e5c31af7Sopenharmony_ci	DE_ASSERT(!m_bottomLevelInstances.empty());
2943e5c31af7Sopenharmony_ci	DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
2944e5c31af7Sopenharmony_ci	DE_ASSERT(m_buildScratchSize != 0);
2945e5c31af7Sopenharmony_ci
2946e5c31af7Sopenharmony_ci	updateInstanceBuffer(vk, device, m_bottomLevelInstances, m_instanceData, m_instanceBuffer.get(), m_buildType, m_inactiveInstances);
2947e5c31af7Sopenharmony_ci
2948e5c31af7Sopenharmony_ci	VkAccelerationStructureGeometryKHR		accelerationStructureGeometryKHR;
2949e5c31af7Sopenharmony_ci	const auto								accelerationStructureGeometryKHRPtr = &accelerationStructureGeometryKHR;
2950e5c31af7Sopenharmony_ci	std::vector<deUint32>					maxPrimitiveCounts;
2951e5c31af7Sopenharmony_ci	prepareInstances(vk, device, accelerationStructureGeometryKHR, maxPrimitiveCounts);
2952e5c31af7Sopenharmony_ci
2953e5c31af7Sopenharmony_ci	VkDeviceOrHostAddressKHR				scratchData										= (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2954e5c31af7Sopenharmony_ci																							? makeDeviceOrHostAddressKHR(vk, device, m_deviceScratchBuffer->get(), 0)
2955e5c31af7Sopenharmony_ci																							: makeDeviceOrHostAddressKHR(m_hostScratchBuffer.data());
2956e5c31af7Sopenharmony_ci
2957e5c31af7Sopenharmony_ci	VkAccelerationStructureKHR				srcStructure									= (srcAccelerationStructure != DE_NULL) ? *(srcAccelerationStructure->getPtr()) : DE_NULL;
2958e5c31af7Sopenharmony_ci	VkBuildAccelerationStructureModeKHR		mode											= (srcAccelerationStructure != DE_NULL) ? VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR : VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
2959e5c31af7Sopenharmony_ci
2960e5c31af7Sopenharmony_ci	VkAccelerationStructureBuildGeometryInfoKHR accelerationStructureBuildGeometryInfoKHR		=
2961e5c31af7Sopenharmony_ci	{
2962e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,						//  VkStructureType										sType;
2963e5c31af7Sopenharmony_ci		DE_NULL,																				//  const void*											pNext;
2964e5c31af7Sopenharmony_ci		VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR,											//  VkAccelerationStructureTypeKHR						type;
2965e5c31af7Sopenharmony_ci		m_buildFlags,																			//  VkBuildAccelerationStructureFlagsKHR				flags;
2966e5c31af7Sopenharmony_ci		mode,																					//  VkBuildAccelerationStructureModeKHR					mode;
2967e5c31af7Sopenharmony_ci		srcStructure,																			//  VkAccelerationStructureKHR							srcAccelerationStructure;
2968e5c31af7Sopenharmony_ci		m_accelerationStructureKHR.get(),														//  VkAccelerationStructureKHR							dstAccelerationStructure;
2969e5c31af7Sopenharmony_ci		1u,																						//  deUint32											geometryCount;
2970e5c31af7Sopenharmony_ci		(m_usePPGeometries ? nullptr : &accelerationStructureGeometryKHR),						//  const VkAccelerationStructureGeometryKHR*			pGeometries;
2971e5c31af7Sopenharmony_ci		(m_usePPGeometries ? &accelerationStructureGeometryKHRPtr : nullptr),					//  const VkAccelerationStructureGeometryKHR* const*	ppGeometries;
2972e5c31af7Sopenharmony_ci		scratchData																				//  VkDeviceOrHostAddressKHR							scratchData;
2973e5c31af7Sopenharmony_ci	};
2974e5c31af7Sopenharmony_ci
2975e5c31af7Sopenharmony_ci	const deUint32 primitiveCount = (m_buildWithoutPrimitives ? 0u : static_cast<deUint32>(m_bottomLevelInstances.size()));
2976e5c31af7Sopenharmony_ci
2977e5c31af7Sopenharmony_ci	VkAccelerationStructureBuildRangeInfoKHR accelerationStructureBuildRangeInfoKHR =
2978e5c31af7Sopenharmony_ci	{
2979e5c31af7Sopenharmony_ci		primitiveCount,	//  deUint32	primitiveCount;
2980e5c31af7Sopenharmony_ci		0,				//  deUint32	primitiveOffset;
2981e5c31af7Sopenharmony_ci		0,				//  deUint32	firstVertex;
2982e5c31af7Sopenharmony_ci		0				//  deUint32	transformOffset;
2983e5c31af7Sopenharmony_ci	};
2984e5c31af7Sopenharmony_ci	VkAccelerationStructureBuildRangeInfoKHR* accelerationStructureBuildRangeInfoKHRPtr	= &accelerationStructureBuildRangeInfoKHR;
2985e5c31af7Sopenharmony_ci
2986e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
2987e5c31af7Sopenharmony_ci	{
2988e5c31af7Sopenharmony_ci		if (m_indirectBuffer == DE_NULL)
2989e5c31af7Sopenharmony_ci			vk.cmdBuildAccelerationStructuresKHR(cmdBuffer, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildRangeInfoKHR**)&accelerationStructureBuildRangeInfoKHRPtr);
2990e5c31af7Sopenharmony_ci		else
2991e5c31af7Sopenharmony_ci		{
2992e5c31af7Sopenharmony_ci			VkDeviceAddress	indirectDeviceAddress = getBufferDeviceAddress(vk, device, m_indirectBuffer, m_indirectBufferOffset);
2993e5c31af7Sopenharmony_ci			deUint32*		pMaxPrimitiveCounts = maxPrimitiveCounts.data();
2994e5c31af7Sopenharmony_ci			vk.cmdBuildAccelerationStructuresIndirectKHR(cmdBuffer, 1u, &accelerationStructureBuildGeometryInfoKHR, &indirectDeviceAddress, &m_indirectBufferStride, &pMaxPrimitiveCounts);
2995e5c31af7Sopenharmony_ci		}
2996e5c31af7Sopenharmony_ci	}
2997e5c31af7Sopenharmony_ci	else if (!m_deferredOperation)
2998e5c31af7Sopenharmony_ci	{
2999e5c31af7Sopenharmony_ci		VK_CHECK(vk.buildAccelerationStructuresKHR(device, DE_NULL, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildRangeInfoKHR**)&accelerationStructureBuildRangeInfoKHRPtr));
3000e5c31af7Sopenharmony_ci	}
3001e5c31af7Sopenharmony_ci	else
3002e5c31af7Sopenharmony_ci	{
3003e5c31af7Sopenharmony_ci		const auto deferredOperationPtr	= createDeferredOperationKHR(vk, device);
3004e5c31af7Sopenharmony_ci		const auto deferredOperation	= deferredOperationPtr.get();
3005e5c31af7Sopenharmony_ci
3006e5c31af7Sopenharmony_ci		VkResult result = vk.buildAccelerationStructuresKHR(device, deferredOperation, 1u, &accelerationStructureBuildGeometryInfoKHR, (const VkAccelerationStructureBuildRangeInfoKHR**)&accelerationStructureBuildRangeInfoKHRPtr);
3007e5c31af7Sopenharmony_ci
3008e5c31af7Sopenharmony_ci		DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
3009e5c31af7Sopenharmony_ci
3010e5c31af7Sopenharmony_ci		finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
3011e5c31af7Sopenharmony_ci
3012e5c31af7Sopenharmony_ci		accelerationStructureBuildGeometryInfoKHR.pNext = DE_NULL;
3013e5c31af7Sopenharmony_ci	}
3014e5c31af7Sopenharmony_ci
3015e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3016e5c31af7Sopenharmony_ci	{
3017e5c31af7Sopenharmony_ci		const VkAccessFlags		accessMasks	= VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
3018e5c31af7Sopenharmony_ci		const VkMemoryBarrier	memBarrier	= makeMemoryBarrier(accessMasks, accessMasks);
3019e5c31af7Sopenharmony_ci
3020e5c31af7Sopenharmony_ci		cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier);
3021e5c31af7Sopenharmony_ci	}
3022e5c31af7Sopenharmony_ci}
3023e5c31af7Sopenharmony_ci
3024e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::copyFrom (const DeviceInterface&				vk,
3025e5c31af7Sopenharmony_ci												 const VkDevice						device,
3026e5c31af7Sopenharmony_ci												 const VkCommandBuffer				cmdBuffer,
3027e5c31af7Sopenharmony_ci												 TopLevelAccelerationStructure*		accelerationStructure,
3028e5c31af7Sopenharmony_ci												 bool								compactCopy)
3029e5c31af7Sopenharmony_ci{
3030e5c31af7Sopenharmony_ci	DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
3031e5c31af7Sopenharmony_ci	DE_ASSERT(accelerationStructure != DE_NULL);
3032e5c31af7Sopenharmony_ci
3033e5c31af7Sopenharmony_ci	VkCopyAccelerationStructureInfoKHR copyAccelerationStructureInfo =
3034e5c31af7Sopenharmony_ci	{
3035e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR,															// VkStructureType						sType;
3036e5c31af7Sopenharmony_ci		DE_NULL,																										// const void*							pNext;
3037e5c31af7Sopenharmony_ci		*(accelerationStructure->getPtr()),																				// VkAccelerationStructureKHR			src;
3038e5c31af7Sopenharmony_ci		*(getPtr()),																									// VkAccelerationStructureKHR			dst;
3039e5c31af7Sopenharmony_ci		compactCopy ? VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR : VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR	// VkCopyAccelerationStructureModeKHR	mode;
3040e5c31af7Sopenharmony_ci	};
3041e5c31af7Sopenharmony_ci
3042e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3043e5c31af7Sopenharmony_ci	{
3044e5c31af7Sopenharmony_ci		vk.cmdCopyAccelerationStructureKHR(cmdBuffer, &copyAccelerationStructureInfo);
3045e5c31af7Sopenharmony_ci	}
3046e5c31af7Sopenharmony_ci	else if (!m_deferredOperation)
3047e5c31af7Sopenharmony_ci	{
3048e5c31af7Sopenharmony_ci		VK_CHECK(vk.copyAccelerationStructureKHR(device, DE_NULL, &copyAccelerationStructureInfo));
3049e5c31af7Sopenharmony_ci	}
3050e5c31af7Sopenharmony_ci	else
3051e5c31af7Sopenharmony_ci	{
3052e5c31af7Sopenharmony_ci		const auto deferredOperationPtr	= createDeferredOperationKHR(vk, device);
3053e5c31af7Sopenharmony_ci		const auto deferredOperation	= deferredOperationPtr.get();
3054e5c31af7Sopenharmony_ci
3055e5c31af7Sopenharmony_ci		VkResult result = vk.copyAccelerationStructureKHR(device, deferredOperation, &copyAccelerationStructureInfo);
3056e5c31af7Sopenharmony_ci
3057e5c31af7Sopenharmony_ci		DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
3058e5c31af7Sopenharmony_ci
3059e5c31af7Sopenharmony_ci		finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
3060e5c31af7Sopenharmony_ci	}
3061e5c31af7Sopenharmony_ci
3062e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3063e5c31af7Sopenharmony_ci	{
3064e5c31af7Sopenharmony_ci		const VkAccessFlags		accessMasks	= VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
3065e5c31af7Sopenharmony_ci		const VkMemoryBarrier	memBarrier	= makeMemoryBarrier(accessMasks, accessMasks);
3066e5c31af7Sopenharmony_ci
3067e5c31af7Sopenharmony_ci		cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier);
3068e5c31af7Sopenharmony_ci	}
3069e5c31af7Sopenharmony_ci
3070e5c31af7Sopenharmony_ci}
3071e5c31af7Sopenharmony_ci
3072e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::serialize (const DeviceInterface&	vk,
3073e5c31af7Sopenharmony_ci												  const VkDevice			device,
3074e5c31af7Sopenharmony_ci												  const VkCommandBuffer		cmdBuffer,
3075e5c31af7Sopenharmony_ci												  SerialStorage*			storage)
3076e5c31af7Sopenharmony_ci{
3077e5c31af7Sopenharmony_ci	DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
3078e5c31af7Sopenharmony_ci	DE_ASSERT(storage != DE_NULL);
3079e5c31af7Sopenharmony_ci
3080e5c31af7Sopenharmony_ci	const VkCopyAccelerationStructureToMemoryInfoKHR	copyAccelerationStructureInfo	=
3081e5c31af7Sopenharmony_ci	{
3082e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR,	// VkStructureType						sType;
3083e5c31af7Sopenharmony_ci		DE_NULL,															// const void*							pNext;
3084e5c31af7Sopenharmony_ci		*(getPtr()),														// VkAccelerationStructureKHR			src;
3085e5c31af7Sopenharmony_ci		storage->getAddress(vk, device, m_buildType),						// VkDeviceOrHostAddressKHR				dst;
3086e5c31af7Sopenharmony_ci		VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR					// VkCopyAccelerationStructureModeKHR	mode;
3087e5c31af7Sopenharmony_ci	};
3088e5c31af7Sopenharmony_ci
3089e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3090e5c31af7Sopenharmony_ci	{
3091e5c31af7Sopenharmony_ci		vk.cmdCopyAccelerationStructureToMemoryKHR(cmdBuffer, &copyAccelerationStructureInfo);
3092e5c31af7Sopenharmony_ci		if (storage->hasDeepFormat()) serializeBottoms(vk, device, cmdBuffer, storage, DE_NULL);
3093e5c31af7Sopenharmony_ci	}
3094e5c31af7Sopenharmony_ci	else if (!m_deferredOperation)
3095e5c31af7Sopenharmony_ci	{
3096e5c31af7Sopenharmony_ci		VK_CHECK(vk.copyAccelerationStructureToMemoryKHR(device, DE_NULL, &copyAccelerationStructureInfo));
3097e5c31af7Sopenharmony_ci		if (storage->hasDeepFormat()) serializeBottoms(vk, device, cmdBuffer, storage, DE_NULL);
3098e5c31af7Sopenharmony_ci	}
3099e5c31af7Sopenharmony_ci	else
3100e5c31af7Sopenharmony_ci	{
3101e5c31af7Sopenharmony_ci		const auto deferredOperationPtr	= createDeferredOperationKHR(vk, device);
3102e5c31af7Sopenharmony_ci		const auto deferredOperation	= deferredOperationPtr.get();
3103e5c31af7Sopenharmony_ci
3104e5c31af7Sopenharmony_ci		const VkResult result = vk.copyAccelerationStructureToMemoryKHR(device, deferredOperation, &copyAccelerationStructureInfo);
3105e5c31af7Sopenharmony_ci
3106e5c31af7Sopenharmony_ci		DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
3107e5c31af7Sopenharmony_ci		if (storage->hasDeepFormat()) serializeBottoms(vk, device, cmdBuffer, storage, deferredOperation);
3108e5c31af7Sopenharmony_ci
3109e5c31af7Sopenharmony_ci		finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
3110e5c31af7Sopenharmony_ci	}
3111e5c31af7Sopenharmony_ci}
3112e5c31af7Sopenharmony_ci
3113e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::deserialize (const DeviceInterface&	vk,
3114e5c31af7Sopenharmony_ci													const VkDevice			device,
3115e5c31af7Sopenharmony_ci													const VkCommandBuffer	cmdBuffer,
3116e5c31af7Sopenharmony_ci													SerialStorage*			storage)
3117e5c31af7Sopenharmony_ci{
3118e5c31af7Sopenharmony_ci	DE_ASSERT(m_accelerationStructureKHR.get() != DE_NULL);
3119e5c31af7Sopenharmony_ci	DE_ASSERT(storage != DE_NULL);
3120e5c31af7Sopenharmony_ci
3121e5c31af7Sopenharmony_ci	const VkCopyMemoryToAccelerationStructureInfoKHR	copyAccelerationStructureInfo	=
3122e5c31af7Sopenharmony_ci	{
3123e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR,	// VkStructureType							sType;
3124e5c31af7Sopenharmony_ci		DE_NULL,															// const void*								pNext;
3125e5c31af7Sopenharmony_ci		storage->getAddressConst(vk, device, m_buildType),					// VkDeviceOrHostAddressConstKHR			src;
3126e5c31af7Sopenharmony_ci		*(getPtr()),														// VkAccelerationStructureKHR				dst;
3127e5c31af7Sopenharmony_ci		VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR					// VkCopyAccelerationStructureModeKHR		mode;
3128e5c31af7Sopenharmony_ci	};
3129e5c31af7Sopenharmony_ci
3130e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3131e5c31af7Sopenharmony_ci	{
3132e5c31af7Sopenharmony_ci		vk.cmdCopyMemoryToAccelerationStructureKHR(cmdBuffer, &copyAccelerationStructureInfo);
3133e5c31af7Sopenharmony_ci	}
3134e5c31af7Sopenharmony_ci	else if (!m_deferredOperation)
3135e5c31af7Sopenharmony_ci	{
3136e5c31af7Sopenharmony_ci		VK_CHECK(vk.copyMemoryToAccelerationStructureKHR(device, DE_NULL, &copyAccelerationStructureInfo));
3137e5c31af7Sopenharmony_ci	}
3138e5c31af7Sopenharmony_ci	else
3139e5c31af7Sopenharmony_ci	{
3140e5c31af7Sopenharmony_ci		const auto deferredOperationPtr	= createDeferredOperationKHR(vk, device);
3141e5c31af7Sopenharmony_ci		const auto deferredOperation	= deferredOperationPtr.get();
3142e5c31af7Sopenharmony_ci
3143e5c31af7Sopenharmony_ci		const VkResult result = vk.copyMemoryToAccelerationStructureKHR(device, deferredOperation, &copyAccelerationStructureInfo);
3144e5c31af7Sopenharmony_ci
3145e5c31af7Sopenharmony_ci		DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
3146e5c31af7Sopenharmony_ci
3147e5c31af7Sopenharmony_ci		finishDeferredOperation(vk, device, deferredOperation, m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
3148e5c31af7Sopenharmony_ci	}
3149e5c31af7Sopenharmony_ci
3150e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3151e5c31af7Sopenharmony_ci	{
3152e5c31af7Sopenharmony_ci		const VkAccessFlags		accessMasks = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
3153e5c31af7Sopenharmony_ci		const VkMemoryBarrier	memBarrier = makeMemoryBarrier(accessMasks, accessMasks);
3154e5c31af7Sopenharmony_ci
3155e5c31af7Sopenharmony_ci		cmdPipelineMemoryBarrier(vk, cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memBarrier);
3156e5c31af7Sopenharmony_ci	}
3157e5c31af7Sopenharmony_ci}
3158e5c31af7Sopenharmony_ci
3159e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::serializeBottoms (const DeviceInterface&	vk,
3160e5c31af7Sopenharmony_ci														 const VkDevice			device,
3161e5c31af7Sopenharmony_ci														 const VkCommandBuffer	cmdBuffer,
3162e5c31af7Sopenharmony_ci														 SerialStorage*			storage,
3163e5c31af7Sopenharmony_ci														 VkDeferredOperationKHR	deferredOperation)
3164e5c31af7Sopenharmony_ci{
3165e5c31af7Sopenharmony_ci	DE_UNREF(deferredOperation);
3166e5c31af7Sopenharmony_ci	DE_ASSERT(storage->hasDeepFormat());
3167e5c31af7Sopenharmony_ci
3168e5c31af7Sopenharmony_ci	const std::vector<deUint64>&	addresses		= storage->getSerialInfo().addresses();
3169e5c31af7Sopenharmony_ci	const std::size_t				cbottoms		= m_bottomLevelInstances.size();
3170e5c31af7Sopenharmony_ci
3171e5c31af7Sopenharmony_ci	deUint32						storageIndex	= 0;
3172e5c31af7Sopenharmony_ci	std::vector<deUint64>			matches;
3173e5c31af7Sopenharmony_ci
3174e5c31af7Sopenharmony_ci	for (std::size_t i = 0; i < cbottoms; ++i)
3175e5c31af7Sopenharmony_ci	{
3176e5c31af7Sopenharmony_ci		const deUint64& lookAddr	= addresses[i+1];
3177e5c31af7Sopenharmony_ci		auto			end			= matches.end();
3178e5c31af7Sopenharmony_ci		auto			match		= std::find_if(matches.begin(), end, [&](const deUint64& item){ return item == lookAddr; });
3179e5c31af7Sopenharmony_ci		if (match == end)
3180e5c31af7Sopenharmony_ci		{
3181e5c31af7Sopenharmony_ci			matches.emplace_back(lookAddr);
3182e5c31af7Sopenharmony_ci			m_bottomLevelInstances[i].get()->serialize(vk, device, cmdBuffer, storage->getBottomStorage(storageIndex).get());
3183e5c31af7Sopenharmony_ci			storageIndex += 1;
3184e5c31af7Sopenharmony_ci		}
3185e5c31af7Sopenharmony_ci	}
3186e5c31af7Sopenharmony_ci}
3187e5c31af7Sopenharmony_ci
3188e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::createAndDeserializeBottoms (const DeviceInterface&	vk,
3189e5c31af7Sopenharmony_ci																	const VkDevice			device,
3190e5c31af7Sopenharmony_ci																	const VkCommandBuffer	cmdBuffer,
3191e5c31af7Sopenharmony_ci																	Allocator&				allocator,
3192e5c31af7Sopenharmony_ci																	SerialStorage*			storage)
3193e5c31af7Sopenharmony_ci{
3194e5c31af7Sopenharmony_ci	DE_ASSERT(storage->hasDeepFormat());
3195e5c31af7Sopenharmony_ci	DE_ASSERT(m_bottomLevelInstances.size() == 0);
3196e5c31af7Sopenharmony_ci
3197e5c31af7Sopenharmony_ci	const std::vector<deUint64>&					addresses		= storage->getSerialInfo().addresses();
3198e5c31af7Sopenharmony_ci	const std::size_t								cbottoms		= addresses.size() - 1;
3199e5c31af7Sopenharmony_ci	deUint32										storageIndex	= 0;
3200e5c31af7Sopenharmony_ci	std::vector<std::pair<deUint64, std::size_t>>	matches;
3201e5c31af7Sopenharmony_ci
3202e5c31af7Sopenharmony_ci	for (std::size_t i = 0; i < cbottoms; ++i)
3203e5c31af7Sopenharmony_ci	{
3204e5c31af7Sopenharmony_ci		const deUint64& lookAddr	= addresses[i+1];
3205e5c31af7Sopenharmony_ci		auto			end			= matches.end();
3206e5c31af7Sopenharmony_ci		auto			match		= std::find_if(matches.begin(), end, [&](const std::pair<deUint64, std::size_t>& item){ return item.first == lookAddr; });
3207e5c31af7Sopenharmony_ci		if (match != end)
3208e5c31af7Sopenharmony_ci		{
3209e5c31af7Sopenharmony_ci			m_bottomLevelInstances .emplace_back(m_bottomLevelInstances[match->second]);
3210e5c31af7Sopenharmony_ci		}
3211e5c31af7Sopenharmony_ci		else
3212e5c31af7Sopenharmony_ci		{
3213e5c31af7Sopenharmony_ci			de::MovePtr<BottomLevelAccelerationStructure> blas = makeBottomLevelAccelerationStructure();
3214e5c31af7Sopenharmony_ci			blas->createAndDeserializeFrom(vk, device, cmdBuffer, allocator, storage->getBottomStorage(storageIndex).get());
3215e5c31af7Sopenharmony_ci			m_bottomLevelInstances.emplace_back(de::SharedPtr<BottomLevelAccelerationStructure>(blas.release()));
3216e5c31af7Sopenharmony_ci			matches.emplace_back(lookAddr, i);
3217e5c31af7Sopenharmony_ci			storageIndex += 1;
3218e5c31af7Sopenharmony_ci		}
3219e5c31af7Sopenharmony_ci	}
3220e5c31af7Sopenharmony_ci
3221e5c31af7Sopenharmony_ci	std::vector<deUint64>						newAddresses	= getSerializingAddresses(vk, device);
3222e5c31af7Sopenharmony_ci	DE_ASSERT(addresses.size() == newAddresses.size());
3223e5c31af7Sopenharmony_ci
3224e5c31af7Sopenharmony_ci	SerialStorage::AccelerationStructureHeader* header			= storage->getASHeader();
3225e5c31af7Sopenharmony_ci	DE_ASSERT(cbottoms ==header->handleCount);
3226e5c31af7Sopenharmony_ci
3227e5c31af7Sopenharmony_ci	// finally update bottom-level AS addresses before top-level AS deserialization
3228e5c31af7Sopenharmony_ci	for (std::size_t i = 0; i < cbottoms; ++i)
3229e5c31af7Sopenharmony_ci	{
3230e5c31af7Sopenharmony_ci		header->handleArray[i] = newAddresses[i+1];
3231e5c31af7Sopenharmony_ci	}
3232e5c31af7Sopenharmony_ci}
3233e5c31af7Sopenharmony_ci
3234e5c31af7Sopenharmony_cistd::vector<VkDeviceSize> TopLevelAccelerationStructureKHR::getSerializingSizes (const DeviceInterface&	vk,
3235e5c31af7Sopenharmony_ci																				 const VkDevice			device,
3236e5c31af7Sopenharmony_ci																				 const VkQueue			queue,
3237e5c31af7Sopenharmony_ci																				 const deUint32			queueFamilyIndex)
3238e5c31af7Sopenharmony_ci{
3239e5c31af7Sopenharmony_ci	const deUint32							queryCount(deUint32(m_bottomLevelInstances.size()) + 1);
3240e5c31af7Sopenharmony_ci	std::vector<VkAccelerationStructureKHR>	handles(queryCount);
3241e5c31af7Sopenharmony_ci	std::vector<VkDeviceSize>				sizes(queryCount);
3242e5c31af7Sopenharmony_ci
3243e5c31af7Sopenharmony_ci	handles[0] = m_accelerationStructureKHR.get();
3244e5c31af7Sopenharmony_ci
3245e5c31af7Sopenharmony_ci	for (deUint32 h = 1; h < queryCount; ++h)
3246e5c31af7Sopenharmony_ci		handles[h] = *m_bottomLevelInstances[h-1].get()->getPtr();
3247e5c31af7Sopenharmony_ci
3248e5c31af7Sopenharmony_ci	if (VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR == m_buildType)
3249e5c31af7Sopenharmony_ci		queryAccelerationStructureSize(vk, device, DE_NULL, handles, m_buildType, DE_NULL, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, sizes);
3250e5c31af7Sopenharmony_ci	else
3251e5c31af7Sopenharmony_ci	{
3252e5c31af7Sopenharmony_ci		const Move<VkCommandPool>	cmdPool		= createCommandPool(vk, device, 0, queueFamilyIndex);
3253e5c31af7Sopenharmony_ci		const Move<VkCommandBuffer>	cmdBuffer	= allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3254e5c31af7Sopenharmony_ci		const Move<VkQueryPool>		queryPool	= makeQueryPool(vk, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
3255e5c31af7Sopenharmony_ci
3256e5c31af7Sopenharmony_ci		beginCommandBuffer(vk, *cmdBuffer);
3257e5c31af7Sopenharmony_ci		queryAccelerationStructureSize(vk, device, *cmdBuffer, handles, m_buildType, *queryPool, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, sizes);
3258e5c31af7Sopenharmony_ci		endCommandBuffer(vk, *cmdBuffer);
3259e5c31af7Sopenharmony_ci		submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
3260e5c31af7Sopenharmony_ci
3261e5c31af7Sopenharmony_ci		VK_CHECK(vk.getQueryPoolResults(device, *queryPool, 0u, queryCount, queryCount * sizeof(VkDeviceSize), sizes.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3262e5c31af7Sopenharmony_ci	}
3263e5c31af7Sopenharmony_ci
3264e5c31af7Sopenharmony_ci	return sizes;
3265e5c31af7Sopenharmony_ci}
3266e5c31af7Sopenharmony_ci
3267e5c31af7Sopenharmony_cistd::vector<deUint64> TopLevelAccelerationStructureKHR::getSerializingAddresses (const DeviceInterface& vk, const VkDevice device) const
3268e5c31af7Sopenharmony_ci{
3269e5c31af7Sopenharmony_ci	std::vector<deUint64> result(m_bottomLevelInstances.size() + 1);
3270e5c31af7Sopenharmony_ci
3271e5c31af7Sopenharmony_ci	VkAccelerationStructureDeviceAddressInfoKHR asDeviceAddressInfo =
3272e5c31af7Sopenharmony_ci	{
3273e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR,	// VkStructureType				sType;
3274e5c31af7Sopenharmony_ci		DE_NULL,															// const void*					pNext;
3275e5c31af7Sopenharmony_ci		DE_NULL																// VkAccelerationStructureKHR	accelerationStructure;
3276e5c31af7Sopenharmony_ci	};
3277e5c31af7Sopenharmony_ci
3278e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3279e5c31af7Sopenharmony_ci	{
3280e5c31af7Sopenharmony_ci		asDeviceAddressInfo.accelerationStructure = m_accelerationStructureKHR.get();
3281e5c31af7Sopenharmony_ci		result[0] = vk.getAccelerationStructureDeviceAddressKHR(device, &asDeviceAddressInfo);
3282e5c31af7Sopenharmony_ci	}
3283e5c31af7Sopenharmony_ci	else
3284e5c31af7Sopenharmony_ci	{
3285e5c31af7Sopenharmony_ci		result[0] = deUint64(getPtr()->getInternal());
3286e5c31af7Sopenharmony_ci	}
3287e5c31af7Sopenharmony_ci
3288e5c31af7Sopenharmony_ci	for (size_t instanceNdx = 0; instanceNdx < m_bottomLevelInstances.size(); ++instanceNdx)
3289e5c31af7Sopenharmony_ci	{
3290e5c31af7Sopenharmony_ci		const BottomLevelAccelerationStructure&		bottomLevelAccelerationStructure	= *m_bottomLevelInstances[instanceNdx];
3291e5c31af7Sopenharmony_ci		const VkAccelerationStructureKHR			accelerationStructureKHR			= *bottomLevelAccelerationStructure.getPtr();
3292e5c31af7Sopenharmony_ci
3293e5c31af7Sopenharmony_ci		if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3294e5c31af7Sopenharmony_ci		{
3295e5c31af7Sopenharmony_ci			asDeviceAddressInfo.accelerationStructure = accelerationStructureKHR;
3296e5c31af7Sopenharmony_ci			result[instanceNdx+1] = vk.getAccelerationStructureDeviceAddressKHR(device, &asDeviceAddressInfo);
3297e5c31af7Sopenharmony_ci		}
3298e5c31af7Sopenharmony_ci		else
3299e5c31af7Sopenharmony_ci		{
3300e5c31af7Sopenharmony_ci			result[instanceNdx+1] = deUint64(accelerationStructureKHR.getInternal());
3301e5c31af7Sopenharmony_ci		}
3302e5c31af7Sopenharmony_ci	}
3303e5c31af7Sopenharmony_ci
3304e5c31af7Sopenharmony_ci	return result;
3305e5c31af7Sopenharmony_ci}
3306e5c31af7Sopenharmony_ci
3307e5c31af7Sopenharmony_ciconst VkAccelerationStructureKHR* TopLevelAccelerationStructureKHR::getPtr (void) const
3308e5c31af7Sopenharmony_ci{
3309e5c31af7Sopenharmony_ci	return &m_accelerationStructureKHR.get();
3310e5c31af7Sopenharmony_ci}
3311e5c31af7Sopenharmony_ci
3312e5c31af7Sopenharmony_civoid TopLevelAccelerationStructureKHR::prepareInstances (const DeviceInterface&							vk,
3313e5c31af7Sopenharmony_ci														 const VkDevice									device,
3314e5c31af7Sopenharmony_ci														 VkAccelerationStructureGeometryKHR&			accelerationStructureGeometryKHR,
3315e5c31af7Sopenharmony_ci														 std::vector<deUint32>&							maxPrimitiveCounts)
3316e5c31af7Sopenharmony_ci{
3317e5c31af7Sopenharmony_ci	maxPrimitiveCounts.resize(1);
3318e5c31af7Sopenharmony_ci	maxPrimitiveCounts[0] = static_cast<deUint32>(m_bottomLevelInstances.size());
3319e5c31af7Sopenharmony_ci
3320e5c31af7Sopenharmony_ci	VkDeviceOrHostAddressConstKHR							instancesData;
3321e5c31af7Sopenharmony_ci	if (m_buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3322e5c31af7Sopenharmony_ci	{
3323e5c31af7Sopenharmony_ci		if(m_instanceBuffer.get() != DE_NULL)
3324e5c31af7Sopenharmony_ci		{
3325e5c31af7Sopenharmony_ci			if (m_useArrayOfPointers)
3326e5c31af7Sopenharmony_ci			{
3327e5c31af7Sopenharmony_ci				deUint8*						bufferStart			= static_cast<deUint8*>(m_instanceAddressBuffer->getAllocation().getHostPtr());
3328e5c31af7Sopenharmony_ci				VkDeviceSize					bufferOffset		= 0;
3329e5c31af7Sopenharmony_ci				VkDeviceOrHostAddressConstKHR	firstInstance		= makeDeviceOrHostAddressConstKHR(vk, device, m_instanceBuffer->get(), 0);
3330e5c31af7Sopenharmony_ci				for (size_t instanceNdx = 0; instanceNdx < m_bottomLevelInstances.size(); ++instanceNdx)
3331e5c31af7Sopenharmony_ci				{
3332e5c31af7Sopenharmony_ci					VkDeviceOrHostAddressConstKHR	currentInstance;
3333e5c31af7Sopenharmony_ci					currentInstance.deviceAddress	= firstInstance.deviceAddress + instanceNdx * sizeof(VkAccelerationStructureInstanceKHR);
3334e5c31af7Sopenharmony_ci
3335e5c31af7Sopenharmony_ci					deMemcpy(&bufferStart[bufferOffset], &currentInstance, sizeof(VkDeviceOrHostAddressConstKHR::deviceAddress));
3336e5c31af7Sopenharmony_ci					bufferOffset += sizeof(VkDeviceOrHostAddressConstKHR::deviceAddress);
3337e5c31af7Sopenharmony_ci				}
3338e5c31af7Sopenharmony_ci				flushMappedMemoryRange(vk, device, m_instanceAddressBuffer->getAllocation().getMemory(), m_instanceAddressBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
3339e5c31af7Sopenharmony_ci
3340e5c31af7Sopenharmony_ci				instancesData = makeDeviceOrHostAddressConstKHR(vk, device, m_instanceAddressBuffer->get(), 0);
3341e5c31af7Sopenharmony_ci			}
3342e5c31af7Sopenharmony_ci			else
3343e5c31af7Sopenharmony_ci				instancesData = makeDeviceOrHostAddressConstKHR(vk, device, m_instanceBuffer->get(), 0);
3344e5c31af7Sopenharmony_ci		}
3345e5c31af7Sopenharmony_ci		else
3346e5c31af7Sopenharmony_ci			instancesData = makeDeviceOrHostAddressConstKHR(DE_NULL);
3347e5c31af7Sopenharmony_ci	}
3348e5c31af7Sopenharmony_ci	else
3349e5c31af7Sopenharmony_ci	{
3350e5c31af7Sopenharmony_ci		if (m_instanceBuffer.get() != DE_NULL)
3351e5c31af7Sopenharmony_ci		{
3352e5c31af7Sopenharmony_ci			if (m_useArrayOfPointers)
3353e5c31af7Sopenharmony_ci			{
3354e5c31af7Sopenharmony_ci				deUint8*						bufferStart			= static_cast<deUint8*>(m_instanceAddressBuffer->getAllocation().getHostPtr());
3355e5c31af7Sopenharmony_ci				VkDeviceSize					bufferOffset		= 0;
3356e5c31af7Sopenharmony_ci				for (size_t instanceNdx = 0; instanceNdx < m_bottomLevelInstances.size(); ++instanceNdx)
3357e5c31af7Sopenharmony_ci				{
3358e5c31af7Sopenharmony_ci					VkDeviceOrHostAddressConstKHR	currentInstance;
3359e5c31af7Sopenharmony_ci					currentInstance.hostAddress	= (deUint8*)m_instanceBuffer->getAllocation().getHostPtr() + instanceNdx * sizeof(VkAccelerationStructureInstanceKHR);
3360e5c31af7Sopenharmony_ci
3361e5c31af7Sopenharmony_ci					deMemcpy(&bufferStart[bufferOffset], &currentInstance, sizeof(VkDeviceOrHostAddressConstKHR::hostAddress));
3362e5c31af7Sopenharmony_ci					bufferOffset += sizeof(VkDeviceOrHostAddressConstKHR::hostAddress);
3363e5c31af7Sopenharmony_ci				}
3364e5c31af7Sopenharmony_ci				instancesData = makeDeviceOrHostAddressConstKHR(m_instanceAddressBuffer->getAllocation().getHostPtr());
3365e5c31af7Sopenharmony_ci			}
3366e5c31af7Sopenharmony_ci			else
3367e5c31af7Sopenharmony_ci				instancesData = makeDeviceOrHostAddressConstKHR(m_instanceBuffer->getAllocation().getHostPtr());
3368e5c31af7Sopenharmony_ci		}
3369e5c31af7Sopenharmony_ci		else
3370e5c31af7Sopenharmony_ci			instancesData = makeDeviceOrHostAddressConstKHR(DE_NULL);
3371e5c31af7Sopenharmony_ci	}
3372e5c31af7Sopenharmony_ci
3373e5c31af7Sopenharmony_ci	VkAccelerationStructureGeometryInstancesDataKHR accelerationStructureGeometryInstancesDataKHR	=
3374e5c31af7Sopenharmony_ci	{
3375e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR,	//  VkStructureType					sType;
3376e5c31af7Sopenharmony_ci		DE_NULL,																//  const void*						pNext;
3377e5c31af7Sopenharmony_ci		(VkBool32)( m_useArrayOfPointers ? DE_TRUE : DE_FALSE ),				//  VkBool32						arrayOfPointers;
3378e5c31af7Sopenharmony_ci		instancesData															//  VkDeviceOrHostAddressConstKHR	data;
3379e5c31af7Sopenharmony_ci	};
3380e5c31af7Sopenharmony_ci
3381e5c31af7Sopenharmony_ci	accelerationStructureGeometryKHR					=
3382e5c31af7Sopenharmony_ci	{
3383e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR,										//  VkStructureType							sType;
3384e5c31af7Sopenharmony_ci		DE_NULL,																					//  const void*								pNext;
3385e5c31af7Sopenharmony_ci		VK_GEOMETRY_TYPE_INSTANCES_KHR,																//  VkGeometryTypeKHR						geometryType;
3386e5c31af7Sopenharmony_ci		makeVkAccelerationStructureInstancesDataKHR(accelerationStructureGeometryInstancesDataKHR),	//  VkAccelerationStructureGeometryDataKHR	geometry;
3387e5c31af7Sopenharmony_ci		(VkGeometryFlagsKHR)0u																		//  VkGeometryFlagsKHR						flags;
3388e5c31af7Sopenharmony_ci	};
3389e5c31af7Sopenharmony_ci}
3390e5c31af7Sopenharmony_ci
3391e5c31af7Sopenharmony_cideUint32 TopLevelAccelerationStructure::getRequiredAllocationCount (void)
3392e5c31af7Sopenharmony_ci{
3393e5c31af7Sopenharmony_ci	return TopLevelAccelerationStructureKHR::getRequiredAllocationCount();
3394e5c31af7Sopenharmony_ci}
3395e5c31af7Sopenharmony_ci
3396e5c31af7Sopenharmony_cide::MovePtr<TopLevelAccelerationStructure> makeTopLevelAccelerationStructure ()
3397e5c31af7Sopenharmony_ci{
3398e5c31af7Sopenharmony_ci	return de::MovePtr<TopLevelAccelerationStructure>(new TopLevelAccelerationStructureKHR);
3399e5c31af7Sopenharmony_ci}
3400e5c31af7Sopenharmony_ci
3401e5c31af7Sopenharmony_cibool queryAccelerationStructureSizeKHR (const DeviceInterface&							vk,
3402e5c31af7Sopenharmony_ci										const VkDevice									device,
3403e5c31af7Sopenharmony_ci										const VkCommandBuffer							cmdBuffer,
3404e5c31af7Sopenharmony_ci										const std::vector<VkAccelerationStructureKHR>&	accelerationStructureHandles,
3405e5c31af7Sopenharmony_ci										VkAccelerationStructureBuildTypeKHR				buildType,
3406e5c31af7Sopenharmony_ci										const VkQueryPool								queryPool,
3407e5c31af7Sopenharmony_ci										VkQueryType										queryType,
3408e5c31af7Sopenharmony_ci										deUint32										firstQuery,
3409e5c31af7Sopenharmony_ci										std::vector<VkDeviceSize>&						results)
3410e5c31af7Sopenharmony_ci{
3411e5c31af7Sopenharmony_ci	DE_ASSERT(queryType == VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR || queryType == VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR);
3412e5c31af7Sopenharmony_ci
3413e5c31af7Sopenharmony_ci	if (buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
3414e5c31af7Sopenharmony_ci	{
3415e5c31af7Sopenharmony_ci		// queryPool must be large enough to contain at least (firstQuery + accelerationStructureHandles.size()) queries
3416e5c31af7Sopenharmony_ci		vk.cmdResetQueryPool(cmdBuffer, queryPool, firstQuery, deUint32(accelerationStructureHandles.size()));
3417e5c31af7Sopenharmony_ci		vk.cmdWriteAccelerationStructuresPropertiesKHR(cmdBuffer, deUint32(accelerationStructureHandles.size()), accelerationStructureHandles.data(), queryType, queryPool, firstQuery);
3418e5c31af7Sopenharmony_ci		// results cannot be retrieved to CPU at the moment - you need to do it using getQueryPoolResults after cmdBuffer is executed. Meanwhile function returns a vector of 0s.
3419e5c31af7Sopenharmony_ci		results.resize(accelerationStructureHandles.size(), 0u);
3420e5c31af7Sopenharmony_ci		return false;
3421e5c31af7Sopenharmony_ci	}
3422e5c31af7Sopenharmony_ci	// buildType != VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR
3423e5c31af7Sopenharmony_ci	results.resize(accelerationStructureHandles.size(), 0u);
3424e5c31af7Sopenharmony_ci	vk.writeAccelerationStructuresPropertiesKHR(device, deUint32(accelerationStructureHandles.size()), accelerationStructureHandles.data(), queryType,
3425e5c31af7Sopenharmony_ci												sizeof(VkDeviceSize) * accelerationStructureHandles.size(), results.data(), sizeof(VkDeviceSize));
3426e5c31af7Sopenharmony_ci	// results will contain proper values
3427e5c31af7Sopenharmony_ci	return true;
3428e5c31af7Sopenharmony_ci}
3429e5c31af7Sopenharmony_ci
3430e5c31af7Sopenharmony_cibool queryAccelerationStructureSize (const DeviceInterface&							vk,
3431e5c31af7Sopenharmony_ci									 const VkDevice									device,
3432e5c31af7Sopenharmony_ci									 const VkCommandBuffer							cmdBuffer,
3433e5c31af7Sopenharmony_ci									 const std::vector<VkAccelerationStructureKHR>&	accelerationStructureHandles,
3434e5c31af7Sopenharmony_ci									 VkAccelerationStructureBuildTypeKHR			buildType,
3435e5c31af7Sopenharmony_ci									 const VkQueryPool								queryPool,
3436e5c31af7Sopenharmony_ci									 VkQueryType									queryType,
3437e5c31af7Sopenharmony_ci									 deUint32										firstQuery,
3438e5c31af7Sopenharmony_ci									 std::vector<VkDeviceSize>&						results)
3439e5c31af7Sopenharmony_ci{
3440e5c31af7Sopenharmony_ci	return queryAccelerationStructureSizeKHR(vk, device, cmdBuffer, accelerationStructureHandles, buildType, queryPool, queryType, firstQuery, results);
3441e5c31af7Sopenharmony_ci}
3442e5c31af7Sopenharmony_ci
3443e5c31af7Sopenharmony_ciRayTracingPipeline::RayTracingPipeline ()
3444e5c31af7Sopenharmony_ci	: m_shadersModules			()
3445e5c31af7Sopenharmony_ci	, m_pipelineLibraries		()
3446e5c31af7Sopenharmony_ci	, m_shaderCreateInfos		()
3447e5c31af7Sopenharmony_ci	, m_shadersGroupCreateInfos	()
3448e5c31af7Sopenharmony_ci	, m_pipelineCreateFlags		(0U)
3449e5c31af7Sopenharmony_ci	, m_pipelineCreateFlags2	(0U)
3450e5c31af7Sopenharmony_ci	, m_maxRecursionDepth		(1U)
3451e5c31af7Sopenharmony_ci	, m_maxPayloadSize			(0U)
3452e5c31af7Sopenharmony_ci	, m_maxAttributeSize		(0U)
3453e5c31af7Sopenharmony_ci	, m_deferredOperation		(false)
3454e5c31af7Sopenharmony_ci	, m_workerThreadCount		(0)
3455e5c31af7Sopenharmony_ci{
3456e5c31af7Sopenharmony_ci}
3457e5c31af7Sopenharmony_ci
3458e5c31af7Sopenharmony_ciRayTracingPipeline::~RayTracingPipeline ()
3459e5c31af7Sopenharmony_ci{
3460e5c31af7Sopenharmony_ci}
3461e5c31af7Sopenharmony_ci
3462e5c31af7Sopenharmony_ci#define CHECKED_ASSIGN_SHADER(SHADER, STAGE)						\
3463e5c31af7Sopenharmony_ci	if (SHADER == VK_SHADER_UNUSED_KHR)								\
3464e5c31af7Sopenharmony_ci		SHADER = STAGE;												\
3465e5c31af7Sopenharmony_ci	else															\
3466e5c31af7Sopenharmony_ci		TCU_THROW(InternalError, "Attempt to reassign shader")
3467e5c31af7Sopenharmony_ci
3468e5c31af7Sopenharmony_civoid RayTracingPipeline::addShader (VkShaderStageFlagBits					shaderStage,
3469e5c31af7Sopenharmony_ci									Move<VkShaderModule>					shaderModule,
3470e5c31af7Sopenharmony_ci									deUint32								group,
3471e5c31af7Sopenharmony_ci									const VkSpecializationInfo*				specializationInfo,
3472e5c31af7Sopenharmony_ci									const VkPipelineShaderStageCreateFlags	pipelineShaderStageCreateFlags,
3473e5c31af7Sopenharmony_ci									const void*								pipelineShaderStageCreateInfopNext)
3474e5c31af7Sopenharmony_ci{
3475e5c31af7Sopenharmony_ci	addShader(shaderStage, makeVkSharedPtr(shaderModule), group, specializationInfo, pipelineShaderStageCreateFlags, pipelineShaderStageCreateInfopNext);
3476e5c31af7Sopenharmony_ci}
3477e5c31af7Sopenharmony_ci
3478e5c31af7Sopenharmony_civoid RayTracingPipeline::addShader (VkShaderStageFlagBits					shaderStage,
3479e5c31af7Sopenharmony_ci									de::SharedPtr<Move<VkShaderModule>>		shaderModule,
3480e5c31af7Sopenharmony_ci									deUint32								group,
3481e5c31af7Sopenharmony_ci									const VkSpecializationInfo*				specializationInfoPtr,
3482e5c31af7Sopenharmony_ci									const VkPipelineShaderStageCreateFlags	pipelineShaderStageCreateFlags,
3483e5c31af7Sopenharmony_ci									const void*								pipelineShaderStageCreateInfopNext)
3484e5c31af7Sopenharmony_ci{
3485e5c31af7Sopenharmony_ci	addShader(shaderStage, **shaderModule, group, specializationInfoPtr, pipelineShaderStageCreateFlags, pipelineShaderStageCreateInfopNext);
3486e5c31af7Sopenharmony_ci	m_shadersModules.push_back(shaderModule);
3487e5c31af7Sopenharmony_ci}
3488e5c31af7Sopenharmony_ci
3489e5c31af7Sopenharmony_civoid RayTracingPipeline::addShader (VkShaderStageFlagBits					shaderStage,
3490e5c31af7Sopenharmony_ci									VkShaderModule							shaderModule,
3491e5c31af7Sopenharmony_ci									deUint32								group,
3492e5c31af7Sopenharmony_ci									const VkSpecializationInfo*				specializationInfoPtr,
3493e5c31af7Sopenharmony_ci									const VkPipelineShaderStageCreateFlags	pipelineShaderStageCreateFlags,
3494e5c31af7Sopenharmony_ci									const void*								pipelineShaderStageCreateInfopNext)
3495e5c31af7Sopenharmony_ci{
3496e5c31af7Sopenharmony_ci	if (group >= m_shadersGroupCreateInfos.size())
3497e5c31af7Sopenharmony_ci	{
3498e5c31af7Sopenharmony_ci		for (size_t groupNdx = m_shadersGroupCreateInfos.size(); groupNdx <= group; ++groupNdx)
3499e5c31af7Sopenharmony_ci		{
3500e5c31af7Sopenharmony_ci			VkRayTracingShaderGroupCreateInfoKHR	shaderGroupCreateInfo	=
3501e5c31af7Sopenharmony_ci			{
3502e5c31af7Sopenharmony_ci				VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR,	//  VkStructureType					sType;
3503e5c31af7Sopenharmony_ci				DE_NULL,													//  const void*						pNext;
3504e5c31af7Sopenharmony_ci				VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR,				//  VkRayTracingShaderGroupTypeKHR	type;
3505e5c31af7Sopenharmony_ci				VK_SHADER_UNUSED_KHR,										//  deUint32						generalShader;
3506e5c31af7Sopenharmony_ci				VK_SHADER_UNUSED_KHR,										//  deUint32						closestHitShader;
3507e5c31af7Sopenharmony_ci				VK_SHADER_UNUSED_KHR,										//  deUint32						anyHitShader;
3508e5c31af7Sopenharmony_ci				VK_SHADER_UNUSED_KHR,										//  deUint32						intersectionShader;
3509e5c31af7Sopenharmony_ci				DE_NULL,													//  const void*						pShaderGroupCaptureReplayHandle;
3510e5c31af7Sopenharmony_ci			};
3511e5c31af7Sopenharmony_ci
3512e5c31af7Sopenharmony_ci			m_shadersGroupCreateInfos.push_back(shaderGroupCreateInfo);
3513e5c31af7Sopenharmony_ci		}
3514e5c31af7Sopenharmony_ci	}
3515e5c31af7Sopenharmony_ci
3516e5c31af7Sopenharmony_ci	const deUint32							shaderStageNdx			= (deUint32)m_shaderCreateInfos.size();
3517e5c31af7Sopenharmony_ci	VkRayTracingShaderGroupCreateInfoKHR&	shaderGroupCreateInfo	= m_shadersGroupCreateInfos[group];
3518e5c31af7Sopenharmony_ci
3519e5c31af7Sopenharmony_ci	switch (shaderStage)
3520e5c31af7Sopenharmony_ci	{
3521e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_RAYGEN_BIT_KHR:		CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.generalShader,		shaderStageNdx);	break;
3522e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_MISS_BIT_KHR:			CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.generalShader,		shaderStageNdx);	break;
3523e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_CALLABLE_BIT_KHR:		CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.generalShader,		shaderStageNdx);	break;
3524e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:		CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.anyHitShader,		shaderStageNdx);	break;
3525e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:	CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.closestHitShader,	shaderStageNdx);	break;
3526e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:	CHECKED_ASSIGN_SHADER(shaderGroupCreateInfo.intersectionShader,	shaderStageNdx);	break;
3527e5c31af7Sopenharmony_ci		default:									TCU_THROW(InternalError, "Unacceptable stage");
3528e5c31af7Sopenharmony_ci	}
3529e5c31af7Sopenharmony_ci
3530e5c31af7Sopenharmony_ci	switch (shaderStage)
3531e5c31af7Sopenharmony_ci	{
3532e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
3533e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_MISS_BIT_KHR:
3534e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
3535e5c31af7Sopenharmony_ci		{
3536e5c31af7Sopenharmony_ci			DE_ASSERT(shaderGroupCreateInfo.type == VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR);
3537e5c31af7Sopenharmony_ci			shaderGroupCreateInfo.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
3538e5c31af7Sopenharmony_ci
3539e5c31af7Sopenharmony_ci			break;
3540e5c31af7Sopenharmony_ci		}
3541e5c31af7Sopenharmony_ci
3542e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
3543e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
3544e5c31af7Sopenharmony_ci		case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
3545e5c31af7Sopenharmony_ci		{
3546e5c31af7Sopenharmony_ci			DE_ASSERT(shaderGroupCreateInfo.type != VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR);
3547e5c31af7Sopenharmony_ci			shaderGroupCreateInfo.type	= (shaderGroupCreateInfo.intersectionShader == VK_SHADER_UNUSED_KHR)
3548e5c31af7Sopenharmony_ci										? VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR
3549e5c31af7Sopenharmony_ci										: VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR;
3550e5c31af7Sopenharmony_ci
3551e5c31af7Sopenharmony_ci			break;
3552e5c31af7Sopenharmony_ci		}
3553e5c31af7Sopenharmony_ci
3554e5c31af7Sopenharmony_ci		default: TCU_THROW(InternalError, "Unacceptable stage");
3555e5c31af7Sopenharmony_ci	}
3556e5c31af7Sopenharmony_ci
3557e5c31af7Sopenharmony_ci	{
3558e5c31af7Sopenharmony_ci		const VkPipelineShaderStageCreateInfo	shaderCreateInfo	=
3559e5c31af7Sopenharmony_ci		{
3560e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//  VkStructureType						sType;
3561e5c31af7Sopenharmony_ci			pipelineShaderStageCreateInfopNext,						//  const void*							pNext;
3562e5c31af7Sopenharmony_ci			pipelineShaderStageCreateFlags,							//  VkPipelineShaderStageCreateFlags	flags;
3563e5c31af7Sopenharmony_ci			shaderStage,											//  VkShaderStageFlagBits				stage;
3564e5c31af7Sopenharmony_ci			shaderModule,											//  VkShaderModule						module;
3565e5c31af7Sopenharmony_ci			"main",													//  const char*							pName;
3566e5c31af7Sopenharmony_ci			specializationInfoPtr,									//  const VkSpecializationInfo*			pSpecializationInfo;
3567e5c31af7Sopenharmony_ci		};
3568e5c31af7Sopenharmony_ci
3569e5c31af7Sopenharmony_ci		m_shaderCreateInfos.push_back(shaderCreateInfo);
3570e5c31af7Sopenharmony_ci	}
3571e5c31af7Sopenharmony_ci}
3572e5c31af7Sopenharmony_ci
3573e5c31af7Sopenharmony_civoid RayTracingPipeline::setGroupCaptureReplayHandle (uint32_t group, const void* pShaderGroupCaptureReplayHandle)
3574e5c31af7Sopenharmony_ci{
3575e5c31af7Sopenharmony_ci	DE_ASSERT(static_cast<size_t>(group) < m_shadersGroupCreateInfos.size());
3576e5c31af7Sopenharmony_ci	m_shadersGroupCreateInfos[group].pShaderGroupCaptureReplayHandle = pShaderGroupCaptureReplayHandle;
3577e5c31af7Sopenharmony_ci}
3578e5c31af7Sopenharmony_ci
3579e5c31af7Sopenharmony_civoid RayTracingPipeline::addLibrary (de::SharedPtr<de::MovePtr<RayTracingPipeline>> pipelineLibrary)
3580e5c31af7Sopenharmony_ci{
3581e5c31af7Sopenharmony_ci	m_pipelineLibraries.push_back(pipelineLibrary);
3582e5c31af7Sopenharmony_ci}
3583e5c31af7Sopenharmony_ci
3584e5c31af7Sopenharmony_ciuint32_t RayTracingPipeline::getShaderGroupCount (void)
3585e5c31af7Sopenharmony_ci{
3586e5c31af7Sopenharmony_ci	return de::sizeU32(m_shadersGroupCreateInfos);
3587e5c31af7Sopenharmony_ci}
3588e5c31af7Sopenharmony_ci
3589e5c31af7Sopenharmony_ciuint32_t RayTracingPipeline::getFullShaderGroupCount (void)
3590e5c31af7Sopenharmony_ci{
3591e5c31af7Sopenharmony_ci	uint32_t totalCount = getShaderGroupCount();
3592e5c31af7Sopenharmony_ci
3593e5c31af7Sopenharmony_ci	for (const auto& lib : m_pipelineLibraries)
3594e5c31af7Sopenharmony_ci		totalCount += lib->get()->getFullShaderGroupCount();
3595e5c31af7Sopenharmony_ci
3596e5c31af7Sopenharmony_ci	return totalCount;
3597e5c31af7Sopenharmony_ci}
3598e5c31af7Sopenharmony_ci
3599e5c31af7Sopenharmony_ciMove<VkPipeline> RayTracingPipeline::createPipelineKHR (const DeviceInterface&			vk,
3600e5c31af7Sopenharmony_ci														const VkDevice					device,
3601e5c31af7Sopenharmony_ci														const VkPipelineLayout			pipelineLayout,
3602e5c31af7Sopenharmony_ci														const std::vector<VkPipeline>&	pipelineLibraries,
3603e5c31af7Sopenharmony_ci														const VkPipelineCache			pipelineCache)
3604e5c31af7Sopenharmony_ci{
3605e5c31af7Sopenharmony_ci	for (size_t groupNdx = 0; groupNdx < m_shadersGroupCreateInfos.size(); ++groupNdx)
3606e5c31af7Sopenharmony_ci		DE_ASSERT(m_shadersGroupCreateInfos[groupNdx].sType == VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR);
3607e5c31af7Sopenharmony_ci
3608e5c31af7Sopenharmony_ci	VkPipelineLibraryCreateInfoKHR				librariesCreateInfo	=
3609e5c31af7Sopenharmony_ci	{
3610e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR,	//  VkStructureType	sType;
3611e5c31af7Sopenharmony_ci		DE_NULL,											//  const void*		pNext;
3612e5c31af7Sopenharmony_ci		de::sizeU32(pipelineLibraries),						//  deUint32		libraryCount;
3613e5c31af7Sopenharmony_ci		de::dataOrNull(pipelineLibraries)					//  VkPipeline*		pLibraries;
3614e5c31af7Sopenharmony_ci	};
3615e5c31af7Sopenharmony_ci	const VkRayTracingPipelineInterfaceCreateInfoKHR	pipelineInterfaceCreateInfo		=
3616e5c31af7Sopenharmony_ci	{
3617e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR,	//  VkStructureType	sType;
3618e5c31af7Sopenharmony_ci		DE_NULL,															//  const void*		pNext;
3619e5c31af7Sopenharmony_ci		m_maxPayloadSize,													//  deUint32		maxPayloadSize;
3620e5c31af7Sopenharmony_ci		m_maxAttributeSize													//  deUint32		maxAttributeSize;
3621e5c31af7Sopenharmony_ci	};
3622e5c31af7Sopenharmony_ci	const bool											addPipelineInterfaceCreateInfo	= m_maxPayloadSize != 0 || m_maxAttributeSize != 0;
3623e5c31af7Sopenharmony_ci	const VkRayTracingPipelineInterfaceCreateInfoKHR*	pipelineInterfaceCreateInfoPtr	= addPipelineInterfaceCreateInfo ? &pipelineInterfaceCreateInfo : DE_NULL;
3624e5c31af7Sopenharmony_ci	const VkPipelineLibraryCreateInfoKHR*				librariesCreateInfoPtr			= (pipelineLibraries.empty() ? nullptr : &librariesCreateInfo);
3625e5c31af7Sopenharmony_ci
3626e5c31af7Sopenharmony_ci	Move<VkDeferredOperationKHR>						deferredOperation;
3627e5c31af7Sopenharmony_ci	if (m_deferredOperation)
3628e5c31af7Sopenharmony_ci		deferredOperation = createDeferredOperationKHR(vk, device);
3629e5c31af7Sopenharmony_ci
3630e5c31af7Sopenharmony_ci	VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo	=
3631e5c31af7Sopenharmony_ci	{
3632e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	// VkStructureType						sType;
3633e5c31af7Sopenharmony_ci		DE_NULL,												// const void*							pNext;
3634e5c31af7Sopenharmony_ci		0,														// VkPipelineDynamicStateCreateFlags	flags;
3635e5c31af7Sopenharmony_ci		static_cast<deUint32>(m_dynamicStates.size() ),			// deUint32								dynamicStateCount;
3636e5c31af7Sopenharmony_ci		m_dynamicStates.data(),									// const VkDynamicState*				pDynamicStates;
3637e5c31af7Sopenharmony_ci	};
3638e5c31af7Sopenharmony_ci
3639e5c31af7Sopenharmony_ci	VkRayTracingPipelineCreateInfoKHR					pipelineCreateInfo
3640e5c31af7Sopenharmony_ci	{
3641e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR,	//  VkStructureType								sType;
3642e5c31af7Sopenharmony_ci		DE_NULL,												//  const void*									pNext;
3643e5c31af7Sopenharmony_ci		m_pipelineCreateFlags,									//  VkPipelineCreateFlags						flags;
3644e5c31af7Sopenharmony_ci		de::sizeU32(m_shaderCreateInfos),						//  deUint32									stageCount;
3645e5c31af7Sopenharmony_ci		de::dataOrNull(m_shaderCreateInfos),					//  const VkPipelineShaderStageCreateInfo*		pStages;
3646e5c31af7Sopenharmony_ci		de::sizeU32(m_shadersGroupCreateInfos),					//  deUint32									groupCount;
3647e5c31af7Sopenharmony_ci		de::dataOrNull(m_shadersGroupCreateInfos),				//  const VkRayTracingShaderGroupCreateInfoKHR*	pGroups;
3648e5c31af7Sopenharmony_ci		m_maxRecursionDepth,									//  deUint32									maxRecursionDepth;
3649e5c31af7Sopenharmony_ci		librariesCreateInfoPtr,									//  VkPipelineLibraryCreateInfoKHR*				pLibraryInfo;
3650e5c31af7Sopenharmony_ci		pipelineInterfaceCreateInfoPtr,							//  VkRayTracingPipelineInterfaceCreateInfoKHR*	pLibraryInterface;
3651e5c31af7Sopenharmony_ci		&dynamicStateCreateInfo,								//  const VkPipelineDynamicStateCreateInfo*		pDynamicState;
3652e5c31af7Sopenharmony_ci		pipelineLayout,											//  VkPipelineLayout							layout;
3653e5c31af7Sopenharmony_ci		(VkPipeline)DE_NULL,									//  VkPipeline									basePipelineHandle;
3654e5c31af7Sopenharmony_ci		0,														//  deInt32										basePipelineIndex;
3655e5c31af7Sopenharmony_ci	};
3656e5c31af7Sopenharmony_ci	VkPipeline											object							= DE_NULL;
3657e5c31af7Sopenharmony_ci	VkResult											result							= vk.createRayTracingPipelinesKHR(device, deferredOperation.get(), pipelineCache, 1u, &pipelineCreateInfo, DE_NULL, &object);
3658e5c31af7Sopenharmony_ci	const bool											allowCompileRequired			= ((m_pipelineCreateFlags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT) != 0);
3659e5c31af7Sopenharmony_ci
3660e5c31af7Sopenharmony_ci	VkPipelineCreateFlags2CreateInfoKHR					pipelineFlags2CreateInfo		= initVulkanStructure();
3661e5c31af7Sopenharmony_ci	if (m_pipelineCreateFlags2)
3662e5c31af7Sopenharmony_ci	{
3663e5c31af7Sopenharmony_ci		pipelineFlags2CreateInfo.flags	= m_pipelineCreateFlags2;
3664e5c31af7Sopenharmony_ci		pipelineCreateInfo.pNext		= &pipelineFlags2CreateInfo;
3665e5c31af7Sopenharmony_ci		pipelineCreateInfo.flags		= 0;
3666e5c31af7Sopenharmony_ci	}
3667e5c31af7Sopenharmony_ci
3668e5c31af7Sopenharmony_ci	if (m_deferredOperation)
3669e5c31af7Sopenharmony_ci	{
3670e5c31af7Sopenharmony_ci		DE_ASSERT(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS || (allowCompileRequired && result == VK_PIPELINE_COMPILE_REQUIRED));
3671e5c31af7Sopenharmony_ci		finishDeferredOperation(vk, device, deferredOperation.get(), m_workerThreadCount, result == VK_OPERATION_NOT_DEFERRED_KHR);
3672e5c31af7Sopenharmony_ci	}
3673e5c31af7Sopenharmony_ci
3674e5c31af7Sopenharmony_ci	if (allowCompileRequired && result == VK_PIPELINE_COMPILE_REQUIRED)
3675e5c31af7Sopenharmony_ci		throw CompileRequiredError("createRayTracingPipelinesKHR returned VK_PIPELINE_COMPILE_REQUIRED");
3676e5c31af7Sopenharmony_ci
3677e5c31af7Sopenharmony_ci	Move<VkPipeline> pipeline (check<VkPipeline>(object), Deleter<VkPipeline>(vk, device, DE_NULL));
3678e5c31af7Sopenharmony_ci	return pipeline;
3679e5c31af7Sopenharmony_ci}
3680e5c31af7Sopenharmony_ci
3681e5c31af7Sopenharmony_ci
3682e5c31af7Sopenharmony_ciMove<VkPipeline> RayTracingPipeline::createPipeline (const DeviceInterface&									vk,
3683e5c31af7Sopenharmony_ci													 const VkDevice											device,
3684e5c31af7Sopenharmony_ci													 const VkPipelineLayout									pipelineLayout,
3685e5c31af7Sopenharmony_ci													 const std::vector<de::SharedPtr<Move<VkPipeline>>>&	pipelineLibraries)
3686e5c31af7Sopenharmony_ci{
3687e5c31af7Sopenharmony_ci	std::vector<VkPipeline> rawPipelines;
3688e5c31af7Sopenharmony_ci	rawPipelines.reserve(pipelineLibraries.size());
3689e5c31af7Sopenharmony_ci	for (const auto& lib : pipelineLibraries)
3690e5c31af7Sopenharmony_ci		rawPipelines.push_back(lib.get()->get());
3691e5c31af7Sopenharmony_ci
3692e5c31af7Sopenharmony_ci	return createPipelineKHR(vk, device, pipelineLayout, rawPipelines);
3693e5c31af7Sopenharmony_ci}
3694e5c31af7Sopenharmony_ci
3695e5c31af7Sopenharmony_ciMove<VkPipeline> RayTracingPipeline::createPipeline (const DeviceInterface&			vk,
3696e5c31af7Sopenharmony_ci													 const VkDevice					device,
3697e5c31af7Sopenharmony_ci													 const VkPipelineLayout			pipelineLayout,
3698e5c31af7Sopenharmony_ci													 const std::vector<VkPipeline>&	pipelineLibraries,
3699e5c31af7Sopenharmony_ci													 const VkPipelineCache			pipelineCache)
3700e5c31af7Sopenharmony_ci{
3701e5c31af7Sopenharmony_ci	return createPipelineKHR(vk, device, pipelineLayout, pipelineLibraries, pipelineCache);
3702e5c31af7Sopenharmony_ci}
3703e5c31af7Sopenharmony_ci
3704e5c31af7Sopenharmony_cistd::vector<de::SharedPtr<Move<VkPipeline>>> RayTracingPipeline::createPipelineWithLibraries (const DeviceInterface&			vk,
3705e5c31af7Sopenharmony_ci																								const VkDevice					device,
3706e5c31af7Sopenharmony_ci																								const VkPipelineLayout			pipelineLayout)
3707e5c31af7Sopenharmony_ci{
3708e5c31af7Sopenharmony_ci	for (size_t groupNdx = 0; groupNdx < m_shadersGroupCreateInfos.size(); ++groupNdx)
3709e5c31af7Sopenharmony_ci		DE_ASSERT(m_shadersGroupCreateInfos[groupNdx].sType == VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR);
3710e5c31af7Sopenharmony_ci
3711e5c31af7Sopenharmony_ci	DE_ASSERT(m_shaderCreateInfos.size() > 0);
3712e5c31af7Sopenharmony_ci	DE_ASSERT(m_shadersGroupCreateInfos.size() > 0);
3713e5c31af7Sopenharmony_ci
3714e5c31af7Sopenharmony_ci	std::vector<de::SharedPtr<Move<VkPipeline>>> result, allLibraries, firstLibraries;
3715e5c31af7Sopenharmony_ci	for(auto it=begin(m_pipelineLibraries), eit=end(m_pipelineLibraries); it!=eit; ++it)
3716e5c31af7Sopenharmony_ci	{
3717e5c31af7Sopenharmony_ci		auto childLibraries = (*it)->get()->createPipelineWithLibraries(vk, device, pipelineLayout);
3718e5c31af7Sopenharmony_ci		DE_ASSERT(childLibraries.size() > 0);
3719e5c31af7Sopenharmony_ci		firstLibraries.push_back(childLibraries[0]);
3720e5c31af7Sopenharmony_ci		std::copy(begin(childLibraries), end(childLibraries), std::back_inserter(allLibraries));
3721e5c31af7Sopenharmony_ci	}
3722e5c31af7Sopenharmony_ci	result.push_back(makeVkSharedPtr(createPipeline(vk, device, pipelineLayout, firstLibraries)));
3723e5c31af7Sopenharmony_ci	std::copy(begin(allLibraries), end(allLibraries), std::back_inserter(result));
3724e5c31af7Sopenharmony_ci	return result;
3725e5c31af7Sopenharmony_ci}
3726e5c31af7Sopenharmony_ci
3727e5c31af7Sopenharmony_cistd::vector<uint8_t> RayTracingPipeline::getShaderGroupHandles (const DeviceInterface&		vk,
3728e5c31af7Sopenharmony_ci																const VkDevice				device,
3729e5c31af7Sopenharmony_ci																const VkPipeline			pipeline,
3730e5c31af7Sopenharmony_ci																const deUint32				shaderGroupHandleSize,
3731e5c31af7Sopenharmony_ci																const deUint32				firstGroup,
3732e5c31af7Sopenharmony_ci																const deUint32				groupCount) const
3733e5c31af7Sopenharmony_ci{
3734e5c31af7Sopenharmony_ci	const auto				handleArraySizeBytes	= groupCount * shaderGroupHandleSize;
3735e5c31af7Sopenharmony_ci	std::vector<uint8_t>	shaderHandles			(handleArraySizeBytes);
3736e5c31af7Sopenharmony_ci
3737e5c31af7Sopenharmony_ci	VK_CHECK(getRayTracingShaderGroupHandles(vk, device, pipeline,
3738e5c31af7Sopenharmony_ci											 firstGroup, groupCount,
3739e5c31af7Sopenharmony_ci											 static_cast<uintptr_t>(shaderHandles.size()), de::dataOrNull(shaderHandles)));
3740e5c31af7Sopenharmony_ci
3741e5c31af7Sopenharmony_ci	return shaderHandles;
3742e5c31af7Sopenharmony_ci}
3743e5c31af7Sopenharmony_ci
3744e5c31af7Sopenharmony_cistd::vector<uint8_t> RayTracingPipeline::getShaderGroupReplayHandles (const DeviceInterface &vk,
3745e5c31af7Sopenharmony_ci																	  const VkDevice device,
3746e5c31af7Sopenharmony_ci																	  const VkPipeline pipeline,
3747e5c31af7Sopenharmony_ci																	  const deUint32 shaderGroupHandleReplaySize,
3748e5c31af7Sopenharmony_ci																	  const deUint32 firstGroup,
3749e5c31af7Sopenharmony_ci																	  const deUint32 groupCount) const
3750e5c31af7Sopenharmony_ci{
3751e5c31af7Sopenharmony_ci	const auto				handleArraySizeBytes	= groupCount * shaderGroupHandleReplaySize;
3752e5c31af7Sopenharmony_ci	std::vector<uint8_t>	shaderHandles			(handleArraySizeBytes);
3753e5c31af7Sopenharmony_ci
3754e5c31af7Sopenharmony_ci	VK_CHECK(getRayTracingCaptureReplayShaderGroupHandles(vk, device, pipeline,
3755e5c31af7Sopenharmony_ci														  firstGroup, groupCount,
3756e5c31af7Sopenharmony_ci														  static_cast<uintptr_t>(shaderHandles.size()), de::dataOrNull(shaderHandles)));
3757e5c31af7Sopenharmony_ci
3758e5c31af7Sopenharmony_ci	return shaderHandles;
3759e5c31af7Sopenharmony_ci}
3760e5c31af7Sopenharmony_ci
3761e5c31af7Sopenharmony_cide::MovePtr<BufferWithMemory> RayTracingPipeline::createShaderBindingTable	(const DeviceInterface&			vk,
3762e5c31af7Sopenharmony_ci																			 const VkDevice					device,
3763e5c31af7Sopenharmony_ci																			 const VkPipeline				pipeline,
3764e5c31af7Sopenharmony_ci																			 Allocator&						allocator,
3765e5c31af7Sopenharmony_ci																			 const deUint32&				shaderGroupHandleSize,
3766e5c31af7Sopenharmony_ci																			 const deUint32					shaderGroupBaseAlignment,
3767e5c31af7Sopenharmony_ci																			 const deUint32&				firstGroup,
3768e5c31af7Sopenharmony_ci																			 const deUint32&				groupCount,
3769e5c31af7Sopenharmony_ci																			 const VkBufferCreateFlags&		additionalBufferCreateFlags,
3770e5c31af7Sopenharmony_ci																			 const VkBufferUsageFlags&		additionalBufferUsageFlags,
3771e5c31af7Sopenharmony_ci																			 const MemoryRequirement&		additionalMemoryRequirement,
3772e5c31af7Sopenharmony_ci																			 const VkDeviceAddress&			opaqueCaptureAddress,
3773e5c31af7Sopenharmony_ci																			 const deUint32					shaderBindingTableOffset,
3774e5c31af7Sopenharmony_ci																			 const deUint32					shaderRecordSize,
3775e5c31af7Sopenharmony_ci																			 const void**					shaderGroupDataPtrPerGroup,
3776e5c31af7Sopenharmony_ci																			 const bool						autoAlignRecords)
3777e5c31af7Sopenharmony_ci{
3778e5c31af7Sopenharmony_ci	const auto shaderHandles = getShaderGroupHandles(vk, device, pipeline, shaderGroupHandleSize, firstGroup, groupCount);
3779e5c31af7Sopenharmony_ci	return createShaderBindingTable(vk, device, allocator,
3780e5c31af7Sopenharmony_ci									shaderGroupHandleSize, shaderGroupBaseAlignment, shaderHandles,
3781e5c31af7Sopenharmony_ci									additionalBufferCreateFlags, additionalBufferUsageFlags, additionalMemoryRequirement,
3782e5c31af7Sopenharmony_ci									opaqueCaptureAddress,
3783e5c31af7Sopenharmony_ci									shaderBindingTableOffset, shaderRecordSize, shaderGroupDataPtrPerGroup,
3784e5c31af7Sopenharmony_ci									autoAlignRecords);
3785e5c31af7Sopenharmony_ci}
3786e5c31af7Sopenharmony_ci
3787e5c31af7Sopenharmony_cide::MovePtr<BufferWithMemory> RayTracingPipeline::createShaderBindingTable (const DeviceInterface&		vk,
3788e5c31af7Sopenharmony_ci																			const VkDevice				device,
3789e5c31af7Sopenharmony_ci																			Allocator&					allocator,
3790e5c31af7Sopenharmony_ci																			const deUint32				shaderGroupHandleSize,
3791e5c31af7Sopenharmony_ci																			const deUint32				shaderGroupBaseAlignment,
3792e5c31af7Sopenharmony_ci																			const std::vector<uint8_t>&	shaderHandles,
3793e5c31af7Sopenharmony_ci																			const VkBufferCreateFlags	additionalBufferCreateFlags,
3794e5c31af7Sopenharmony_ci																			const VkBufferUsageFlags	additionalBufferUsageFlags,
3795e5c31af7Sopenharmony_ci																			const MemoryRequirement&	additionalMemoryRequirement,
3796e5c31af7Sopenharmony_ci																			const VkDeviceAddress		opaqueCaptureAddress,
3797e5c31af7Sopenharmony_ci																			const deUint32				shaderBindingTableOffset,
3798e5c31af7Sopenharmony_ci																			const deUint32				shaderRecordSize,
3799e5c31af7Sopenharmony_ci																			const void**				shaderGroupDataPtrPerGroup,
3800e5c31af7Sopenharmony_ci																			const bool					autoAlignRecords)
3801e5c31af7Sopenharmony_ci{
3802e5c31af7Sopenharmony_ci	DE_ASSERT(shaderGroupBaseAlignment != 0u);
3803e5c31af7Sopenharmony_ci	DE_ASSERT((shaderBindingTableOffset % shaderGroupBaseAlignment) == 0);
3804e5c31af7Sopenharmony_ci	DE_UNREF(shaderGroupBaseAlignment);
3805e5c31af7Sopenharmony_ci
3806e5c31af7Sopenharmony_ci	const auto								groupCount						= de::sizeU32(shaderHandles) / shaderGroupHandleSize;
3807e5c31af7Sopenharmony_ci	const auto								totalEntrySize					= (autoAlignRecords ? (deAlign32(shaderGroupHandleSize + shaderRecordSize, shaderGroupHandleSize)) : (shaderGroupHandleSize + shaderRecordSize));
3808e5c31af7Sopenharmony_ci	const deUint32							sbtSize							= shaderBindingTableOffset + groupCount * totalEntrySize;
3809e5c31af7Sopenharmony_ci	const VkBufferUsageFlags				sbtFlags						= VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | additionalBufferUsageFlags;
3810e5c31af7Sopenharmony_ci	VkBufferCreateInfo						sbtCreateInfo					= makeBufferCreateInfo(sbtSize, sbtFlags);
3811e5c31af7Sopenharmony_ci	sbtCreateInfo.flags														|= additionalBufferCreateFlags;
3812e5c31af7Sopenharmony_ci	VkBufferUsageFlags2CreateInfoKHR		bufferUsageFlags2				= vk::initVulkanStructure();
3813e5c31af7Sopenharmony_ci	VkBufferOpaqueCaptureAddressCreateInfo	sbtCaptureAddressInfo			=
3814e5c31af7Sopenharmony_ci	{
3815e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO,	// VkStructureType	sType;
3816e5c31af7Sopenharmony_ci		DE_NULL,														// const void*		pNext;
3817e5c31af7Sopenharmony_ci		deUint64(opaqueCaptureAddress)									// deUint64			opaqueCaptureAddress;
3818e5c31af7Sopenharmony_ci	};
3819e5c31af7Sopenharmony_ci
3820e5c31af7Sopenharmony_ci	// when maintenance5 is tested then m_pipelineCreateFlags2 is non-zero
3821e5c31af7Sopenharmony_ci	if (m_pipelineCreateFlags2)
3822e5c31af7Sopenharmony_ci	{
3823e5c31af7Sopenharmony_ci		bufferUsageFlags2.usage = (VkBufferUsageFlags2KHR)sbtFlags;
3824e5c31af7Sopenharmony_ci		sbtCreateInfo.pNext = &bufferUsageFlags2;
3825e5c31af7Sopenharmony_ci		sbtCreateInfo.usage = 0;
3826e5c31af7Sopenharmony_ci	}
3827e5c31af7Sopenharmony_ci
3828e5c31af7Sopenharmony_ci	if (opaqueCaptureAddress != 0u)
3829e5c31af7Sopenharmony_ci	{
3830e5c31af7Sopenharmony_ci		sbtCreateInfo.pNext = &sbtCaptureAddressInfo;
3831e5c31af7Sopenharmony_ci		sbtCreateInfo.flags |= VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT;
3832e5c31af7Sopenharmony_ci	}
3833e5c31af7Sopenharmony_ci	const MemoryRequirement			sbtMemRequirements						= MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::DeviceAddress | additionalMemoryRequirement;
3834e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>	sbtBuffer								= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, sbtCreateInfo, sbtMemRequirements));
3835e5c31af7Sopenharmony_ci	vk::Allocation&					sbtAlloc								= sbtBuffer->getAllocation();
3836e5c31af7Sopenharmony_ci
3837e5c31af7Sopenharmony_ci	// Copy handles to table, leaving space for ShaderRecordKHR after each handle.
3838e5c31af7Sopenharmony_ci	deUint8* shaderBegin = (deUint8*)sbtAlloc.getHostPtr() + shaderBindingTableOffset;
3839e5c31af7Sopenharmony_ci	for (deUint32 idx = 0; idx < groupCount; ++idx)
3840e5c31af7Sopenharmony_ci	{
3841e5c31af7Sopenharmony_ci		const deUint8*	shaderSrcPos	= shaderHandles.data() + idx * shaderGroupHandleSize;
3842e5c31af7Sopenharmony_ci		deUint8*		shaderDstPos	= shaderBegin + idx * totalEntrySize;
3843e5c31af7Sopenharmony_ci		deMemcpy(shaderDstPos, shaderSrcPos, shaderGroupHandleSize);
3844e5c31af7Sopenharmony_ci
3845e5c31af7Sopenharmony_ci		if (shaderGroupDataPtrPerGroup		!= nullptr &&
3846e5c31af7Sopenharmony_ci			shaderGroupDataPtrPerGroup[idx] != nullptr)
3847e5c31af7Sopenharmony_ci		{
3848e5c31af7Sopenharmony_ci			DE_ASSERT(sbtSize >= static_cast<deUint32>(shaderDstPos - shaderBegin) + shaderGroupHandleSize);
3849e5c31af7Sopenharmony_ci
3850e5c31af7Sopenharmony_ci			deMemcpy(	shaderDstPos + shaderGroupHandleSize,
3851e5c31af7Sopenharmony_ci						shaderGroupDataPtrPerGroup[idx],
3852e5c31af7Sopenharmony_ci						shaderRecordSize);
3853e5c31af7Sopenharmony_ci		}
3854e5c31af7Sopenharmony_ci	}
3855e5c31af7Sopenharmony_ci
3856e5c31af7Sopenharmony_ci	flushMappedMemoryRange(vk, device, sbtAlloc.getMemory(), sbtAlloc.getOffset(), VK_WHOLE_SIZE);
3857e5c31af7Sopenharmony_ci
3858e5c31af7Sopenharmony_ci	return sbtBuffer;
3859e5c31af7Sopenharmony_ci}
3860e5c31af7Sopenharmony_ci
3861e5c31af7Sopenharmony_civoid RayTracingPipeline::setCreateFlags (const VkPipelineCreateFlags& pipelineCreateFlags)
3862e5c31af7Sopenharmony_ci{
3863e5c31af7Sopenharmony_ci	m_pipelineCreateFlags = pipelineCreateFlags;
3864e5c31af7Sopenharmony_ci}
3865e5c31af7Sopenharmony_ci
3866e5c31af7Sopenharmony_civoid RayTracingPipeline::setCreateFlags2 (const VkPipelineCreateFlags2KHR& pipelineCreateFlags2)
3867e5c31af7Sopenharmony_ci{
3868e5c31af7Sopenharmony_ci	m_pipelineCreateFlags2 = pipelineCreateFlags2;
3869e5c31af7Sopenharmony_ci}
3870e5c31af7Sopenharmony_ci
3871e5c31af7Sopenharmony_civoid RayTracingPipeline::setMaxRecursionDepth (const deUint32& maxRecursionDepth)
3872e5c31af7Sopenharmony_ci{
3873e5c31af7Sopenharmony_ci	m_maxRecursionDepth = maxRecursionDepth;
3874e5c31af7Sopenharmony_ci}
3875e5c31af7Sopenharmony_ci
3876e5c31af7Sopenharmony_civoid RayTracingPipeline::setMaxPayloadSize (const deUint32& maxPayloadSize)
3877e5c31af7Sopenharmony_ci{
3878e5c31af7Sopenharmony_ci	m_maxPayloadSize = maxPayloadSize;
3879e5c31af7Sopenharmony_ci}
3880e5c31af7Sopenharmony_ci
3881e5c31af7Sopenharmony_civoid RayTracingPipeline::setMaxAttributeSize (const deUint32& maxAttributeSize)
3882e5c31af7Sopenharmony_ci{
3883e5c31af7Sopenharmony_ci	m_maxAttributeSize = maxAttributeSize;
3884e5c31af7Sopenharmony_ci}
3885e5c31af7Sopenharmony_ci
3886e5c31af7Sopenharmony_civoid RayTracingPipeline::setDeferredOperation (const bool		deferredOperation,
3887e5c31af7Sopenharmony_ci											   const deUint32	workerThreadCount)
3888e5c31af7Sopenharmony_ci{
3889e5c31af7Sopenharmony_ci	m_deferredOperation = deferredOperation;
3890e5c31af7Sopenharmony_ci	m_workerThreadCount = workerThreadCount;
3891e5c31af7Sopenharmony_ci}
3892e5c31af7Sopenharmony_ci
3893e5c31af7Sopenharmony_civoid RayTracingPipeline::addDynamicState(const VkDynamicState& dynamicState)
3894e5c31af7Sopenharmony_ci{
3895e5c31af7Sopenharmony_ci	m_dynamicStates.push_back(dynamicState);
3896e5c31af7Sopenharmony_ci}
3897e5c31af7Sopenharmony_ci
3898e5c31af7Sopenharmony_ciclass RayTracingPropertiesKHR : public RayTracingProperties
3899e5c31af7Sopenharmony_ci{
3900e5c31af7Sopenharmony_cipublic:
3901e5c31af7Sopenharmony_ci							RayTracingPropertiesKHR						() = delete;
3902e5c31af7Sopenharmony_ci							RayTracingPropertiesKHR						(const InstanceInterface&	vki,
3903e5c31af7Sopenharmony_ci																		 const VkPhysicalDevice		physicalDevice);
3904e5c31af7Sopenharmony_ci	virtual					~RayTracingPropertiesKHR					();
3905e5c31af7Sopenharmony_ci
3906e5c31af7Sopenharmony_ci	uint32_t		getShaderGroupHandleSize					(void)	override { return m_rayTracingPipelineProperties.shaderGroupHandleSize;						}
3907e5c31af7Sopenharmony_ci	uint32_t		getShaderGroupHandleAlignment				(void)	override { return m_rayTracingPipelineProperties.shaderGroupHandleAlignment;				}
3908e5c31af7Sopenharmony_ci	deUint32		getShaderGroupHandleCaptureReplaySize		(void)	override { return m_rayTracingPipelineProperties.shaderGroupHandleCaptureReplaySize;		}
3909e5c31af7Sopenharmony_ci	uint32_t		getMaxRecursionDepth						(void)	override { return m_rayTracingPipelineProperties.maxRayRecursionDepth;						}
3910e5c31af7Sopenharmony_ci	uint32_t		getMaxShaderGroupStride						(void)	override { return m_rayTracingPipelineProperties.maxShaderGroupStride;						}
3911e5c31af7Sopenharmony_ci	uint32_t		getShaderGroupBaseAlignment					(void)	override { return m_rayTracingPipelineProperties.shaderGroupBaseAlignment;					}
3912e5c31af7Sopenharmony_ci	uint64_t		getMaxGeometryCount							(void)	override { return m_accelerationStructureProperties.maxGeometryCount;						}
3913e5c31af7Sopenharmony_ci	uint64_t		getMaxInstanceCount							(void)	override { return m_accelerationStructureProperties.maxInstanceCount;						}
3914e5c31af7Sopenharmony_ci	uint64_t		getMaxPrimitiveCount						(void)	override { return m_accelerationStructureProperties.maxPrimitiveCount;						}
3915e5c31af7Sopenharmony_ci	uint32_t		getMaxDescriptorSetAccelerationStructures	(void)	override { return m_accelerationStructureProperties.maxDescriptorSetAccelerationStructures;	}
3916e5c31af7Sopenharmony_ci	uint32_t		getMaxRayDispatchInvocationCount			(void)	override { return m_rayTracingPipelineProperties.maxRayDispatchInvocationCount;				}
3917e5c31af7Sopenharmony_ci	uint32_t		getMaxRayHitAttributeSize					(void)	override { return m_rayTracingPipelineProperties.maxRayHitAttributeSize;					}
3918e5c31af7Sopenharmony_ci	uint32_t		getMaxMemoryAllocationCount					(void)	override { return m_maxMemoryAllocationCount;												}
3919e5c31af7Sopenharmony_ci
3920e5c31af7Sopenharmony_ciprotected:
3921e5c31af7Sopenharmony_ci	VkPhysicalDeviceAccelerationStructurePropertiesKHR	m_accelerationStructureProperties;
3922e5c31af7Sopenharmony_ci	VkPhysicalDeviceRayTracingPipelinePropertiesKHR		m_rayTracingPipelineProperties;
3923e5c31af7Sopenharmony_ci	deUint32											m_maxMemoryAllocationCount;
3924e5c31af7Sopenharmony_ci};
3925e5c31af7Sopenharmony_ci
3926e5c31af7Sopenharmony_ciRayTracingPropertiesKHR::~RayTracingPropertiesKHR ()
3927e5c31af7Sopenharmony_ci{
3928e5c31af7Sopenharmony_ci}
3929e5c31af7Sopenharmony_ci
3930e5c31af7Sopenharmony_ciRayTracingPropertiesKHR::RayTracingPropertiesKHR (const InstanceInterface&	vki,
3931e5c31af7Sopenharmony_ci												  const VkPhysicalDevice	physicalDevice)
3932e5c31af7Sopenharmony_ci	: RayTracingProperties	(vki, physicalDevice)
3933e5c31af7Sopenharmony_ci{
3934e5c31af7Sopenharmony_ci	m_accelerationStructureProperties	= getPhysicalDeviceExtensionProperties(vki, physicalDevice);
3935e5c31af7Sopenharmony_ci	m_rayTracingPipelineProperties		= getPhysicalDeviceExtensionProperties(vki, physicalDevice);
3936e5c31af7Sopenharmony_ci	m_maxMemoryAllocationCount			= getPhysicalDeviceProperties(vki, physicalDevice).limits.maxMemoryAllocationCount;
3937e5c31af7Sopenharmony_ci}
3938e5c31af7Sopenharmony_ci
3939e5c31af7Sopenharmony_cide::MovePtr<RayTracingProperties> makeRayTracingProperties (const InstanceInterface&	vki,
3940e5c31af7Sopenharmony_ci															const VkPhysicalDevice		physicalDevice)
3941e5c31af7Sopenharmony_ci{
3942e5c31af7Sopenharmony_ci	return de::MovePtr<RayTracingProperties>(new RayTracingPropertiesKHR(vki, physicalDevice));
3943e5c31af7Sopenharmony_ci}
3944e5c31af7Sopenharmony_ci
3945e5c31af7Sopenharmony_cistatic inline void cmdTraceRaysKHR (const DeviceInterface&					vk,
3946e5c31af7Sopenharmony_ci									VkCommandBuffer							commandBuffer,
3947e5c31af7Sopenharmony_ci									const VkStridedDeviceAddressRegionKHR*	raygenShaderBindingTableRegion,
3948e5c31af7Sopenharmony_ci									const VkStridedDeviceAddressRegionKHR*	missShaderBindingTableRegion,
3949e5c31af7Sopenharmony_ci									const VkStridedDeviceAddressRegionKHR*	hitShaderBindingTableRegion,
3950e5c31af7Sopenharmony_ci									const VkStridedDeviceAddressRegionKHR*	callableShaderBindingTableRegion,
3951e5c31af7Sopenharmony_ci									deUint32								width,
3952e5c31af7Sopenharmony_ci									deUint32								height,
3953e5c31af7Sopenharmony_ci									deUint32								depth)
3954e5c31af7Sopenharmony_ci{
3955e5c31af7Sopenharmony_ci	return vk.cmdTraceRaysKHR(commandBuffer,
3956e5c31af7Sopenharmony_ci							  raygenShaderBindingTableRegion,
3957e5c31af7Sopenharmony_ci							  missShaderBindingTableRegion,
3958e5c31af7Sopenharmony_ci							  hitShaderBindingTableRegion,
3959e5c31af7Sopenharmony_ci							  callableShaderBindingTableRegion,
3960e5c31af7Sopenharmony_ci							  width,
3961e5c31af7Sopenharmony_ci							  height,
3962e5c31af7Sopenharmony_ci							  depth);
3963e5c31af7Sopenharmony_ci}
3964e5c31af7Sopenharmony_ci
3965e5c31af7Sopenharmony_ci
3966e5c31af7Sopenharmony_civoid cmdTraceRays (const DeviceInterface&					vk,
3967e5c31af7Sopenharmony_ci				   VkCommandBuffer							commandBuffer,
3968e5c31af7Sopenharmony_ci				   const VkStridedDeviceAddressRegionKHR*	raygenShaderBindingTableRegion,
3969e5c31af7Sopenharmony_ci				   const VkStridedDeviceAddressRegionKHR*	missShaderBindingTableRegion,
3970e5c31af7Sopenharmony_ci				   const VkStridedDeviceAddressRegionKHR*	hitShaderBindingTableRegion,
3971e5c31af7Sopenharmony_ci				   const VkStridedDeviceAddressRegionKHR*	callableShaderBindingTableRegion,
3972e5c31af7Sopenharmony_ci				   deUint32									width,
3973e5c31af7Sopenharmony_ci				   deUint32									height,
3974e5c31af7Sopenharmony_ci				   deUint32									depth)
3975e5c31af7Sopenharmony_ci{
3976e5c31af7Sopenharmony_ci	DE_ASSERT(raygenShaderBindingTableRegion	!= DE_NULL);
3977e5c31af7Sopenharmony_ci	DE_ASSERT(missShaderBindingTableRegion		!= DE_NULL);
3978e5c31af7Sopenharmony_ci	DE_ASSERT(hitShaderBindingTableRegion		!= DE_NULL);
3979e5c31af7Sopenharmony_ci	DE_ASSERT(callableShaderBindingTableRegion	!= DE_NULL);
3980e5c31af7Sopenharmony_ci
3981e5c31af7Sopenharmony_ci	return cmdTraceRaysKHR(vk,
3982e5c31af7Sopenharmony_ci						   commandBuffer,
3983e5c31af7Sopenharmony_ci						   raygenShaderBindingTableRegion,
3984e5c31af7Sopenharmony_ci						   missShaderBindingTableRegion,
3985e5c31af7Sopenharmony_ci						   hitShaderBindingTableRegion,
3986e5c31af7Sopenharmony_ci						   callableShaderBindingTableRegion,
3987e5c31af7Sopenharmony_ci						   width,
3988e5c31af7Sopenharmony_ci						   height,
3989e5c31af7Sopenharmony_ci						   depth);
3990e5c31af7Sopenharmony_ci}
3991e5c31af7Sopenharmony_ci
3992e5c31af7Sopenharmony_cistatic inline void cmdTraceRaysIndirectKHR (const DeviceInterface&					vk,
3993e5c31af7Sopenharmony_ci											VkCommandBuffer							commandBuffer,
3994e5c31af7Sopenharmony_ci											const VkStridedDeviceAddressRegionKHR*	raygenShaderBindingTableRegion,
3995e5c31af7Sopenharmony_ci											const VkStridedDeviceAddressRegionKHR*	missShaderBindingTableRegion,
3996e5c31af7Sopenharmony_ci											const VkStridedDeviceAddressRegionKHR*	hitShaderBindingTableRegion,
3997e5c31af7Sopenharmony_ci											const VkStridedDeviceAddressRegionKHR*	callableShaderBindingTableRegion,
3998e5c31af7Sopenharmony_ci											VkDeviceAddress							indirectDeviceAddress )
3999e5c31af7Sopenharmony_ci{
4000e5c31af7Sopenharmony_ci	DE_ASSERT(raygenShaderBindingTableRegion	!= DE_NULL);
4001e5c31af7Sopenharmony_ci	DE_ASSERT(missShaderBindingTableRegion		!= DE_NULL);
4002e5c31af7Sopenharmony_ci	DE_ASSERT(hitShaderBindingTableRegion		!= DE_NULL);
4003e5c31af7Sopenharmony_ci	DE_ASSERT(callableShaderBindingTableRegion	!= DE_NULL);
4004e5c31af7Sopenharmony_ci	DE_ASSERT(indirectDeviceAddress				!= 0);
4005e5c31af7Sopenharmony_ci
4006e5c31af7Sopenharmony_ci	return vk.cmdTraceRaysIndirectKHR(commandBuffer,
4007e5c31af7Sopenharmony_ci									  raygenShaderBindingTableRegion,
4008e5c31af7Sopenharmony_ci									  missShaderBindingTableRegion,
4009e5c31af7Sopenharmony_ci									  hitShaderBindingTableRegion,
4010e5c31af7Sopenharmony_ci									  callableShaderBindingTableRegion,
4011e5c31af7Sopenharmony_ci									  indirectDeviceAddress);
4012e5c31af7Sopenharmony_ci}
4013e5c31af7Sopenharmony_ci
4014e5c31af7Sopenharmony_civoid cmdTraceRaysIndirect (const DeviceInterface&					vk,
4015e5c31af7Sopenharmony_ci						   VkCommandBuffer							commandBuffer,
4016e5c31af7Sopenharmony_ci						   const VkStridedDeviceAddressRegionKHR*	raygenShaderBindingTableRegion,
4017e5c31af7Sopenharmony_ci						   const VkStridedDeviceAddressRegionKHR*	missShaderBindingTableRegion,
4018e5c31af7Sopenharmony_ci						   const VkStridedDeviceAddressRegionKHR*	hitShaderBindingTableRegion,
4019e5c31af7Sopenharmony_ci						   const VkStridedDeviceAddressRegionKHR*	callableShaderBindingTableRegion,
4020e5c31af7Sopenharmony_ci						   VkDeviceAddress							indirectDeviceAddress)
4021e5c31af7Sopenharmony_ci{
4022e5c31af7Sopenharmony_ci	return cmdTraceRaysIndirectKHR(vk,
4023e5c31af7Sopenharmony_ci								   commandBuffer,
4024e5c31af7Sopenharmony_ci								   raygenShaderBindingTableRegion,
4025e5c31af7Sopenharmony_ci								   missShaderBindingTableRegion,
4026e5c31af7Sopenharmony_ci								   hitShaderBindingTableRegion,
4027e5c31af7Sopenharmony_ci								   callableShaderBindingTableRegion,
4028e5c31af7Sopenharmony_ci								   indirectDeviceAddress);
4029e5c31af7Sopenharmony_ci}
4030e5c31af7Sopenharmony_ci
4031e5c31af7Sopenharmony_cistatic inline void cmdTraceRaysIndirect2KHR (const DeviceInterface&	vk,
4032e5c31af7Sopenharmony_ci											VkCommandBuffer			commandBuffer,
4033e5c31af7Sopenharmony_ci											VkDeviceAddress			indirectDeviceAddress )
4034e5c31af7Sopenharmony_ci{
4035e5c31af7Sopenharmony_ci	DE_ASSERT(indirectDeviceAddress != 0);
4036e5c31af7Sopenharmony_ci
4037e5c31af7Sopenharmony_ci	return vk.cmdTraceRaysIndirect2KHR(commandBuffer, indirectDeviceAddress);
4038e5c31af7Sopenharmony_ci}
4039e5c31af7Sopenharmony_ci
4040e5c31af7Sopenharmony_civoid cmdTraceRaysIndirect2	(const DeviceInterface&	vk,
4041e5c31af7Sopenharmony_ci							 VkCommandBuffer		commandBuffer,
4042e5c31af7Sopenharmony_ci							 VkDeviceAddress		indirectDeviceAddress)
4043e5c31af7Sopenharmony_ci{
4044e5c31af7Sopenharmony_ci	return cmdTraceRaysIndirect2KHR(vk, commandBuffer, indirectDeviceAddress);
4045e5c31af7Sopenharmony_ci}
4046e5c31af7Sopenharmony_ci
4047e5c31af7Sopenharmony_ci#else
4048e5c31af7Sopenharmony_ci
4049e5c31af7Sopenharmony_cideUint32 rayTracingDefineAnything()
4050e5c31af7Sopenharmony_ci{
4051e5c31af7Sopenharmony_ci	return 0;
4052e5c31af7Sopenharmony_ci}
4053e5c31af7Sopenharmony_ci
4054e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
4055e5c31af7Sopenharmony_ci
4056e5c31af7Sopenharmony_ci} // vk
4057