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