1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2021 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci * Copyright (c) 2021 Valve Corporation.
7e5c31af7Sopenharmony_ci *
8e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
9e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
10e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
11e5c31af7Sopenharmony_ci *
12e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
13e5c31af7Sopenharmony_ci *
14e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
15e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
16e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
18e5c31af7Sopenharmony_ci * limitations under the License.
19e5c31af7Sopenharmony_ci *
20e5c31af7Sopenharmony_ci *//*!
21e5c31af7Sopenharmony_ci * \file
22e5c31af7Sopenharmony_ci * \brief Ray Query Direction Tests
23e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
24e5c31af7Sopenharmony_ci
25e5c31af7Sopenharmony_ci#include "vktRayQueryDirectionTests.hpp"
26e5c31af7Sopenharmony_ci#include "vktTestCase.hpp"
27e5c31af7Sopenharmony_ci
28e5c31af7Sopenharmony_ci#include "vkObjUtil.hpp"
29e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp"
30e5c31af7Sopenharmony_ci#include "vkTypeUtil.hpp"
31e5c31af7Sopenharmony_ci#include "vkBuilderUtil.hpp"
32e5c31af7Sopenharmony_ci#include "vkRayTracingUtil.hpp"
33e5c31af7Sopenharmony_ci#include "vkBufferWithMemory.hpp"
34e5c31af7Sopenharmony_ci#include "vkBarrierUtil.hpp"
35e5c31af7Sopenharmony_ci
36e5c31af7Sopenharmony_ci#include "tcuVector.hpp"
37e5c31af7Sopenharmony_ci#include "tcuMatrix.hpp"
38e5c31af7Sopenharmony_ci
39e5c31af7Sopenharmony_ci#include "deUniquePtr.hpp"
40e5c31af7Sopenharmony_ci#include "deRandom.hpp"
41e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
42e5c31af7Sopenharmony_ci#include "deDefs.hpp"
43e5c31af7Sopenharmony_ci
44e5c31af7Sopenharmony_ci#include <vector>
45e5c31af7Sopenharmony_ci#include <cmath>
46e5c31af7Sopenharmony_ci#include <sstream>
47e5c31af7Sopenharmony_ci#include <utility>
48e5c31af7Sopenharmony_ci#include <algorithm>
49e5c31af7Sopenharmony_ci#include <limits>
50e5c31af7Sopenharmony_ci
51e5c31af7Sopenharmony_cinamespace vkt
52e5c31af7Sopenharmony_ci{
53e5c31af7Sopenharmony_cinamespace RayQuery
54e5c31af7Sopenharmony_ci{
55e5c31af7Sopenharmony_ci
56e5c31af7Sopenharmony_cinamespace
57e5c31af7Sopenharmony_ci{
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_ciusing namespace vk;
60e5c31af7Sopenharmony_ci
61e5c31af7Sopenharmony_ciusing GeometryData = std::vector<tcu::Vec3>;
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ci// Should rays be shot from inside the geometry or not?
64e5c31af7Sopenharmony_cienum class RayOriginType
65e5c31af7Sopenharmony_ci{
66e5c31af7Sopenharmony_ci	OUTSIDE = 0,	// Works with AABBs and triangles.
67e5c31af7Sopenharmony_ci	INSIDE,			// Works with AABBs only.
68e5c31af7Sopenharmony_ci};
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_ci// When rays are shot from the outside, they are expected to cross the geometry.
71e5c31af7Sopenharmony_ci// When shot from the inside, they can end inside, at the edge or outside the geometry.
72e5c31af7Sopenharmony_cienum class RayEndType
73e5c31af7Sopenharmony_ci{
74e5c31af7Sopenharmony_ci	CROSS = 0,		// For RayOriginType::OUTSIDE.
75e5c31af7Sopenharmony_ci	ZERO,			// For RayOriginType::INSIDE.
76e5c31af7Sopenharmony_ci	INSIDE,			// For RayOriginType::INSIDE.
77e5c31af7Sopenharmony_ci	EDGE,			// For RayOriginType::INSIDE.
78e5c31af7Sopenharmony_ci	OUTSIDE,		// For RayOriginType::INSIDE.
79e5c31af7Sopenharmony_ci};
80e5c31af7Sopenharmony_ci
81e5c31af7Sopenharmony_cistruct SpaceObjects
82e5c31af7Sopenharmony_ci{
83e5c31af7Sopenharmony_ci	tcu::Vec3		origin;
84e5c31af7Sopenharmony_ci	tcu::Vec3		direction;
85e5c31af7Sopenharmony_ci	GeometryData	geometry;
86e5c31af7Sopenharmony_ci
87e5c31af7Sopenharmony_ci	SpaceObjects (RayOriginType rayOriginType, VkGeometryTypeKHR geometryType)
88e5c31af7Sopenharmony_ci		: origin	(0.0f, 0.0f, 1.0f)	// Origin of the ray at (0, 0, 1).
89e5c31af7Sopenharmony_ci		, direction	(0.0f, 0.0f, 1.0f)	// Shooting towards (0, 0, 1).
90e5c31af7Sopenharmony_ci		, geometry	()
91e5c31af7Sopenharmony_ci	{
92e5c31af7Sopenharmony_ci		DE_ASSERT(geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR || geometryType == VK_GEOMETRY_TYPE_AABBS_KHR);
93e5c31af7Sopenharmony_ci		DE_ASSERT(rayOriginType == RayOriginType::OUTSIDE || geometryType == VK_GEOMETRY_TYPE_AABBS_KHR);
94e5c31af7Sopenharmony_ci
95e5c31af7Sopenharmony_ci		if (geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR)
96e5c31af7Sopenharmony_ci		{
97e5c31af7Sopenharmony_ci			// Triangle around (0, 0, 5).
98e5c31af7Sopenharmony_ci			geometry.reserve(3u);
99e5c31af7Sopenharmony_ci			geometry.push_back(tcu::Vec3( 0.0f,  0.5f, 5.0f));
100e5c31af7Sopenharmony_ci			geometry.push_back(tcu::Vec3(-0.5f, -0.5f, 5.0f));
101e5c31af7Sopenharmony_ci			geometry.push_back(tcu::Vec3( 0.5f, -0.5f, 5.0f));
102e5c31af7Sopenharmony_ci		}
103e5c31af7Sopenharmony_ci		else
104e5c31af7Sopenharmony_ci		{
105e5c31af7Sopenharmony_ci			// AABB around (0, 0, 5) or with its back side at that distance when shot from the inside.
106e5c31af7Sopenharmony_ci			geometry.reserve(2u);
107e5c31af7Sopenharmony_ci			geometry.push_back(tcu::Vec3(-0.5f, -0.5f, ((rayOriginType == RayOriginType::INSIDE) ? 0.0f : 5.0f)));
108e5c31af7Sopenharmony_ci			geometry.push_back(tcu::Vec3( 0.5f,  0.5f, 5.0f));
109e5c31af7Sopenharmony_ci		}
110e5c31af7Sopenharmony_ci	}
111e5c31af7Sopenharmony_ci
112e5c31af7Sopenharmony_ci	static float getDefaultDistance (void)
113e5c31af7Sopenharmony_ci	{
114e5c31af7Sopenharmony_ci		// Consistent with the Z coordinates of the origin, direction and points in constructors.
115e5c31af7Sopenharmony_ci		return 4.0f;
116e5c31af7Sopenharmony_ci	}
117e5c31af7Sopenharmony_ci
118e5c31af7Sopenharmony_ci	// Calculates distance to geometry edge given the direction scaling factor.
119e5c31af7Sopenharmony_ci	static float getDistanceToEdge (float directionScale)
120e5c31af7Sopenharmony_ci	{
121e5c31af7Sopenharmony_ci		return getDefaultDistance() / directionScale;
122e5c31af7Sopenharmony_ci	}
123e5c31af7Sopenharmony_ci};
124e5c31af7Sopenharmony_ci
125e5c31af7Sopenharmony_ci// Default test tolerance for distance values.
126e5c31af7Sopenharmony_ciconstexpr float kDefaultTolerance = 0.001f;
127e5c31af7Sopenharmony_ci
128e5c31af7Sopenharmony_ci// Calculates appropriate values for Tmin/Tmax given the distance to the geometry edge.
129e5c31af7Sopenharmony_cistd::pair<float, float> calcTminTmax (RayOriginType rayOriginType, RayEndType rayEndType, float distanceToEdge)
130e5c31af7Sopenharmony_ci{
131e5c31af7Sopenharmony_ci	std::pair<float, float> result;
132e5c31af7Sopenharmony_ci
133e5c31af7Sopenharmony_ci	if (rayOriginType == RayOriginType::OUTSIDE)
134e5c31af7Sopenharmony_ci	{
135e5c31af7Sopenharmony_ci		DE_ASSERT(rayEndType == RayEndType::CROSS);
136e5c31af7Sopenharmony_ci		const auto margin = kDefaultTolerance / 2.0f;
137e5c31af7Sopenharmony_ci		result = std::make_pair(de::max(distanceToEdge - margin, 0.0f), distanceToEdge + margin);
138e5c31af7Sopenharmony_ci	}
139e5c31af7Sopenharmony_ci	else
140e5c31af7Sopenharmony_ci	{
141e5c31af7Sopenharmony_ci		result.first = 0.0f;
142e5c31af7Sopenharmony_ci		switch (rayEndType)
143e5c31af7Sopenharmony_ci		{
144e5c31af7Sopenharmony_ci		case RayEndType::ZERO:		result.second = 0.0f;					break;
145e5c31af7Sopenharmony_ci		case RayEndType::INSIDE:	result.second = distanceToEdge / 2.0f;	break;
146e5c31af7Sopenharmony_ci		case RayEndType::EDGE:		result.second = distanceToEdge;			break;
147e5c31af7Sopenharmony_ci		case RayEndType::OUTSIDE:	result.second = distanceToEdge + 1.0f;	break;
148e5c31af7Sopenharmony_ci		default: DE_ASSERT(false); break;
149e5c31af7Sopenharmony_ci		}
150e5c31af7Sopenharmony_ci	}
151e5c31af7Sopenharmony_ci
152e5c31af7Sopenharmony_ci	return result;
153e5c31af7Sopenharmony_ci}
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ci// Get matrix to scale a point with the given scale factor.
156e5c31af7Sopenharmony_citcu::Mat3 getScaleMatrix (float scaleFactor)
157e5c31af7Sopenharmony_ci{
158e5c31af7Sopenharmony_ci	const float scaleDirectionMatrixData[] =
159e5c31af7Sopenharmony_ci	{
160e5c31af7Sopenharmony_ci		scaleFactor,		0.f,			0.f,
161e5c31af7Sopenharmony_ci		0.f,				scaleFactor,	0.f,
162e5c31af7Sopenharmony_ci		0.f,				0.f,			scaleFactor,
163e5c31af7Sopenharmony_ci	};
164e5c31af7Sopenharmony_ci	return tcu::Mat3(scaleDirectionMatrixData);
165e5c31af7Sopenharmony_ci}
166e5c31af7Sopenharmony_ci
167e5c31af7Sopenharmony_ci// Get a matrix to rotate a point around the X and Y axis by the given angles in radians.
168e5c31af7Sopenharmony_citcu::Mat3 getRotationMatrix (float rotationX, float rotationY)
169e5c31af7Sopenharmony_ci{
170e5c31af7Sopenharmony_ci	const float cosA = std::cos(rotationX);
171e5c31af7Sopenharmony_ci	const float sinA = std::sin(rotationX);
172e5c31af7Sopenharmony_ci
173e5c31af7Sopenharmony_ci	const float cosB = std::cos(rotationY);
174e5c31af7Sopenharmony_ci	const float sinB = std::sin(rotationY);
175e5c31af7Sopenharmony_ci
176e5c31af7Sopenharmony_ci	const float rotationMatrixDataX[] =
177e5c31af7Sopenharmony_ci	{
178e5c31af7Sopenharmony_ci		1.0f, 0.0f, 0.0f,
179e5c31af7Sopenharmony_ci		0.0f, cosA,-sinA,
180e5c31af7Sopenharmony_ci		0.0f, sinA, cosA,
181e5c31af7Sopenharmony_ci	};
182e5c31af7Sopenharmony_ci	const tcu::Mat3 rotationMatrixX (rotationMatrixDataX);
183e5c31af7Sopenharmony_ci
184e5c31af7Sopenharmony_ci	const float rotationMatrixDataY[] =
185e5c31af7Sopenharmony_ci	{
186e5c31af7Sopenharmony_ci		cosB, 0.0f,-sinB,
187e5c31af7Sopenharmony_ci		0.0f, 1.0f, 0.0f,
188e5c31af7Sopenharmony_ci		sinB, 0.0f, cosB,
189e5c31af7Sopenharmony_ci	};
190e5c31af7Sopenharmony_ci	const tcu::Mat3 rotationMatrixY (rotationMatrixDataY);
191e5c31af7Sopenharmony_ci
192e5c31af7Sopenharmony_ci	return rotationMatrixX * rotationMatrixY;
193e5c31af7Sopenharmony_ci}
194e5c31af7Sopenharmony_ci
195e5c31af7Sopenharmony_ci// Converts transformation matrix to the expected KHR format.
196e5c31af7Sopenharmony_ciVkTransformMatrixKHR toTransformMatrixKHR (const tcu::Mat3& mat3)
197e5c31af7Sopenharmony_ci{
198e5c31af7Sopenharmony_ci	VkTransformMatrixKHR result;
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ci	deMemset(result.matrix, 0, sizeof(result.matrix));
201e5c31af7Sopenharmony_ci	for (int y = 0; y < 3; ++y)
202e5c31af7Sopenharmony_ci	for (int x = 0; x < 3; ++x)
203e5c31af7Sopenharmony_ci		result.matrix[x][y] = mat3[x][y];
204e5c31af7Sopenharmony_ci
205e5c31af7Sopenharmony_ci	return result;
206e5c31af7Sopenharmony_ci}
207e5c31af7Sopenharmony_ci
208e5c31af7Sopenharmony_cistruct TestParams
209e5c31af7Sopenharmony_ci{
210e5c31af7Sopenharmony_ci	SpaceObjects			spaceObjects;
211e5c31af7Sopenharmony_ci	float					directionScale;
212e5c31af7Sopenharmony_ci	float					rotationX;
213e5c31af7Sopenharmony_ci	float					rotationY;
214e5c31af7Sopenharmony_ci	VkGeometryTypeKHR		geometryType;
215e5c31af7Sopenharmony_ci	bool					useArraysOfPointers;
216e5c31af7Sopenharmony_ci	bool					updateMatrixAfterBuild;
217e5c31af7Sopenharmony_ci	RayOriginType			rayOriginType;
218e5c31af7Sopenharmony_ci	RayEndType				rayEndtype;
219e5c31af7Sopenharmony_ci};
220e5c31af7Sopenharmony_ci
221e5c31af7Sopenharmony_ciclass DirectionTestCase : public vkt::TestCase
222e5c31af7Sopenharmony_ci{
223e5c31af7Sopenharmony_cipublic:
224e5c31af7Sopenharmony_ci							DirectionTestCase		(tcu::TestContext& testCtx, const std::string& name, const TestParams& params);
225e5c31af7Sopenharmony_ci	virtual					~DirectionTestCase		(void) {}
226e5c31af7Sopenharmony_ci
227e5c31af7Sopenharmony_ci	virtual void			checkSupport			(Context& context) const;
228e5c31af7Sopenharmony_ci	virtual void			initPrograms			(vk::SourceCollections& programCollection) const;
229e5c31af7Sopenharmony_ci	virtual TestInstance*	createInstance			(Context& context) const;
230e5c31af7Sopenharmony_ci
231e5c31af7Sopenharmony_ciprotected:
232e5c31af7Sopenharmony_ci	TestParams				m_params;
233e5c31af7Sopenharmony_ci};
234e5c31af7Sopenharmony_ci
235e5c31af7Sopenharmony_ciclass DirectionTestInstance : public vkt::TestInstance
236e5c31af7Sopenharmony_ci{
237e5c31af7Sopenharmony_cipublic:
238e5c31af7Sopenharmony_ci								DirectionTestInstance	(Context& context, const TestParams& params);
239e5c31af7Sopenharmony_ci	virtual						~DirectionTestInstance	(void) {}
240e5c31af7Sopenharmony_ci
241e5c31af7Sopenharmony_ci	virtual tcu::TestStatus		iterate					(void);
242e5c31af7Sopenharmony_ci
243e5c31af7Sopenharmony_ciprotected:
244e5c31af7Sopenharmony_ci	TestParams					m_params;
245e5c31af7Sopenharmony_ci};
246e5c31af7Sopenharmony_ci
247e5c31af7Sopenharmony_ci
248e5c31af7Sopenharmony_ciDirectionTestCase::DirectionTestCase(tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
249e5c31af7Sopenharmony_ci	: vkt::TestCase	(testCtx, name)
250e5c31af7Sopenharmony_ci	, m_params		(params)
251e5c31af7Sopenharmony_ci{}
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_civoid DirectionTestCase::checkSupport (Context& context) const
254e5c31af7Sopenharmony_ci{
255e5c31af7Sopenharmony_ci	context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
256e5c31af7Sopenharmony_ci	context.requireDeviceFunctionality("VK_KHR_ray_query");
257e5c31af7Sopenharmony_ci}
258e5c31af7Sopenharmony_ci
259e5c31af7Sopenharmony_ci// Push constants. They need to match the shaders.
260e5c31af7Sopenharmony_ci// Note: origin and direction will be used as a Vec3. Declaring them as Vec4 eases matching alignments.
261e5c31af7Sopenharmony_cistruct PushConstants
262e5c31af7Sopenharmony_ci{
263e5c31af7Sopenharmony_ci	tcu::Vec4	origin;
264e5c31af7Sopenharmony_ci	tcu::Vec4	direction;
265e5c31af7Sopenharmony_ci	float		tmix;
266e5c31af7Sopenharmony_ci	float		tmax;
267e5c31af7Sopenharmony_ci};
268e5c31af7Sopenharmony_ci
269e5c31af7Sopenharmony_citcu::Vec4 toVec4 (const tcu::Vec3& vec3)
270e5c31af7Sopenharmony_ci{
271e5c31af7Sopenharmony_ci	return tcu::Vec4(vec3.x(), vec3.y(), vec3.z(), 0.0f);
272e5c31af7Sopenharmony_ci}
273e5c31af7Sopenharmony_ci
274e5c31af7Sopenharmony_civoid DirectionTestCase::initPrograms (vk::SourceCollections& programCollection) const
275e5c31af7Sopenharmony_ci{
276e5c31af7Sopenharmony_ci	const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
277e5c31af7Sopenharmony_ci
278e5c31af7Sopenharmony_ci	std::ostringstream comp;
279e5c31af7Sopenharmony_ci	comp
280e5c31af7Sopenharmony_ci		<< "#version 460 core\n"
281e5c31af7Sopenharmony_ci		<< "#extension GL_EXT_ray_query : require\n"
282e5c31af7Sopenharmony_ci		<< "\n"
283e5c31af7Sopenharmony_ci		<< "layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
284e5c31af7Sopenharmony_ci		<< "\n"
285e5c31af7Sopenharmony_ci		<< "layout(set=0, binding=0) uniform accelerationStructureEXT topLevelAS;\n"
286e5c31af7Sopenharmony_ci		<< "layout(set=0, binding=1, std430) buffer OutBuffer { float val; } outBuffer;\n"
287e5c31af7Sopenharmony_ci		// Needs to match the PushConstants struct above.
288e5c31af7Sopenharmony_ci		<< "layout(push_constant, std430) uniform PushConstants {\n"
289e5c31af7Sopenharmony_ci		<< "  vec4 origin;\n"
290e5c31af7Sopenharmony_ci		<< "  vec4 direction;\n"
291e5c31af7Sopenharmony_ci		<< "  float tmin;\n"
292e5c31af7Sopenharmony_ci		<< "  float tmax;\n"
293e5c31af7Sopenharmony_ci		<< "} pc;\n"
294e5c31af7Sopenharmony_ci		<< "\n"
295e5c31af7Sopenharmony_ci		<< "void main()\n"
296e5c31af7Sopenharmony_ci		<< "{\n"
297e5c31af7Sopenharmony_ci		<< "  const uint  cullMask = 0xFF;\n"
298e5c31af7Sopenharmony_ci		<< "  float       outVal   = -10000.0f;\n"
299e5c31af7Sopenharmony_ci		<< "  rayQueryEXT rq;\n"
300e5c31af7Sopenharmony_ci		<< "  rayQueryInitializeEXT(rq, topLevelAS, gl_RayFlagsNoneEXT, cullMask, pc.origin.xyz, pc.tmin, pc.direction.xyz, pc.tmax);\n"
301e5c31af7Sopenharmony_ci		<< "  while (rayQueryProceedEXT(rq)) {\n"
302e5c31af7Sopenharmony_ci		<< "    const uint candidateType = rayQueryGetIntersectionTypeEXT(rq, false);\n"
303e5c31af7Sopenharmony_ci		<< "    if (candidateType == gl_RayQueryCandidateIntersectionTriangleEXT) {\n"
304e5c31af7Sopenharmony_ci		<< "      outVal = rayQueryGetIntersectionTEXT(rq, false);\n"
305e5c31af7Sopenharmony_ci		<< "    }\n"
306e5c31af7Sopenharmony_ci		<< "    else if (candidateType == gl_RayQueryCandidateIntersectionAABBEXT) {\n"
307e5c31af7Sopenharmony_ci		<< "      outVal = pc.tmin;\n"
308e5c31af7Sopenharmony_ci		<< "    }\n"
309e5c31af7Sopenharmony_ci		<< "  }\n"
310e5c31af7Sopenharmony_ci		<< "  outBuffer.val = outVal;\n"
311e5c31af7Sopenharmony_ci		<< "}\n"
312e5c31af7Sopenharmony_ci		;
313e5c31af7Sopenharmony_ci
314e5c31af7Sopenharmony_ci	programCollection.glslSources.add("comp") << glu::ComputeSource(updateRayTracingGLSL(comp.str())) << buildOptions;
315e5c31af7Sopenharmony_ci}
316e5c31af7Sopenharmony_ci
317e5c31af7Sopenharmony_ciTestInstance* DirectionTestCase::createInstance (Context& context) const
318e5c31af7Sopenharmony_ci{
319e5c31af7Sopenharmony_ci	return new DirectionTestInstance(context, m_params);
320e5c31af7Sopenharmony_ci}
321e5c31af7Sopenharmony_ci
322e5c31af7Sopenharmony_ciDirectionTestInstance::DirectionTestInstance (Context& context, const TestParams& params)
323e5c31af7Sopenharmony_ci	: vkt::TestInstance	(context)
324e5c31af7Sopenharmony_ci	, m_params			(params)
325e5c31af7Sopenharmony_ci{}
326e5c31af7Sopenharmony_ci
327e5c31af7Sopenharmony_citcu::TestStatus DirectionTestInstance::iterate (void)
328e5c31af7Sopenharmony_ci{
329e5c31af7Sopenharmony_ci	const auto&	vkd		= m_context.getDeviceInterface();
330e5c31af7Sopenharmony_ci	const auto	device	= m_context.getDevice();
331e5c31af7Sopenharmony_ci	auto&		alloc	= m_context.getDefaultAllocator();
332e5c31af7Sopenharmony_ci	const auto	qIndex	= m_context.getUniversalQueueFamilyIndex();
333e5c31af7Sopenharmony_ci	const auto	queue	= m_context.getUniversalQueue();
334e5c31af7Sopenharmony_ci	const auto	stages	= VK_SHADER_STAGE_COMPUTE_BIT;
335e5c31af7Sopenharmony_ci	const auto	pcSize	= static_cast<deUint32>(sizeof(PushConstants));
336e5c31af7Sopenharmony_ci
337e5c31af7Sopenharmony_ci	const auto	scaleMatrix		= getScaleMatrix(m_params.directionScale);
338e5c31af7Sopenharmony_ci	const auto	rotationMatrix	= getRotationMatrix(m_params.rotationX, m_params.rotationY);
339e5c31af7Sopenharmony_ci	const auto	transformMatrix	= toTransformMatrixKHR(rotationMatrix);
340e5c31af7Sopenharmony_ci
341e5c31af7Sopenharmony_ci	// Command pool and buffer.
342e5c31af7Sopenharmony_ci	const auto cmdPool		= makeCommandPool(vkd, device, qIndex);
343e5c31af7Sopenharmony_ci	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
344e5c31af7Sopenharmony_ci	const auto cmdBuffer	= cmdBufferPtr.get();
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_ci	beginCommandBuffer(vkd, cmdBuffer);
347e5c31af7Sopenharmony_ci
348e5c31af7Sopenharmony_ci	// Build acceleration structures.
349e5c31af7Sopenharmony_ci	auto topLevelAS		= makeTopLevelAccelerationStructure();
350e5c31af7Sopenharmony_ci	auto bottomLevelAS	= makeBottomLevelAccelerationStructure();
351e5c31af7Sopenharmony_ci
352e5c31af7Sopenharmony_ci	const bool							isTriangles		= (m_params.geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR);
353e5c31af7Sopenharmony_ci	const VkGeometryInstanceFlagsKHR	instanceFlags	= (isTriangles ? VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR : 0);
354e5c31af7Sopenharmony_ci
355e5c31af7Sopenharmony_ci	bottomLevelAS->addGeometry(m_params.spaceObjects.geometry, isTriangles, VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR);
356e5c31af7Sopenharmony_ci	bottomLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
357e5c31af7Sopenharmony_ci
358e5c31af7Sopenharmony_ci	de::SharedPtr<BottomLevelAccelerationStructure> blasSharedPtr (bottomLevelAS.release());
359e5c31af7Sopenharmony_ci	topLevelAS->setUseArrayOfPointers(m_params.useArraysOfPointers);
360e5c31af7Sopenharmony_ci	topLevelAS->setUsePPGeometries(m_params.useArraysOfPointers);
361e5c31af7Sopenharmony_ci	topLevelAS->setInstanceCount(1);
362e5c31af7Sopenharmony_ci	{
363e5c31af7Sopenharmony_ci		const auto& initialMatrix = (m_params.updateMatrixAfterBuild ? identityMatrix3x4 : transformMatrix);
364e5c31af7Sopenharmony_ci		topLevelAS->addInstance(blasSharedPtr, initialMatrix, 0, 0xFFu, 0u, instanceFlags);
365e5c31af7Sopenharmony_ci	}
366e5c31af7Sopenharmony_ci	topLevelAS->createAndBuild(vkd, device, cmdBuffer, alloc);
367e5c31af7Sopenharmony_ci	if (m_params.updateMatrixAfterBuild)
368e5c31af7Sopenharmony_ci		topLevelAS->updateInstanceMatrix(vkd, device, 0u, transformMatrix);
369e5c31af7Sopenharmony_ci
370e5c31af7Sopenharmony_ci	// Create output buffer.
371e5c31af7Sopenharmony_ci	const auto			bufferSize			= static_cast<VkDeviceSize>(sizeof(float));
372e5c31af7Sopenharmony_ci	const auto			bufferCreateInfo	= makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
373e5c31af7Sopenharmony_ci	BufferWithMemory	buffer				(vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible);
374e5c31af7Sopenharmony_ci	auto&				bufferAlloc			= buffer.getAllocation();
375e5c31af7Sopenharmony_ci
376e5c31af7Sopenharmony_ci	// Fill output buffer with an initial value.
377e5c31af7Sopenharmony_ci	deMemset(bufferAlloc.getHostPtr(), 0, sizeof(float));
378e5c31af7Sopenharmony_ci	flushAlloc(vkd, device, bufferAlloc);
379e5c31af7Sopenharmony_ci
380e5c31af7Sopenharmony_ci	// Descriptor set layout and pipeline layout.
381e5c31af7Sopenharmony_ci	DescriptorSetLayoutBuilder setLayoutBuilder;
382e5c31af7Sopenharmony_ci	setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, stages);
383e5c31af7Sopenharmony_ci	setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stages);
384e5c31af7Sopenharmony_ci	const auto setLayout = setLayoutBuilder.build(vkd, device);
385e5c31af7Sopenharmony_ci
386e5c31af7Sopenharmony_ci	const auto pcRange = makePushConstantRange(stages, 0u, pcSize);
387e5c31af7Sopenharmony_ci	const auto pipelineLayout = makePipelineLayout(vkd, device, 1u, &setLayout.get(), 1u, &pcRange);
388e5c31af7Sopenharmony_ci
389e5c31af7Sopenharmony_ci	// Descriptor pool and set.
390e5c31af7Sopenharmony_ci	DescriptorPoolBuilder poolBuilder;
391e5c31af7Sopenharmony_ci	poolBuilder.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
392e5c31af7Sopenharmony_ci	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
393e5c31af7Sopenharmony_ci	const auto descriptorPool	= poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
394e5c31af7Sopenharmony_ci	const auto descriptorSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
395e5c31af7Sopenharmony_ci
396e5c31af7Sopenharmony_ci	// Update descriptor set.
397e5c31af7Sopenharmony_ci	{
398e5c31af7Sopenharmony_ci		const VkWriteDescriptorSetAccelerationStructureKHR accelDescInfo =
399e5c31af7Sopenharmony_ci		{
400e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
401e5c31af7Sopenharmony_ci			nullptr,
402e5c31af7Sopenharmony_ci			1u,
403e5c31af7Sopenharmony_ci			topLevelAS.get()->getPtr(),
404e5c31af7Sopenharmony_ci		};
405e5c31af7Sopenharmony_ci
406e5c31af7Sopenharmony_ci		const auto bufferDescInfo = makeDescriptorBufferInfo(buffer.get(), 0ull, VK_WHOLE_SIZE);
407e5c31af7Sopenharmony_ci
408e5c31af7Sopenharmony_ci		DescriptorSetUpdateBuilder updateBuilder;
409e5c31af7Sopenharmony_ci		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelDescInfo);
410e5c31af7Sopenharmony_ci		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferDescInfo);
411e5c31af7Sopenharmony_ci		updateBuilder.update(vkd, device);
412e5c31af7Sopenharmony_ci	}
413e5c31af7Sopenharmony_ci
414e5c31af7Sopenharmony_ci	// Shader module and pipeline.
415e5c31af7Sopenharmony_ci	const auto compModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("comp"), 0);
416e5c31af7Sopenharmony_ci
417e5c31af7Sopenharmony_ci	const VkPipelineShaderStageCreateInfo shaderInfo =
418e5c31af7Sopenharmony_ci	{
419e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//	VkStructureType						sType;
420e5c31af7Sopenharmony_ci		nullptr,												//	const void*							pNext;
421e5c31af7Sopenharmony_ci		0u,														//	VkPipelineShaderStageCreateFlags	flags;
422e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_COMPUTE_BIT,							//	VkShaderStageFlagBits				stage;
423e5c31af7Sopenharmony_ci		compModule.get(),										//	VkShaderModule						module;
424e5c31af7Sopenharmony_ci		"main",													//	const char*							pName;
425e5c31af7Sopenharmony_ci		nullptr,												//	const VkSpecializationInfo*			pSpecializationInfo;
426e5c31af7Sopenharmony_ci	};
427e5c31af7Sopenharmony_ci	const VkComputePipelineCreateInfo pipelineInfo =
428e5c31af7Sopenharmony_ci	{
429e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			//	VkStructureType					sType;
430e5c31af7Sopenharmony_ci		nullptr,												//	const void*						pNext;
431e5c31af7Sopenharmony_ci		0u,														//	VkPipelineCreateFlags			flags;
432e5c31af7Sopenharmony_ci		shaderInfo,												//	VkPipelineShaderStageCreateInfo	stage;
433e5c31af7Sopenharmony_ci		pipelineLayout.get(),									//	VkPipelineLayout				layout;
434e5c31af7Sopenharmony_ci		DE_NULL,												//	VkPipeline						basePipelineHandle;
435e5c31af7Sopenharmony_ci		0,														//	deInt32							basePipelineIndex;
436e5c31af7Sopenharmony_ci	};
437e5c31af7Sopenharmony_ci	const auto pipeline = createComputePipeline(vkd, device, DE_NULL, &pipelineInfo);
438e5c31af7Sopenharmony_ci
439e5c31af7Sopenharmony_ci	// Push constants.
440e5c31af7Sopenharmony_ci	const auto			rotatedOrigin		= m_params.spaceObjects.origin * rotationMatrix;
441e5c31af7Sopenharmony_ci	const auto			finalDirection		= m_params.spaceObjects.direction * scaleMatrix * rotationMatrix;
442e5c31af7Sopenharmony_ci	const auto			distanceToEdge		= SpaceObjects::getDistanceToEdge(m_params.directionScale);
443e5c31af7Sopenharmony_ci	const auto			tMinMax				= calcTminTmax(m_params.rayOriginType, m_params.rayEndtype, distanceToEdge);
444e5c31af7Sopenharmony_ci	const PushConstants	pcData				=
445e5c31af7Sopenharmony_ci	{
446e5c31af7Sopenharmony_ci		toVec4(rotatedOrigin),	//	tcu::Vec4	origin;
447e5c31af7Sopenharmony_ci		toVec4(finalDirection),	//	tcu::Vec4	direction;
448e5c31af7Sopenharmony_ci		tMinMax.first,			//	float		tmix;
449e5c31af7Sopenharmony_ci		tMinMax.second,			//	float		tmax;
450e5c31af7Sopenharmony_ci	};
451e5c31af7Sopenharmony_ci
452e5c31af7Sopenharmony_ci	// Trace rays.
453e5c31af7Sopenharmony_ci	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.get());
454e5c31af7Sopenharmony_ci	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
455e5c31af7Sopenharmony_ci	vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), stages, 0u, pcSize, &pcData);
456e5c31af7Sopenharmony_ci	vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
457e5c31af7Sopenharmony_ci
458e5c31af7Sopenharmony_ci	// Barrier for the output buffer.
459e5c31af7Sopenharmony_ci	const auto bufferBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
460e5c31af7Sopenharmony_ci	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &bufferBarrier, 0u, nullptr, 0u, nullptr);
461e5c31af7Sopenharmony_ci
462e5c31af7Sopenharmony_ci	endCommandBuffer(vkd, cmdBuffer);
463e5c31af7Sopenharmony_ci	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
464e5c31af7Sopenharmony_ci
465e5c31af7Sopenharmony_ci	// Read value back from the buffer.
466e5c31af7Sopenharmony_ci	float bufferValue = 0.0f;
467e5c31af7Sopenharmony_ci	invalidateAlloc(vkd, device, bufferAlloc);
468e5c31af7Sopenharmony_ci	deMemcpy(&bufferValue, bufferAlloc.getHostPtr(), sizeof(bufferValue));
469e5c31af7Sopenharmony_ci
470e5c31af7Sopenharmony_ci	if (m_params.rayEndtype == RayEndType::CROSS)
471e5c31af7Sopenharmony_ci	{
472e5c31af7Sopenharmony_ci		// Shooting from the ouside.
473e5c31af7Sopenharmony_ci		if (de::abs(bufferValue - distanceToEdge) > kDefaultTolerance)
474e5c31af7Sopenharmony_ci		{
475e5c31af7Sopenharmony_ci			std::ostringstream msg;
476e5c31af7Sopenharmony_ci			msg << "Result distance (" << bufferValue << ") differs from expected distance (" << distanceToEdge << ", tolerance " << kDefaultTolerance << ")";
477e5c31af7Sopenharmony_ci			TCU_FAIL(msg.str());
478e5c31af7Sopenharmony_ci		}
479e5c31af7Sopenharmony_ci	}
480e5c31af7Sopenharmony_ci	else
481e5c31af7Sopenharmony_ci	{
482e5c31af7Sopenharmony_ci		// Rays are shot from inside AABBs, rayTMin should be zero and the reported hit distance.
483e5c31af7Sopenharmony_ci		if (bufferValue != 0.0f)
484e5c31af7Sopenharmony_ci		{
485e5c31af7Sopenharmony_ci			std::ostringstream msg;
486e5c31af7Sopenharmony_ci			msg << "Result distance nonzero (" << bufferValue << ")";
487e5c31af7Sopenharmony_ci			TCU_FAIL(msg.str());
488e5c31af7Sopenharmony_ci		}
489e5c31af7Sopenharmony_ci	}
490e5c31af7Sopenharmony_ci
491e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Pass");
492e5c31af7Sopenharmony_ci}
493e5c31af7Sopenharmony_ci
494e5c31af7Sopenharmony_ciusing GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
495e5c31af7Sopenharmony_ci
496e5c31af7Sopenharmony_ci// Generate a list of scaling factors suitable for the tests.
497e5c31af7Sopenharmony_cistd::vector<float> generateScalingFactors (de::Random& rnd)
498e5c31af7Sopenharmony_ci{
499e5c31af7Sopenharmony_ci	const float	kMinScalingFactor			= 0.5f;
500e5c31af7Sopenharmony_ci	const float	kMaxScalingFactor			= 10.0f;
501e5c31af7Sopenharmony_ci	const int	kNumRandomScalingFactors	= 5;
502e5c31af7Sopenharmony_ci
503e5c31af7Sopenharmony_ci	// Scaling factors: 1.0 and some randomly-generated ones.
504e5c31af7Sopenharmony_ci	std::vector<float> scalingFactors;
505e5c31af7Sopenharmony_ci
506e5c31af7Sopenharmony_ci	scalingFactors.reserve(kNumRandomScalingFactors + 1);
507e5c31af7Sopenharmony_ci	scalingFactors.push_back(1.0f);
508e5c31af7Sopenharmony_ci
509e5c31af7Sopenharmony_ci	for (int i = 0; i < kNumRandomScalingFactors; ++i)
510e5c31af7Sopenharmony_ci		scalingFactors.push_back(rnd.getFloat() * (kMaxScalingFactor - kMinScalingFactor) + kMinScalingFactor);
511e5c31af7Sopenharmony_ci
512e5c31af7Sopenharmony_ci	return scalingFactors;
513e5c31af7Sopenharmony_ci}
514e5c31af7Sopenharmony_ci
515e5c31af7Sopenharmony_ci// Generate a list of rotation angles suitable for the tests.
516e5c31af7Sopenharmony_cistd::vector<std::pair<float, float>> generateRotationAngles (de::Random& rnd)
517e5c31af7Sopenharmony_ci{
518e5c31af7Sopenharmony_ci	const float	kPi2				= DE_PI * 2.0f;
519e5c31af7Sopenharmony_ci	const int	kNumRandomRotations	= 4;
520e5c31af7Sopenharmony_ci
521e5c31af7Sopenharmony_ci	// Rotations: 0.0 on both axis and some randomly-generated ones.
522e5c31af7Sopenharmony_ci	std::vector<std::pair<float, float>> rotationAngles;
523e5c31af7Sopenharmony_ci
524e5c31af7Sopenharmony_ci	rotationAngles.reserve(kNumRandomRotations + 1);
525e5c31af7Sopenharmony_ci	rotationAngles.push_back(std::make_pair(0.0f, 0.0f));
526e5c31af7Sopenharmony_ci
527e5c31af7Sopenharmony_ci	for (int i = 0; i < kNumRandomRotations; ++i)
528e5c31af7Sopenharmony_ci		rotationAngles.push_back(std::make_pair(rnd.getFloat() * kPi2, rnd.getFloat() * kPi2));
529e5c31af7Sopenharmony_ci
530e5c31af7Sopenharmony_ci	return rotationAngles;
531e5c31af7Sopenharmony_ci}
532e5c31af7Sopenharmony_ci
533e5c31af7Sopenharmony_ci} // anonymous
534e5c31af7Sopenharmony_ci
535e5c31af7Sopenharmony_citcu::TestCaseGroup*	createDirectionLengthTests (tcu::TestContext& testCtx)
536e5c31af7Sopenharmony_ci{
537e5c31af7Sopenharmony_ci	// Test direction vector length when using ray queries
538e5c31af7Sopenharmony_ci	GroupPtr directionGroup (new tcu::TestCaseGroup(testCtx, "direction_length"));
539e5c31af7Sopenharmony_ci
540e5c31af7Sopenharmony_ci	struct
541e5c31af7Sopenharmony_ci	{
542e5c31af7Sopenharmony_ci		VkGeometryTypeKHR		geometryType;
543e5c31af7Sopenharmony_ci		const char*				name;
544e5c31af7Sopenharmony_ci	} geometryTypes[] =
545e5c31af7Sopenharmony_ci	{
546e5c31af7Sopenharmony_ci		{ VK_GEOMETRY_TYPE_TRIANGLES_KHR,	"triangles"	},
547e5c31af7Sopenharmony_ci		{ VK_GEOMETRY_TYPE_AABBS_KHR,		"aabbs"		},
548e5c31af7Sopenharmony_ci	};
549e5c31af7Sopenharmony_ci
550e5c31af7Sopenharmony_ci	de::Random	rnd(1614686501u);
551e5c31af7Sopenharmony_ci	deUint32	caseCounter = 0u;
552e5c31af7Sopenharmony_ci
553e5c31af7Sopenharmony_ci	// Scaling factors: 1.0 and some randomly-generated ones.
554e5c31af7Sopenharmony_ci	// Scaling factors and rotation angles.
555e5c31af7Sopenharmony_ci	const auto scalingFactors = generateScalingFactors(rnd);
556e5c31af7Sopenharmony_ci	const auto rotationAngles = generateRotationAngles(rnd);
557e5c31af7Sopenharmony_ci
558e5c31af7Sopenharmony_ci	for (int geometryTypeIdx = 0; geometryTypeIdx < DE_LENGTH_OF_ARRAY(geometryTypes); ++geometryTypeIdx)
559e5c31af7Sopenharmony_ci	{
560e5c31af7Sopenharmony_ci		const auto& gType = geometryTypes[geometryTypeIdx];
561e5c31af7Sopenharmony_ci
562e5c31af7Sopenharmony_ci		GroupPtr geomGroup (new tcu::TestCaseGroup(testCtx, gType.name));
563e5c31af7Sopenharmony_ci
564e5c31af7Sopenharmony_ci		for (size_t scalingIdx = 0; scalingIdx < scalingFactors.size(); ++scalingIdx)
565e5c31af7Sopenharmony_ci		{
566e5c31af7Sopenharmony_ci			const auto scale		= scalingFactors[scalingIdx];
567e5c31af7Sopenharmony_ci			const auto scaleName	= "scaling_factor_" + de::toString(scalingIdx);
568e5c31af7Sopenharmony_ci			GroupPtr factorGroup (new tcu::TestCaseGroup(testCtx, scaleName.c_str()));
569e5c31af7Sopenharmony_ci
570e5c31af7Sopenharmony_ci			for (size_t rotationIdx = 0; rotationIdx < rotationAngles.size(); ++rotationIdx)
571e5c31af7Sopenharmony_ci			{
572e5c31af7Sopenharmony_ci				const auto angles		= rotationAngles[rotationIdx];
573e5c31af7Sopenharmony_ci				const auto angleName	= "rotation_" + de::toString(rotationIdx);
574e5c31af7Sopenharmony_ci				const auto geometryType	= gType.geometryType;
575e5c31af7Sopenharmony_ci				const auto rayOrigType	= RayOriginType::OUTSIDE;
576e5c31af7Sopenharmony_ci				const auto rayEndType	= RayEndType::CROSS;
577e5c31af7Sopenharmony_ci
578e5c31af7Sopenharmony_ci				SpaceObjects spaceObjects(rayOrigType, geometryType);
579e5c31af7Sopenharmony_ci
580e5c31af7Sopenharmony_ci				TestParams params =
581e5c31af7Sopenharmony_ci				{
582e5c31af7Sopenharmony_ci					spaceObjects,				//		SpaceObjects			spaceObjects;
583e5c31af7Sopenharmony_ci					scale,						//		float					directionScale;
584e5c31af7Sopenharmony_ci					angles.first,				//		float					rotationX;
585e5c31af7Sopenharmony_ci					angles.second,				//		float					rotationY;
586e5c31af7Sopenharmony_ci					geometryType,				//		VkGeometryTypeKHR		geometryType;
587e5c31af7Sopenharmony_ci					// Use arrays of pointers when building the TLAS in every other test.
588e5c31af7Sopenharmony_ci					(caseCounter % 2u == 0u),	//		bool					useArraysOfPointers;
589e5c31af7Sopenharmony_ci					// Sometimes, update matrix after building the lop level AS and before submitting the command buffer.
590e5c31af7Sopenharmony_ci					(caseCounter % 3u == 0u),	//		bool					updateMatrixAfterBuild;
591e5c31af7Sopenharmony_ci					rayOrigType,				//		RayOriginType			rayOriginType;
592e5c31af7Sopenharmony_ci					rayEndType,					//		RayEndType				rayEndType;
593e5c31af7Sopenharmony_ci				};
594e5c31af7Sopenharmony_ci				++caseCounter;
595e5c31af7Sopenharmony_ci
596e5c31af7Sopenharmony_ci				factorGroup->addChild(new DirectionTestCase(testCtx, angleName, params));
597e5c31af7Sopenharmony_ci			}
598e5c31af7Sopenharmony_ci
599e5c31af7Sopenharmony_ci			geomGroup->addChild(factorGroup.release());
600e5c31af7Sopenharmony_ci		}
601e5c31af7Sopenharmony_ci
602e5c31af7Sopenharmony_ci		directionGroup->addChild(geomGroup.release());
603e5c31af7Sopenharmony_ci	}
604e5c31af7Sopenharmony_ci
605e5c31af7Sopenharmony_ci	return directionGroup.release();
606e5c31af7Sopenharmony_ci}
607e5c31af7Sopenharmony_ci
608e5c31af7Sopenharmony_citcu::TestCaseGroup*	createInsideAABBsTests (tcu::TestContext& testCtx)
609e5c31af7Sopenharmony_ci{
610e5c31af7Sopenharmony_ci	GroupPtr insideAABBsGroup (new tcu::TestCaseGroup(testCtx, "inside_aabbs", "Test shooting rays that start inside AABBs"));
611e5c31af7Sopenharmony_ci
612e5c31af7Sopenharmony_ci	struct
613e5c31af7Sopenharmony_ci	{
614e5c31af7Sopenharmony_ci		RayEndType				rayEndType;
615e5c31af7Sopenharmony_ci		const char*				name;
616e5c31af7Sopenharmony_ci	} rayEndCases[] =
617e5c31af7Sopenharmony_ci	{
618e5c31af7Sopenharmony_ci		{	RayEndType::ZERO,			"tmax_zero"	},
619e5c31af7Sopenharmony_ci		{	RayEndType::INSIDE,			"inside"	},
620e5c31af7Sopenharmony_ci		{	RayEndType::EDGE,			"edge"		},
621e5c31af7Sopenharmony_ci		{	RayEndType::OUTSIDE,		"outside"	},
622e5c31af7Sopenharmony_ci	};
623e5c31af7Sopenharmony_ci
624e5c31af7Sopenharmony_ci	de::Random rnd(1621948244u);
625e5c31af7Sopenharmony_ci
626e5c31af7Sopenharmony_ci	// Scaling factors: 1.0 and some randomly-generated ones.
627e5c31af7Sopenharmony_ci	// Scaling factors and rotation angles.
628e5c31af7Sopenharmony_ci	const auto scalingFactors = generateScalingFactors(rnd);
629e5c31af7Sopenharmony_ci	const auto rotationAngles = generateRotationAngles(rnd);
630e5c31af7Sopenharmony_ci
631e5c31af7Sopenharmony_ci	for (int rayEndCaseIdx = 0; rayEndCaseIdx < DE_LENGTH_OF_ARRAY(rayEndCases); ++rayEndCaseIdx)
632e5c31af7Sopenharmony_ci	{
633e5c31af7Sopenharmony_ci		const auto&			rayEndCase	= rayEndCases[rayEndCaseIdx];
634e5c31af7Sopenharmony_ci		const std::string	rayEndName	= std::string("ray_end_") + rayEndCase.name;
635e5c31af7Sopenharmony_ci		GroupPtr			rayEndGroup	(new tcu::TestCaseGroup(testCtx, rayEndName.c_str()));
636e5c31af7Sopenharmony_ci
637e5c31af7Sopenharmony_ci		for (size_t scalingIdx = 0; scalingIdx < scalingFactors.size(); ++scalingIdx)
638e5c31af7Sopenharmony_ci		{
639e5c31af7Sopenharmony_ci			const auto scale		= scalingFactors[scalingIdx];
640e5c31af7Sopenharmony_ci			const auto scaleName	= "scaling_factor_" + de::toString(scalingIdx);
641e5c31af7Sopenharmony_ci			GroupPtr factorGroup (new tcu::TestCaseGroup(testCtx, scaleName.c_str()));
642e5c31af7Sopenharmony_ci
643e5c31af7Sopenharmony_ci			for (size_t rotationIdx = 0; rotationIdx < rotationAngles.size(); ++rotationIdx)
644e5c31af7Sopenharmony_ci			{
645e5c31af7Sopenharmony_ci				const auto angles		= rotationAngles[rotationIdx];
646e5c31af7Sopenharmony_ci				const auto angleName	= "rotation_" + de::toString(rotationIdx);
647e5c31af7Sopenharmony_ci				const auto geometryType	= VK_GEOMETRY_TYPE_AABBS_KHR;
648e5c31af7Sopenharmony_ci				const auto rayOrigType	= RayOriginType::INSIDE;
649e5c31af7Sopenharmony_ci
650e5c31af7Sopenharmony_ci				SpaceObjects spaceObjects(rayOrigType, geometryType);
651e5c31af7Sopenharmony_ci
652e5c31af7Sopenharmony_ci				TestParams params =
653e5c31af7Sopenharmony_ci				{
654e5c31af7Sopenharmony_ci					spaceObjects,			//		SpaceObjects			spaceObjects;
655e5c31af7Sopenharmony_ci					scale,					//		float					directionScale;
656e5c31af7Sopenharmony_ci					angles.first,			//		float					rotationX;
657e5c31af7Sopenharmony_ci					angles.second,			//		float					rotationY;
658e5c31af7Sopenharmony_ci					geometryType,			//		VkGeometryTypeKHR		geometryType;
659e5c31af7Sopenharmony_ci					false,					//		bool					useArraysOfPointers;
660e5c31af7Sopenharmony_ci					false,					//		bool					updateMatrixAfterBuild;
661e5c31af7Sopenharmony_ci					rayOrigType,			//		RayOriginType			rayOriginType;
662e5c31af7Sopenharmony_ci					rayEndCase.rayEndType,	//		RayEndType				rayEndType;
663e5c31af7Sopenharmony_ci				};
664e5c31af7Sopenharmony_ci
665e5c31af7Sopenharmony_ci				factorGroup->addChild(new DirectionTestCase(testCtx, angleName, params));
666e5c31af7Sopenharmony_ci			}
667e5c31af7Sopenharmony_ci
668e5c31af7Sopenharmony_ci			rayEndGroup->addChild(factorGroup.release());
669e5c31af7Sopenharmony_ci		}
670e5c31af7Sopenharmony_ci
671e5c31af7Sopenharmony_ci		insideAABBsGroup->addChild(rayEndGroup.release());
672e5c31af7Sopenharmony_ci	}
673e5c31af7Sopenharmony_ci
674e5c31af7Sopenharmony_ci	return insideAABBsGroup.release();
675e5c31af7Sopenharmony_ci}
676e5c31af7Sopenharmony_ci
677e5c31af7Sopenharmony_ci} // RayQuery
678e5c31af7Sopenharmony_ci} // vkt
679