1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2020 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Test procedural geometry with complex bouding box sets 22 *//*--------------------------------------------------------------------*/ 23 24#include "vktRayQueryProceduralGeometryTests.hpp" 25#include "vkDefs.hpp" 26#include "vktTestCase.hpp" 27#include "vktTestGroupUtil.hpp" 28#include "vkCmdUtil.hpp" 29#include "vkObjUtil.hpp" 30#include "vkBuilderUtil.hpp" 31#include "vkBarrierUtil.hpp" 32#include "vkBufferWithMemory.hpp" 33#include "vkImageWithMemory.hpp" 34#include "vkTypeUtil.hpp" 35#include "vkImageUtil.hpp" 36#include "vkRayTracingUtil.hpp" 37#include "tcuVectorUtil.hpp" 38#include "tcuTexture.hpp" 39#include "tcuTestLog.hpp" 40#include "tcuImageCompare.hpp" 41#include "tcuFloat.hpp" 42 43namespace vkt 44{ 45namespace RayQuery 46{ 47namespace 48{ 49using namespace vk; 50using namespace vkt; 51 52enum class TestType 53{ 54 OBJECT_BEHIND_BOUNDING_BOX = 0, 55 TRIANGLE_IN_BETWEEN 56}; 57 58class RayQueryProceduralGeometryTestBase : public TestInstance 59{ 60public: 61 62 RayQueryProceduralGeometryTestBase (Context& context); 63 ~RayQueryProceduralGeometryTestBase (void) = default; 64 65 tcu::TestStatus iterate (void) override; 66 67protected: 68 69 virtual void setupAccelerationStructures() = 0; 70 71private: 72 73 VkWriteDescriptorSetAccelerationStructureKHR makeASWriteDescriptorSet (const VkAccelerationStructureKHR* pAccelerationStructure); 74 void clearBuffer (de::SharedPtr<BufferWithMemory> buffer, VkDeviceSize bufferSize); 75 76protected: 77 78 Move<VkCommandPool> m_cmdPool; 79 Move<VkCommandBuffer> m_cmdBuffer; 80 81 std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > m_blasVect; 82 de::SharedPtr<TopLevelAccelerationStructure> m_referenceTLAS; 83 de::SharedPtr<TopLevelAccelerationStructure> m_resultTLAS; 84}; 85 86RayQueryProceduralGeometryTestBase::RayQueryProceduralGeometryTestBase(Context& context) 87 : vkt::TestInstance (context) 88 , m_referenceTLAS (makeTopLevelAccelerationStructure().release()) 89 , m_resultTLAS (makeTopLevelAccelerationStructure().release()) 90{ 91} 92 93tcu::TestStatus RayQueryProceduralGeometryTestBase::iterate(void) 94{ 95 const DeviceInterface& vkd = m_context.getDeviceInterface(); 96 const VkDevice device = m_context.getDevice(); 97 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 98 const VkQueue queue = m_context.getUniversalQueue(); 99 Allocator& allocator = m_context.getDefaultAllocator(); 100 const deUint32 imageSize = 64u; 101 102 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder() 103 .addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 2u) 104 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u) 105 .build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u); 106 107 Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder() 108 .addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_COMPUTE_BIT) // as with single/four aabb's 109 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) // ssbo with result/reference values 110 .build(vkd, device); 111 112 const Move<VkDescriptorSet> referenceDescriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout); 113 const Move<VkDescriptorSet> resultDescriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout); 114 115 const VkDeviceSize resultBufferSize = imageSize * imageSize * sizeof(int); 116 const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT); 117 de::SharedPtr<BufferWithMemory> referenceBuffer = de::SharedPtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible)); 118 de::SharedPtr<BufferWithMemory> resultBuffer = de::SharedPtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible)); 119 120 Move<VkShaderModule> shaderModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("comp"), 0u); 121 const Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get()); 122 const VkComputePipelineCreateInfo pipelineCreateInfo 123 { 124 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType 125 DE_NULL, // const void* pNext 126 0u, // VkPipelineCreateFlags flags 127 { // VkPipelineShaderStageCreateInfo stage 128 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 129 DE_NULL, 130 (VkPipelineShaderStageCreateFlags)0, 131 VK_SHADER_STAGE_COMPUTE_BIT, 132 *shaderModule, 133 "main", 134 DE_NULL 135 }, 136 *pipelineLayout, // VkPipelineLayout layout 137 DE_NULL, // VkPipeline basePipelineHandle 138 0, // deInt32 basePipelineIndex 139 }; 140 Move<VkPipeline> pipeline = createComputePipeline(vkd, device, DE_NULL, &pipelineCreateInfo); 141 142 m_cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex); 143 m_cmdBuffer = allocateCommandBuffer(vkd, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 144 145 // clear result and reference buffers 146 clearBuffer(resultBuffer, resultBufferSize); 147 clearBuffer(referenceBuffer, resultBufferSize); 148 149 beginCommandBuffer(vkd, *m_cmdBuffer, 0u); 150 { 151 setupAccelerationStructures(); 152 153 // update descriptor sets 154 { 155 typedef DescriptorSetUpdateBuilder::Location DSL; 156 157 const VkWriteDescriptorSetAccelerationStructureKHR referenceAS = makeASWriteDescriptorSet(m_referenceTLAS->getPtr()); 158 const VkDescriptorBufferInfo referenceSSBO = makeDescriptorBufferInfo(**referenceBuffer, 0u, VK_WHOLE_SIZE); 159 DescriptorSetUpdateBuilder() 160 .writeSingle(*referenceDescriptorSet, DSL::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &referenceAS) 161 .writeSingle(*referenceDescriptorSet, DSL::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &referenceSSBO) 162 .update(vkd, device); 163 164 const VkWriteDescriptorSetAccelerationStructureKHR resultAS = makeASWriteDescriptorSet(m_resultTLAS->getPtr()); 165 const VkDescriptorBufferInfo resultSSBO = makeDescriptorBufferInfo(**resultBuffer, 0u, VK_WHOLE_SIZE); 166 DescriptorSetUpdateBuilder() 167 .writeSingle(*resultDescriptorSet, DSL::binding(0u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &resultAS) 168 .writeSingle(*resultDescriptorSet, DSL::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultSSBO) 169 .update(vkd, device); 170 } 171 172 // wait for data transfers 173 const VkMemoryBarrier bufferUploadBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); 174 cmdPipelineMemoryBarrier(vkd, *m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, &bufferUploadBarrier, 1u); 175 176 // wait for as build 177 const VkMemoryBarrier asBuildBarrier = makeMemoryBarrier(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, VK_ACCESS_SHADER_READ_BIT); 178 cmdPipelineMemoryBarrier(vkd, *m_cmdBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, &asBuildBarrier, 1u); 179 180 vkd.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); 181 182 // generate reference 183 vkd.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1, &referenceDescriptorSet.get(), 0, DE_NULL); 184 vkd.cmdDispatch(*m_cmdBuffer, imageSize, imageSize, 1); 185 186 // generate result 187 vkd.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1, &resultDescriptorSet.get(), 0, DE_NULL); 188 vkd.cmdDispatch(*m_cmdBuffer, imageSize, imageSize, 1); 189 190 const VkMemoryBarrier postTraceMemoryBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT); 191 cmdPipelineMemoryBarrier(vkd, *m_cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTraceMemoryBarrier); 192 } 193 endCommandBuffer(vkd, *m_cmdBuffer); 194 195 submitCommandsAndWait(vkd, device, queue, m_cmdBuffer.get()); 196 197 // verify result buffer 198 auto referenceAllocation = referenceBuffer->getAllocation(); 199 invalidateMappedMemoryRange(vkd, device, referenceAllocation.getMemory(), referenceAllocation.getOffset(), resultBufferSize); 200 201 auto resultAllocation = resultBuffer->getAllocation(); 202 invalidateMappedMemoryRange(vkd, device, resultAllocation.getMemory(), resultAllocation.getOffset(), resultBufferSize); 203 204 tcu::TextureFormat imageFormat (vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM)); 205 tcu::PixelBufferAccess referenceAccess (imageFormat, imageSize, imageSize, 1, referenceAllocation.getHostPtr()); 206 tcu::PixelBufferAccess resultAccess (imageFormat, imageSize, imageSize, 1, resultAllocation.getHostPtr()); 207 208 if (tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_EVERYTHING)) 209 return tcu::TestStatus::pass("Pass"); 210 return tcu::TestStatus::fail("Fail"); 211} 212 213VkWriteDescriptorSetAccelerationStructureKHR RayQueryProceduralGeometryTestBase::makeASWriteDescriptorSet(const VkAccelerationStructureKHR* pAccelerationStructure) 214{ 215 return 216 { 217 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType 218 DE_NULL, // const void* pNext 219 1u, // deUint32 accelerationStructureCount 220 pAccelerationStructure // const VkAccelerationStructureKHR* pAccelerationStructures 221 }; 222} 223 224void RayQueryProceduralGeometryTestBase::clearBuffer(de::SharedPtr<BufferWithMemory> buffer, VkDeviceSize bufferSize) 225{ 226 const DeviceInterface& vkd = m_context.getDeviceInterface(); 227 const VkDevice device = m_context.getDevice(); 228 auto& bufferAlloc = buffer->getAllocation(); 229 void* bufferPtr = bufferAlloc.getHostPtr(); 230 231 deMemset(bufferPtr, 1, static_cast<size_t>(bufferSize)); 232 vk::flushAlloc(vkd, device, bufferAlloc); 233} 234 235class ObjectBehindBoundingBoxInstance : public RayQueryProceduralGeometryTestBase 236{ 237public: 238 239 ObjectBehindBoundingBoxInstance(Context& context); 240 void setupAccelerationStructures() override; 241}; 242 243ObjectBehindBoundingBoxInstance::ObjectBehindBoundingBoxInstance(Context& context) 244 : RayQueryProceduralGeometryTestBase(context) 245{ 246} 247 248void ObjectBehindBoundingBoxInstance::setupAccelerationStructures() 249{ 250 const DeviceInterface& vkd = m_context.getDeviceInterface(); 251 const VkDevice device = m_context.getDevice(); 252 Allocator& allocator = m_context.getDefaultAllocator(); 253 254 // build reference acceleration structure - single aabb big enough to fit whole procedural geometry 255 de::SharedPtr<BottomLevelAccelerationStructure> referenceBLAS(makeBottomLevelAccelerationStructure().release()); 256 referenceBLAS->setGeometryData( 257 { 258 { 0.0, 0.0, -64.0 }, 259 { 64.0, 64.0, -16.0 }, 260 }, 261 false, 262 0 263 ); 264 referenceBLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator); 265 m_blasVect.push_back(referenceBLAS); 266 267 m_referenceTLAS->setInstanceCount(1); 268 m_referenceTLAS->addInstance(m_blasVect.back()); 269 m_referenceTLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator); 270 271 // build result acceleration structure - wall of 4 aabb's and generated object is actualy behind it (as it is just 1.0 unit thick) 272 de::SharedPtr<BottomLevelAccelerationStructure> resultBLAS(makeBottomLevelAccelerationStructure().release()); 273 resultBLAS->setGeometryData( 274 { 275 { 0.0, 0.0, 0.0 }, // | | 276 { 32.0, 32.0, 1.0 }, // |* | 277 { 32.0, 0.0, 0.0 }, // | | 278 { 64.0, 32.0, 1.0 }, // | *| 279 { 0.0, 32.0, 0.0 }, // |* | 280 { 32.0, 64.0, 1.0 }, // | | 281 { 32.0, 32.0, 0.0 }, // | *| 282 { 64.0, 64.0, 1.0 }, // | | 283 }, 284 false, 285 0 286 ); 287 resultBLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator); 288 m_blasVect.push_back(resultBLAS); 289 290 m_resultTLAS->setInstanceCount(1); 291 m_resultTLAS->addInstance(m_blasVect.back()); 292 m_resultTLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator); 293} 294 295class TriangleInBeteenInstance : public RayQueryProceduralGeometryTestBase 296{ 297public: 298 299 TriangleInBeteenInstance(Context& context); 300 void setupAccelerationStructures() override; 301}; 302 303TriangleInBeteenInstance::TriangleInBeteenInstance(Context& context) 304 : RayQueryProceduralGeometryTestBase(context) 305{ 306} 307 308void TriangleInBeteenInstance::setupAccelerationStructures() 309{ 310 const DeviceInterface& vkd = m_context.getDeviceInterface(); 311 const VkDevice device = m_context.getDevice(); 312 Allocator& allocator = m_context.getDefaultAllocator(); 313 314 de::SharedPtr<BottomLevelAccelerationStructure> triangleBLAS(makeBottomLevelAccelerationStructure().release()); 315 triangleBLAS->setGeometryData( 316 { 317 { 16.0, 16.0, -8.0 }, 318 { 56.0, 32.0, -8.0 }, 319 { 32.0, 48.0, -8.0 }, 320 }, 321 true, 322 VK_GEOMETRY_OPAQUE_BIT_KHR 323 ); 324 triangleBLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator); 325 m_blasVect.push_back(triangleBLAS); 326 327 de::SharedPtr<BottomLevelAccelerationStructure> fullElipsoidBLAS(makeBottomLevelAccelerationStructure().release()); 328 fullElipsoidBLAS->setGeometryData( 329 { 330 { 0.0, 0.0, -64.0 }, 331 { 64.0, 64.0, -16.0 }, 332 }, 333 false, 334 0 335 ); 336 fullElipsoidBLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator); 337 m_blasVect.push_back(fullElipsoidBLAS); 338 339 // build reference acceleration structure - triangle and a single aabb big enough to fit whole procedural geometry 340 m_referenceTLAS->setInstanceCount(2); 341 m_referenceTLAS->addInstance(fullElipsoidBLAS); 342 m_referenceTLAS->addInstance(triangleBLAS); 343 m_referenceTLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator); 344 345 de::SharedPtr<BottomLevelAccelerationStructure> elipsoidWallBLAS(makeBottomLevelAccelerationStructure().release()); 346 elipsoidWallBLAS->setGeometryData( 347 { 348 { 0.0, 0.0, 0.0 }, // |* | 349 { 20.0, 64.0, 1.0 }, 350 { 20.0, 0.0, 0.0 }, // | * | 351 { 44.0, 64.0, 1.0 }, 352 { 44.0, 0.0, 0.0 }, // | *| 353 { 64.0, 64.0, 1.0 }, 354 }, 355 false, 356 0 357 ); 358 elipsoidWallBLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator); 359 m_blasVect.push_back(elipsoidWallBLAS); 360 361 // build result acceleration structure - triangle and a three aabb's (they are in front of triangle but generate intersections behind it) 362 m_resultTLAS->setInstanceCount(2); 363 m_resultTLAS->addInstance(elipsoidWallBLAS); 364 m_resultTLAS->addInstance(triangleBLAS); 365 m_resultTLAS->createAndBuild(vkd, device, *m_cmdBuffer, allocator); 366} 367 368class RayQueryProceduralGeometryTestCase : public TestCase 369{ 370public: 371 RayQueryProceduralGeometryTestCase (tcu::TestContext& context, const char* name, TestType testType); 372 ~RayQueryProceduralGeometryTestCase (void) = default; 373 374 void checkSupport (Context& context) const override; 375 void initPrograms (SourceCollections& programCollection) const override; 376 TestInstance* createInstance (Context& context) const override; 377 378protected: 379 TestType m_testType; 380}; 381 382RayQueryProceduralGeometryTestCase::RayQueryProceduralGeometryTestCase(tcu::TestContext& context, const char* name, TestType testType) 383 : TestCase (context, name) 384 , m_testType (testType) 385{ 386} 387 388void RayQueryProceduralGeometryTestCase::checkSupport(Context& context) const 389{ 390 context.requireDeviceFunctionality("VK_KHR_acceleration_structure"); 391 context.requireDeviceFunctionality("VK_KHR_ray_query"); 392 393 if (!context.getRayQueryFeatures().rayQuery) 394 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayQueryFeaturesKHR.rayQuery"); 395 396 if (!context.getAccelerationStructureFeatures().accelerationStructure) 397 TCU_THROW(TestError, "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure"); 398} 399 400void RayQueryProceduralGeometryTestCase::initPrograms(SourceCollections& programCollection) const 401{ 402 const vk::ShaderBuildOptions glslBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true); 403 404 std::string compSource = 405 "#version 460 core\n" 406 "#extension GL_EXT_ray_query : require\n" 407 408 "layout(set = 0, binding = 0) uniform accelerationStructureEXT tlas;\n" 409 "layout(set = 0, binding = 1, std430) writeonly buffer Result {\n" 410 " int value[];\n" 411 "} result;\n" 412 413 "void main()\n" 414 "{\n" 415 " float tmin = 0.0;\n" 416 " float tmax = 50.0;\n" 417 " vec3 rayOrigin = vec3(float(gl_GlobalInvocationID.x) + 0.5f, float(gl_GlobalInvocationID.y) + 0.5f, 2.0);\n" 418 " vec3 rayDir = vec3(0.0,0.0,-1.0);\n" 419 " uint resultIndex = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * gl_NumWorkGroups.x;\n" 420 " int payload = 30;\n" 421 422 // elipsoid center and radii 423 " vec3 elipsoidOrigin = vec3(32.0, 32.0, -30.0);\n" 424 " vec3 elipsoidRadii = vec3(30.0, 15.0, 5.0);\n" 425 426 " rayQueryEXT rq;\n" 427 " rayQueryInitializeEXT(rq, tlas, gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, rayOrigin, tmin, rayDir, tmax);\n" 428 429 " while (rayQueryProceedEXT(rq))\n" 430 " {\n" 431 " uint intersectionType = rayQueryGetIntersectionTypeEXT(rq, false);\n" 432 " if (intersectionType == gl_RayQueryCandidateIntersectionAABBEXT)\n" 433 " {\n" 434 // simplify to ray sphere intersection 435 " vec3 eliDir = rayOrigin - elipsoidOrigin;\n" 436 " vec3 eliS = eliDir / elipsoidRadii;\n" 437 " vec3 rayS = rayDir / elipsoidRadii;\n" 438 439 " float a = dot(rayS, rayS);\n" 440 " float b = dot(eliS, rayS);\n" 441 " float c = dot(eliS, eliS);\n" 442 " float h = b * b - a * (c - 1.0);\n" 443 " if (h >= 0.0)\n" 444 " rayQueryGenerateIntersectionEXT(rq, (-b - sqrt(h)) / a);\n" 445 " }\n" 446 " else if (intersectionType == gl_RayQueryCandidateIntersectionTriangleEXT)\n" 447 " {\n" 448 " payload = 250;\n" 449 " rayQueryConfirmIntersectionEXT(rq);\n" 450 " }\n" 451 " }\n" 452 " if (rayQueryGetIntersectionTypeEXT(rq, true) != gl_RayQueryCommittedIntersectionNoneEXT)\n" 453 " {\n" 454 " int instanceId = rayQueryGetIntersectionInstanceIdEXT(rq, true);\n" 455 " if (instanceId > -1)\n" 456 " {\n" 457 " float hitT = rayQueryGetIntersectionTEXT(rq, true);\n" 458 " vec3 lightDir = normalize(vec3(0.0, 0.0, 1.0));\n" 459 " vec3 hitPos = rayOrigin + hitT * rayDir;\n" 460 " vec3 hitNormal = normalize((hitPos - elipsoidOrigin) / elipsoidRadii);\n" 461 " payload = 50 + int(200.0 * clamp(dot(hitNormal, lightDir), 0.0, 1.0));\n" 462 " }\n" 463 " }\n" 464 465 // to be able to display result in cherry this is interpreated as r8g8b8a8 during verification 466 // we are using only red but we need to add alpha (note: r and a may be swapped depending on endianness) 467 " result.value[resultIndex] = payload + 0xFF000000;\n" 468 "};\n"; 469 programCollection.glslSources.add("comp") << glu::ComputeSource(compSource) << glslBuildOptions; 470} 471 472TestInstance* RayQueryProceduralGeometryTestCase::createInstance(Context& context) const 473{ 474 if (m_testType == TestType::TRIANGLE_IN_BETWEEN) 475 return new TriangleInBeteenInstance(context); 476 477 // TestType::OBJECT_BEHIND_BOUNDING_BOX 478 return new ObjectBehindBoundingBoxInstance(context); 479} 480 481} // anonymous 482 483tcu::TestCaseGroup* createProceduralGeometryTests(tcu::TestContext& testCtx) 484{ 485 // Test procedural geometry with complex bouding box sets 486 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "procedural_geometry")); 487 488 group->addChild(new RayQueryProceduralGeometryTestCase(testCtx, "object_behind_bounding_boxes", TestType::OBJECT_BEHIND_BOUNDING_BOX)); 489 group->addChild(new RayQueryProceduralGeometryTestCase(testCtx, "triangle_in_between", TestType::TRIANGLE_IN_BETWEEN)); 490 491 return group.release(); 492} 493 494} // RayQuery 495 496} // vkt 497