File indexing completed on 2026-04-09 07:49:03
0001 #include <iostream>
0002 #include <iomanip>
0003 #include <cstring>
0004 #include <csignal>
0005 #include <sstream>
0006 #include <fstream>
0007
0008 #include <optix.h>
0009 #include <optix_stubs.h>
0010 #include <cuda_runtime.h>
0011
0012 #include "SGeoConfig.hh"
0013 #include "SSys.hh"
0014 #include "SVec.hh"
0015 #include "scuda.h"
0016 #include "SScene.h"
0017 #include "NPX.h"
0018
0019 #include "OPTIX_CHECK.h"
0020 #include "CUDA_CHECK.h"
0021
0022 #include "CSGFoundry.h"
0023 #include "CSGSolid.h"
0024 #include "CSGNode.h"
0025
0026 #include "Binding.h"
0027 #include "Params.h"
0028 #include "Ctx.h"
0029
0030 #include "PIP.h"
0031 #include "SBT.h"
0032 #include "Properties.h"
0033
0034 #include "CU.h"
0035 #include "SLOG.hh"
0036
0037 #ifdef WITH_SOPTIX_ACCEL
0038 #include "SOPTIX_Accel.h"
0039 #include "SOPTIX_BuildInput_CPA.h"
0040 #include "SOPTIX_BuildInput_IA.h"
0041 #include "SOPTIX_BuildInput_Mesh.h"
0042 #include "SOPTIX_MeshGroup.h"
0043 #else
0044 #include "GAS.h"
0045 #include "GAS_Builder.h"
0046 #include "IAS.h"
0047 #include "IAS_Builder.h"
0048 #endif
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 const plog::Severity SBT::LEVEL = SLOG::EnvLevel("SBT", "DEBUG");
0064
0065
0066 std::string SBT::Desc()
0067 {
0068 std::stringstream ss ;
0069 ss << "SBT::Desc"
0070 #ifdef WITH_SOPTIX_ACCEL
0071 << " WITH_SOPTIX_ACCEL"
0072 #else
0073 << " NOT:WITH_SOPTIX_ACCEL"
0074 #endif
0075 ;
0076 std::string str = ss.str();
0077 return str ;
0078 }
0079
0080
0081
0082 SBT::SBT(const PIP* pip_)
0083 :
0084 emm(SGeoConfig::EnabledMergedMesh()),
0085 pip(pip_),
0086 properties(pip->properties),
0087 raygen(nullptr),
0088 miss(nullptr),
0089 hitgroup(nullptr),
0090 check(nullptr),
0091 foundry(nullptr),
0092 scene(nullptr)
0093 {
0094 init();
0095 }
0096
0097 SBT::~SBT()
0098 {
0099 destroy();
0100 }
0101
0102
0103 void SBT::init()
0104 {
0105 LOG(LEVEL) << "[" ;
0106 createRaygen();
0107 updateRaygen();
0108 createMiss();
0109 updateMiss();
0110 LOG(LEVEL) << "]" ;
0111 }
0112
0113
0114 void SBT::destroy()
0115 {
0116 destroyRaygen();
0117 destroyMiss();
0118 destroyHitgroup();
0119 }
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131 void SBT::createRaygen()
0132 {
0133 raygen = new Raygen ;
0134 CUDA_CHECK( cudaMalloc( reinterpret_cast<void**>( &d_raygen ), sizeof(Raygen) ) );
0135 sbt.raygenRecord = d_raygen;
0136 OPTIX_CHECK( optixSbtRecordPackHeader( pip->raygen_pg, raygen ) );
0137 }
0138
0139 void SBT::destroyRaygen()
0140 {
0141 CUDA_CHECK( cudaFree( reinterpret_cast<void*>( d_raygen ) ) );
0142 }
0143
0144 void SBT::updateRaygen()
0145 {
0146 raygen->data = {};
0147 raygen->data.placeholder = 42.0f ;
0148
0149 CUDA_CHECK( cudaMemcpy(
0150 reinterpret_cast<void*>( d_raygen ),
0151 raygen,
0152 sizeof( Raygen ),
0153 cudaMemcpyHostToDevice
0154 ) );
0155 }
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 void SBT::createMiss()
0166 {
0167 miss = new Miss ;
0168 CUDA_CHECK( cudaMalloc( reinterpret_cast<void**>( &d_miss ), sizeof(Miss) ) );
0169 sbt.missRecordBase = d_miss;
0170 OPTIX_CHECK( optixSbtRecordPackHeader( pip->miss_pg, miss ) );
0171
0172 sbt.missRecordStrideInBytes = sizeof( Miss );
0173 sbt.missRecordCount = 1;
0174 }
0175
0176 void SBT::destroyMiss()
0177 {
0178 CUDA_CHECK( cudaFree( reinterpret_cast<void*>( d_miss ) ) );
0179 }
0180
0181 void SBT::updateMiss()
0182 {
0183
0184
0185
0186 float3 midgrey = make_float3( 0.6f, 0.6f, 0.6f);
0187 const float3& bkg = midgrey ;
0188
0189 miss->data.r = bkg.x ;
0190 miss->data.g = bkg.y ;
0191 miss->data.b = bkg.z ;
0192
0193 CUDA_CHECK( cudaMemcpy(
0194 reinterpret_cast<void*>( d_miss ),
0195 miss,
0196 sizeof(Miss),
0197 cudaMemcpyHostToDevice
0198 ) );
0199 }
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 void SBT::setFoundry(const CSGFoundry* foundry_)
0228 {
0229 foundry = foundry_ ;
0230 scene = foundry->getScene();
0231
0232 createGeom();
0233 }
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 void SBT::createGeom()
0248 {
0249 LOG(LEVEL) << "[" ;
0250 createGAS();
0251 LOG(LEVEL) << "] createGAS " ;
0252 createIAS();
0253 LOG(LEVEL) << "] createIAS " ;
0254 createHitgroup();
0255 LOG(LEVEL) << "] createHitGroup " ;
0256 checkHitgroup();
0257 LOG(LEVEL) << "] checkHitGroup " ;
0258 LOG(LEVEL) << "]" ;
0259 }
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 void SBT::createGAS()
0278 {
0279 LOG(LEVEL) << SGeoConfig::DescEMM() ;
0280
0281 unsigned num_solid = foundry->getNumSolid();
0282 for(unsigned i=0 ; i < num_solid ; i++)
0283 {
0284 unsigned gas_idx = i ;
0285
0286 bool enabled = SGeoConfig::IsEnabledMergedMesh(gas_idx) ;
0287 bool enabled2 = emm & ( 0x1 << gas_idx ) ;
0288 bool enabled_expect = enabled == enabled2 ;
0289 assert( enabled_expect );
0290 if(!enabled_expect) std::raise(SIGINT);
0291
0292 if( enabled )
0293 {
0294 LOG(LEVEL) << " emm proceed " << gas_idx ;
0295 createGAS(gas_idx);
0296 }
0297 else
0298 {
0299 LOG(LEVEL) << " emm skip " << gas_idx ;
0300 }
0301 }
0302 LOG(LEVEL) << descGAS() ;
0303 }
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316 #ifdef WITH_SOPTIX_ACCEL
0317 void SBT::createGAS(unsigned gas_idx)
0318 {
0319 SOPTIX_BuildInput* bi = nullptr ;
0320 SOPTIX_Accel* gas = nullptr ;
0321
0322 bool trimesh = foundry->isSolidTrimesh(gas_idx);
0323
0324 const std::string& mmlabel = foundry->getSolidMMLabel(gas_idx);
0325
0326 LOG(LEVEL)
0327 << " WITH_SOPTIX_ACCEL "
0328 << " gas_idx " << gas_idx
0329 << " trimesh " << ( trimesh ? "YES" : "NO " )
0330 << " mmlabel " << mmlabel
0331 ;
0332
0333 if(trimesh)
0334 {
0335
0336 const SMeshGroup* mg = scene->getMeshGroup(gas_idx) ;
0337 LOG_IF(fatal, mg == nullptr)
0338 << " FAILED to SScene::getMeshGroup"
0339 << " gas_idx " << gas_idx
0340 << "\n"
0341 << scene->desc()
0342 ;
0343 assert(mg);
0344
0345 SOPTIX_MeshGroup* xmg = SOPTIX_MeshGroup::Create( mg ) ;
0346 gas = SOPTIX_Accel::Create(Ctx::context, xmg->bis );
0347 xgas[gas_idx] = xmg ;
0348 }
0349 else
0350 {
0351
0352 SCSGPrimSpec ps = foundry->getPrimSpec(gas_idx);
0353 bi = new SOPTIX_BuildInput_CPA(ps) ;
0354 gas = SOPTIX_Accel::Create(Ctx::context, bi );
0355 }
0356 vgas[gas_idx] = gas ;
0357 }
0358
0359 #else
0360 void SBT::createGAS(unsigned gas_idx)
0361 {
0362 bool trimesh = foundry->isSolidTrimesh(gas_idx);
0363 LOG(fatal, trimesh == true ) << " NOT:WITH_SOPTIX_ACCEL ONLY SUPPORTS ANALYTIC GEOMETRY : INVALID SGeoConfig::Trimesh setting " ;
0364 assert( trimesh == false );
0365
0366 SCSGPrimSpec ps = foundry->getPrimSpec(gas_idx);
0367 GAS gas = {} ;
0368 GAS_Builder::Build(gas, ps);
0369 vgas[gas_idx] = gas ;
0370 }
0371 #endif
0372
0373
0374
0375 OptixTraversableHandle SBT::getGASHandle(unsigned gas_idx) const
0376 {
0377 unsigned count = vgas.count(gas_idx);
0378 LOG_IF(fatal, count == 0) << " no such gas_idx " << gas_idx ;
0379 assert( count == 1 );
0380
0381 #ifdef WITH_SOPTIX_ACCEL
0382 SOPTIX_Accel* _gas = vgas.at(gas_idx) ;
0383 OptixTraversableHandle handle = _gas->handle ;
0384 #else
0385 const GAS& gas = vgas.at(gas_idx);
0386 OptixTraversableHandle handle = gas.handle ;
0387 #endif
0388
0389 return handle ;
0390 }
0391
0392
0393 void SBT::createIAS()
0394 {
0395 unsigned num_ias = foundry->getNumUniqueIAS() ;
0396 bool num_ias_expect = num_ias == 1 ;
0397 assert( num_ias_expect );
0398 if(!num_ias_expect) std::raise(SIGINT);
0399
0400 unsigned ias_idx = 0 ;
0401 createIAS(ias_idx);
0402 }
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427 void SBT::createIAS(unsigned ias_idx)
0428 {
0429 unsigned num_inst = foundry->getNumInst();
0430 unsigned num_ias_inst = foundry->getNumInstancesIAS(ias_idx, emm);
0431 LOG(LEVEL)
0432 << " ias_idx " << ias_idx
0433 << " num_inst " << num_inst
0434 << " num_ias_inst(getNumInstancesIAS) " << num_ias_inst
0435 ;
0436
0437 std::vector<qat4> inst ;
0438 foundry->getInstanceTransformsIAS(inst, ias_idx, emm );
0439 assert( num_ias_inst == inst.size() );
0440
0441
0442 collectInstances(inst);
0443
0444 LOG(LEVEL) << descIAS(inst);
0445
0446 #ifdef WITH_SOPTIX_ACCEL
0447 SOPTIX_BuildInput* ia = new SOPTIX_BuildInput_IA(instances) ;
0448 SOPTIX_Accel* ias = SOPTIX_Accel::Create(Ctx::context, ia );
0449 vias.push_back(ias);
0450 #else
0451 IAS ias = {} ;
0452 IAS_Builder::Build(ias, instances );
0453 vias.push_back(ias);
0454 #endif
0455
0456 }
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495 void SBT::collectInstances( const std::vector<qat4>& ias_inst )
0496 {
0497 LOG(LEVEL) << "[ ias_inst.size " << ias_inst.size() ;
0498
0499 unsigned num_ias_inst = ias_inst.size() ;
0500 unsigned flags = OPTIX_INSTANCE_FLAG_DISABLE_ANYHIT ;
0501 unsigned prim_idx = 0u ;
0502
0503 std::map<unsigned, unsigned> gasIdx_sbtOffset ;
0504
0505 for(unsigned i=0 ; i < num_ias_inst ; i++)
0506 {
0507 const qat4& q = ias_inst[i] ;
0508 int ins_idx, gasIdx, sensor_identifier, sensor_index ;
0509 q.getIdentity(ins_idx, gasIdx, sensor_identifier, sensor_index );
0510
0511 unsigned instanceId = q.get_IAS_OptixInstance_instanceId() ;
0512 assert( int(instanceId) == sensor_identifier );
0513
0514 bool instanceId_is_allowed = instanceId < properties->limitMaxInstanceId ;
0515 LOG_IF(fatal, !instanceId_is_allowed)
0516 << " instanceId " << instanceId
0517 << " sbt->properties->limitMaxInstanceId " << properties->limitMaxInstanceId
0518 << " instanceId_is_allowed " << ( instanceId_is_allowed ? "YES" : "NO " )
0519 ;
0520 assert( instanceId_is_allowed ) ;
0521
0522 OptixTraversableHandle handle = getGASHandle(gasIdx);
0523
0524 bool found = gasIdx_sbtOffset.count(gasIdx) == 1 ;
0525 unsigned sbtOffset = found ? gasIdx_sbtOffset.at(gasIdx) : getOffset(gasIdx, prim_idx ) ;
0526 if(!found)
0527 {
0528 gasIdx_sbtOffset[gasIdx] = sbtOffset ;
0529 LOG(LEVEL)
0530 << " i " << std::setw(7) << i
0531 << " gasIdx " << std::setw(3) << gasIdx
0532 << " sbtOffset " << std::setw(6) << sbtOffset
0533 << " gasIdx_sbtOffset.size " << std::setw(3) << gasIdx_sbtOffset.size()
0534 << " instanceId " << instanceId
0535 ;
0536 }
0537
0538
0539 unsigned visibilityMask = properties->visibilityMask(gasIdx);
0540
0541 OptixInstance instance = {} ;
0542 q.copy_columns_3x4( instance.transform );
0543 instance.instanceId = instanceId ;
0544 instance.sbtOffset = sbtOffset ;
0545 instance.visibilityMask = visibilityMask ;
0546
0547 instance.flags = flags ;
0548 instance.traversableHandle = handle ;
0549
0550 instances.push_back(instance);
0551 }
0552 LOG(LEVEL) << "] instances.size " << instances.size() ;
0553 }
0554
0555 NP* SBT::serializeInstances() const
0556 {
0557 return NPX::ArrayFromVec<unsigned, OptixInstance>(instances) ;
0558 }
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570 std::string SBT::descIAS(const std::vector<qat4>& inst ) const
0571 {
0572 std::stringstream ss ;
0573 bool sbt_dump_ias = SSys::getenvbool("SBT_DUMP_IAS") ;
0574 ss
0575 << "SBT::descIAS"
0576 << " inst.size " << inst.size()
0577 << " SBT_DUMP_IAS " << sbt_dump_ias
0578 << std::endl
0579 ;
0580
0581 typedef std::map<int, std::vector<int>> MUV ;
0582 MUV ins_idx_per_gas ;
0583
0584 for(unsigned i=0 ; i < inst.size() ; i++)
0585 {
0586 const qat4& q = inst[i] ;
0587 int ins_idx, gas_idx, sensor_identifier, sensor_index ;
0588 q.getIdentity(ins_idx, gas_idx, sensor_identifier, sensor_index );
0589
0590 ins_idx_per_gas[gas_idx].push_back(ins_idx);
0591
0592 if(sbt_dump_ias) ss
0593 << " i " << std::setw(10) << i
0594 << " ins_idx " << std::setw(10) << ins_idx
0595 << " gas_idx " << std::setw(10) << gas_idx
0596 << " sensor_identifier " << std::setw(10) << sensor_identifier
0597 << " sensor_index " << std::setw(10) << sensor_index
0598 << std::endl
0599 ;
0600 }
0601
0602 MUV::const_iterator b = ins_idx_per_gas.begin();
0603 MUV::const_iterator e = ins_idx_per_gas.end();
0604 MUV::const_iterator i ;
0605
0606 for( i=b ; i != e ; i++)
0607 {
0608 int gas_idx = i->first ;
0609 const std::vector<int>& v = i->second ;
0610 int num_ins_idx = int(v.size()) ;
0611
0612 int ins_idx_mn, ins_idx_mx ;
0613 SVec<int>::MinMax(v, ins_idx_mn, ins_idx_mx) ;
0614 int num_ins_idx2 = ins_idx_mx - ins_idx_mn + 1 ;
0615
0616 ss
0617 << " gas_idx " << std::setw(10) << gas_idx
0618 << " num_ins_idx " << std::setw(10) << num_ins_idx
0619 << " ins_idx_mn " << std::setw(10) << ins_idx_mn
0620 << " ins_idx_mx " << std::setw(10) << ins_idx_mx
0621 << " ins_idx_mx - ins_idx_mx + 1 (num_ins_idx2) " << std::setw(10) << num_ins_idx2
0622 << std::endl
0623 ;
0624
0625 assert( num_ins_idx == num_ins_idx2 );
0626 }
0627 std::string s = ss.str();
0628 return s ;
0629 }
0630
0631
0632 OptixTraversableHandle SBT::getIASHandle(unsigned ias_idx) const
0633 {
0634 assert( ias_idx < vias.size() );
0635
0636 #ifdef WITH_SOPTIX_ACCEL
0637 SOPTIX_Accel* _ias = vias[ias_idx] ;
0638 OptixTraversableHandle handle = _ias->handle ;
0639 #else
0640 const IAS& ias = vias[ias_idx];
0641 OptixTraversableHandle handle = ias.handle ;
0642 #endif
0643 return handle ;
0644 }
0645
0646
0647 OptixTraversableHandle SBT::getTOPHandle() const
0648 {
0649 return getIASHandle(0);
0650 }
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668 int SBT::getOffset(unsigned q_gas_idx, unsigned q_layer_idx ) const
0669 {
0670 int offset_sbt = _getOffset(q_gas_idx, q_layer_idx );
0671
0672 LOG_IF(LEVEL, q_layer_idx < 10)
0673 << " q_gas_idx " << q_gas_idx
0674 << " q_layer_idx " << q_layer_idx
0675 << " offset_sbt " << offset_sbt
0676 ;
0677
0678 assert( offset_sbt > -1 );
0679 return offset_sbt ;
0680 }
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698 int SBT::_getOffset(unsigned q_gas_idx , unsigned q_layer_idx ) const
0699 {
0700 int offset_sbt = 0 ;
0701
0702 for(IT it=vgas.begin() ; it !=vgas.end() ; it++)
0703 {
0704 unsigned gas_idx = it->first ;
0705 bool trimesh = foundry->isSolidTrimesh(gas_idx);
0706 const std::string& mmlabel = foundry->getSolidMMLabel(gas_idx);
0707 const CSGSolid* so = foundry->getSolid(gas_idx) ;
0708 int numPrim = so->numPrim ;
0709
0710 #ifdef WITH_SOPTIX_ACCEL
0711 SOPTIX_Accel* gas = it->second ;
0712 #else
0713 const GAS* gas = &(it->second) ;
0714 #endif
0715
0716 int num_bi = gas->bis.size();
0717 LOG(debug)
0718 << " gas_idx " << gas_idx
0719 << " num_bi " << num_bi
0720 << " trimesh " << ( trimesh ? "YES" : "NO " )
0721 << " mmlabel " << mmlabel
0722 ;
0723
0724 if(!trimesh) assert(num_bi == 1);
0725 if(trimesh)
0726 {
0727 bool are_equal = num_bi == numPrim ;
0728 LOG_IF(fatal, !are_equal )
0729 << " UNEXPECTED trimesh with "
0730 << " UNEQUAL: "
0731 << " num_bi " << num_bi
0732 << " numPrim " << numPrim
0733 << " gas_idx " << gas_idx
0734 << " mmlabel " << mmlabel
0735 ;
0736 assert(are_equal );
0737 }
0738
0739 for(int j=0 ; j < num_bi ; j++)
0740 {
0741
0742 #ifdef WITH_SOPTIX_ACCEL
0743 const SOPTIX_BuildInput* bi = gas->bis[j] ;
0744 int num_sbt = bi->numSbtRecords() ;
0745 if(!trimesh) assert( bi->is_BuildInputCustomPrimitiveArray() && num_sbt == numPrim );
0746 if(trimesh) assert( bi->is_BuildInputTriangleArray() && num_sbt == 1 );
0747 #else
0748 assert( trimesh == false );
0749 const BI& bi = gas->bis[j] ;
0750 const OptixBuildInputCustomPrimitiveArray& buildInputCPA = bi.getBuildInputCPA() ;
0751 unsigned num_sbt = buildInputCPA.numSbtRecords ;
0752 #endif
0753 LOG(debug)
0754 << " gas_idx " << gas_idx
0755 << " num_bi " << num_bi
0756 << " j " << j
0757 << " num_sbt " << num_sbt
0758 ;
0759
0760 for( int k=0 ; k < num_sbt ; k++)
0761 {
0762 unsigned localPrimIdx = trimesh ? j : k ;
0763 if( q_gas_idx == gas_idx && q_layer_idx == localPrimIdx ) return offset_sbt ;
0764 offset_sbt += 1 ;
0765 }
0766 }
0767 }
0768 LOG(error)
0769 << "did not find targetted shape "
0770 << " vgas.size " << vgas.size()
0771 << " q_gas_idx_ " << q_gas_idx
0772 << " q_layer_idx " << q_layer_idx
0773 << " offset_sbt " << offset_sbt
0774 ;
0775 return -1 ;
0776 }
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789 unsigned SBT::getTotalRec() const
0790 {
0791 unsigned tot_bi = 0 ;
0792 unsigned tot_sbt = 0 ;
0793
0794 for(IT it=vgas.begin() ; it !=vgas.end() ; it++)
0795 {
0796 unsigned gas_idx = it->first ;
0797 bool trimesh = foundry->isSolidTrimesh(gas_idx);
0798 const std::string& mmlabel = foundry->getSolidMMLabel(gas_idx);
0799
0800 bool enabled = SGeoConfig::IsEnabledMergedMesh(gas_idx) ;
0801 LOG_IF(error, !enabled) << "gas_idx " << gas_idx << " enabled " << enabled ;
0802
0803
0804 #ifdef WITH_SOPTIX_ACCEL
0805 SOPTIX_Accel* gas = it->second ;
0806 #else
0807 const GAS* gas = &(it->second) ;
0808 #endif
0809 unsigned num_bi = gas->bis.size();
0810 tot_bi += num_bi ;
0811
0812 LOG(LEVEL)
0813 << " gas_idx " << gas_idx
0814 << " num_bi " << num_bi
0815 << " trimesh " << ( trimesh ? "YES" : "NO " )
0816 << " mmlabel " << mmlabel
0817 ;
0818
0819 for(unsigned j=0 ; j < num_bi ; j++)
0820 {
0821 #ifdef WITH_SOPTIX_ACCEL
0822 const SOPTIX_BuildInput* bi = gas->bis[j] ;
0823 unsigned num_sbt = bi->numSbtRecords() ;
0824 #else
0825 assert( trimesh == false );
0826 const BI& bi = gas->bis[j] ;
0827 const OptixBuildInputCustomPrimitiveArray& buildInputCPA = bi.getBuildInputCPA() ;
0828 unsigned num_sbt = buildInputCPA.numSbtRecords ;
0829 #endif
0830 tot_sbt += num_sbt ;
0831
0832 LOG(LEVEL)
0833 << " gas_idx " << gas_idx
0834 << " num_bi " << num_bi
0835 << " j " << j
0836 << " num_sbt " << num_sbt
0837 ;
0838
0839 }
0840 }
0841 assert( tot_bi > 0 && tot_sbt > 0 );
0842 return tot_sbt ;
0843 }
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856 std::string SBT::descGAS() const
0857 {
0858 unsigned tot_sbt = 0 ;
0859 unsigned tot_bi = 0 ;
0860 std::stringstream ss ;
0861 ss
0862 << "SBT::descGAS"
0863 << " num_gas " << vgas.size()
0864 << " bi.numRec ( "
0865 ;
0866
0867 for(IT it=vgas.begin() ; it !=vgas.end() ; it++)
0868 {
0869 unsigned gas_idx = it->first ;
0870 bool trimesh = foundry->isSolidTrimesh(gas_idx);
0871 const std::string& mmlabel = foundry->getSolidMMLabel(gas_idx);
0872
0873 #ifdef WITH_SOPTIX_ACCEL
0874 SOPTIX_Accel* gas = it->second ;
0875 #else
0876 assert( trimesh == false );
0877 const GAS* gas = &(it->second) ;
0878 #endif
0879
0880 bool enabled = SGeoConfig::IsEnabledMergedMesh(gas_idx) ;
0881 LOG_IF(error, !enabled)
0882 << " gas_idx " << gas_idx
0883 << " enabled " << enabled
0884 << " trimesh " << ( trimesh ? "YES" : "NO " )
0885 << " mmlabel " << mmlabel
0886 ;
0887
0888 unsigned num_bi = gas->bis.size();
0889 tot_bi += num_bi ;
0890 for(unsigned j=0 ; j < num_bi ; j++)
0891 {
0892
0893 #ifdef WITH_SOPTIX_ACCEL
0894 const SOPTIX_BuildInput* bi = gas->bis[j] ;
0895 unsigned num_sbt = bi->numSbtRecords() ;
0896 #else
0897 const BI& bi = gas->bis[j] ;
0898 const OptixBuildInputCustomPrimitiveArray& buildInputCPA = bi.getBuildInputCPA() ;
0899 unsigned num_sbt = buildInputCPA.numSbtRecords ;
0900 #endif
0901 ss << num_sbt << " " ;
0902 tot_sbt += num_sbt ;
0903 }
0904 }
0905
0906 ss << " ) "
0907 << " tot_sbt " << tot_sbt
0908 << " tot_bi " << tot_bi
0909 ;
0910
0911 std::string str = ss.str();
0912 return str ;
0913 }
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963
0964
0965
0966 #ifdef WITH_SOPTIX_ACCEL
0967 void SBT::createHitgroup()
0968 {
0969 unsigned num_solid = foundry->getNumSolid();
0970 unsigned num_gas = vgas.size();
0971 unsigned tot_rec = getTotalRec();
0972
0973 LOG(LEVEL)
0974 << " WITH_SOPTIX_ACCEL "
0975 << " num_solid " << num_solid
0976 << " num_gas " << num_gas
0977 << " tot_rec " << tot_rec
0978 ;
0979
0980 hitgroup = new HitGroup[tot_rec] ;
0981 HitGroup* hg = hitgroup ;
0982
0983 for(unsigned i=0 ; i < tot_rec ; i++)
0984 OPTIX_CHECK( optixSbtRecordPackHeader( pip->hitgroup_pg, hitgroup + i ) );
0985
0986 unsigned sbt_offset = 0 ;
0987
0988 for(IT it=vgas.begin() ; it !=vgas.end() ; it++)
0989 {
0990 unsigned gas_idx = it->first ;
0991 SOPTIX_Accel* gas = it->second ;
0992
0993
0994 int num_bi = gas->bis.size();
0995
0996 bool trimesh = foundry->isSolidTrimesh(gas_idx);
0997 const std::string& mmlabel = foundry->getSolidMMLabel(gas_idx);
0998
0999 const SOPTIX_MeshGroup* xmg = trimesh ? xgas.at(gas_idx) : nullptr ;
1000 const SCUDA_MeshGroup* cmg = xmg ? xmg->cmg : nullptr ;
1001
1002
1003 const CSGSolid* so = foundry->getSolid(gas_idx) ;
1004 int numPrim = so->numPrim ;
1005 int primOffset = so->primOffset ;
1006
1007 LOG(LEVEL)
1008 << " WITH_SOPTIX_ACCEL "
1009 << " gas_idx " << gas_idx
1010 << " trimesh " << ( trimesh ? "YES" : "NO " )
1011 << " num_bi " << num_bi
1012 << " mmlabel " << mmlabel
1013 << " so.numPrim " << numPrim
1014 << " so.primOffset " << primOffset
1015 ;
1016
1017 if(!trimesh) assert( num_bi == 1 );
1018 if(trimesh) assert( num_bi == numPrim );
1019
1020
1021
1022
1023
1024
1025
1026 for(int j=0 ; j < num_bi ; j++)
1027 {
1028 const SOPTIX_BuildInput* bi = gas->bis[j] ;
1029 int num_sbt = bi->numSbtRecords() ;
1030
1031 if(!trimesh) assert( bi->is_BuildInputCustomPrimitiveArray() && num_sbt == numPrim );
1032 if(trimesh) assert( bi->is_BuildInputTriangleArray() && num_sbt == 1 );
1033
1034 LOG(LEVEL)
1035 << " gas_idx " << gas_idx
1036 << " num_sbt " << num_sbt << "(ana: num_sbt is num_CSGPrim in CSGSolid, tri: num_sbt is 1)"
1037 ;
1038
1039 for( int k=0 ; k < num_sbt ; k++)
1040 {
1041 unsigned localPrimIdx = trimesh ? j : k ;
1042 unsigned globalPrimIdx = primOffset + localPrimIdx ;
1043 const CSGPrim* prim = foundry->getPrim( globalPrimIdx );
1044
1045 unsigned globalPrimIdx_1 = prim->globalPrimIdx();
1046
1047 bool same_globalPrimIdx = globalPrimIdx == globalPrimIdx_1 ;
1048 LOG_IF(info, !same_globalPrimIdx)
1049 << " globalPrimIdx " << std::setw(5) << globalPrimIdx
1050 << " globalPrimIdx_1 " << std::setw(5) << globalPrimIdx_1
1051 << " YOU PROBABLY NEED TO RECREATE THE PERSISTED CSGFoundry GEOMETRY "
1052 ;
1053
1054 assert( globalPrimIdx == globalPrimIdx_1 );
1055
1056 int boundary = foundry->getPrimBoundary_(prim);
1057 assert( boundary > -1 );
1058
1059 if( trimesh == false )
1060 {
1061 setPrimData( hg->data.prim, prim );
1062 }
1063 else
1064 {
1065 setMeshData( hg->data.mesh, cmg, localPrimIdx, boundary, globalPrimIdx );
1066 }
1067
1068 unsigned check_sbt_offset = getOffset(gas_idx, localPrimIdx );
1069
1070 bool sbt_offset_expect = check_sbt_offset == sbt_offset ;
1071 assert( sbt_offset_expect );
1072 if(!sbt_offset_expect) std::raise(SIGINT);
1073
1074 hg++ ;
1075 sbt_offset++ ;
1076 }
1077 }
1078 }
1079 UploadHitGroup(sbt, d_hitgroup, hitgroup, tot_rec );
1080 }
1081 #else
1082
1083
1084
1085
1086
1087
1088 void SBT::createHitgroup()
1089 {
1090 unsigned num_solid = foundry->getNumSolid();
1091 unsigned num_gas = vgas.size();
1092 unsigned tot_rec = getTotalRec();
1093
1094 LOG(info) << " NOT:WITH_SOPTIX_ACCEL " ;
1095 LOG(LEVEL)
1096 << " num_solid " << num_solid
1097 << " num_gas " << num_gas
1098 << " tot_rec " << tot_rec
1099 ;
1100
1101 hitgroup = new HitGroup[tot_rec] ;
1102 HitGroup* hg = hitgroup ;
1103
1104 for(unsigned i=0 ; i < tot_rec ; i++)
1105 OPTIX_CHECK( optixSbtRecordPackHeader( pip->hitgroup_pg, hitgroup + i ) );
1106
1107 unsigned sbt_offset = 0 ;
1108
1109
1110 for(IT it=vgas.begin() ; it !=vgas.end() ; it++)
1111 {
1112 unsigned gas_idx = it->first ;
1113 const GAS* gas = &(it->second) ;
1114 unsigned num_bi = gas->bis.size();
1115 assert( num_bi == 1 );
1116
1117 bool trimesh = foundry->isSolidTrimesh(gas_idx);
1118 LOG_IF( fatal, trimesh ) << " NOT:WITH_SOPTIX_ACCEL trimesh NOT ALLOWED gas_idx " << gas_idx ;
1119 assert( !trimesh );
1120
1121 const CSGSolid* so = foundry->getSolid(gas_idx) ;
1122 int numPrim = so->numPrim ;
1123 int primOffset = so->primOffset ;
1124
1125 LOG(LEVEL) << "gas_idx " << gas_idx << " so.numPrim " << numPrim << " so.primOffset " << primOffset ;
1126
1127 for(unsigned j=0 ; j < num_bi ; j++)
1128 {
1129 const BI& bi = gas->bis[j] ;
1130 const OptixBuildInputCustomPrimitiveArray& buildInputCPA = bi.getBuildInputCPA() ;
1131 unsigned num_sbt = buildInputCPA.numSbtRecords ;
1132 assert( num_sbt == unsigned(numPrim) ) ;
1133
1134 for( unsigned k=0 ; k < num_sbt ; k++)
1135 {
1136 unsigned localPrimIdx = k ;
1137
1138 unsigned globalPrimIdx = primOffset + localPrimIdx ;
1139 const CSGPrim* prim = foundry->getPrim( globalPrimIdx );
1140 setPrimData( hg->data.prim, prim, globalPrimIdx );
1141 unsigned check_sbt_offset = getOffset(gas_idx, localPrimIdx );
1142
1143 bool sbt_offset_expect = check_sbt_offset == sbt_offset ;
1144 assert( sbt_offset_expect );
1145 if(!sbt_offset_expect) std::raise(SIGINT);
1146
1147 hg++ ;
1148 sbt_offset++ ;
1149 }
1150 }
1151 }
1152 UploadHitGroup(sbt, d_hitgroup, hitgroup, tot_rec );
1153 }
1154 #endif
1155
1156
1157
1158 void SBT::UploadHitGroup(OptixShaderBindingTable& sbt, CUdeviceptr& d_hitgroup, HitGroup* hitgroup, size_t tot_rec )
1159 {
1160 CUDA_CHECK( cudaMalloc(reinterpret_cast<void**>( &d_hitgroup ), sizeof(HitGroup)*tot_rec ));
1161 CUDA_CHECK( cudaMemcpy(reinterpret_cast<void*>( d_hitgroup ), hitgroup, sizeof(HitGroup)*tot_rec, cudaMemcpyHostToDevice ));
1162
1163 sbt.hitgroupRecordBase = d_hitgroup;
1164 sbt.hitgroupRecordStrideInBytes = sizeof(HitGroup);
1165 sbt.hitgroupRecordCount = tot_rec ;
1166 }
1167
1168 void SBT::destroyHitgroup()
1169 {
1170 CUDA_CHECK( cudaFree( reinterpret_cast<void*>( d_hitgroup ) ) );
1171 }
1172
1173
1174 void SBT::checkHitgroup()
1175 {
1176 unsigned num_solid = foundry->getNumSolid();
1177 unsigned num_prim = foundry->getNumPrim();
1178 unsigned num_sbt = sbt.hitgroupRecordCount ;
1179
1180 LOG(LEVEL)
1181 << " num_sbt (sbt.hitgroupRecordCount) " << num_sbt
1182 << " num_solid " << num_solid
1183 << " num_prim " << num_prim
1184 ;
1185 }
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198 void SBT::setPrimData( CustomPrim& cp, const CSGPrim* prim )
1199 {
1200 cp.numNode = prim->numNode();
1201 cp.nodeOffset = prim->nodeOffset();
1202 cp.globalPrimIdx = prim->globalPrimIdx();
1203 }
1204
1205 void SBT::checkPrimData( CustomPrim& cp, const CSGPrim* prim)
1206 {
1207 assert( cp.numNode == prim->numNode() );
1208 assert( cp.nodeOffset == prim->nodeOffset() );
1209
1210 }
1211 void SBT::dumpPrimData( const CustomPrim& cp ) const
1212 {
1213 std::cout
1214 << "SBT::dumpPrimData"
1215 << " cp.numNode " << cp.numNode
1216 << " cp.nodeOffset " << cp.nodeOffset
1217 << std::endl
1218 ;
1219 }
1220
1221
1222 #ifdef WITH_SOPTIX_ACCEL
1223
1224
1225
1226
1227
1228
1229
1230
1231 void SBT::setMeshData( TriMesh& tm, const SCUDA_MeshGroup* cmg, int j, int boundary, unsigned globalPrimIdx )
1232 {
1233 tm.boundary = boundary ;
1234 tm.vertex = reinterpret_cast<float3*>( cmg->vtx.pointer(j) );
1235 tm.normal = reinterpret_cast<float3*>( cmg->nrm.pointer(j) );
1236 tm.indice = reinterpret_cast<uint3*>( cmg->idx.pointer(j) );
1237 tm.globalPrimIdx = globalPrimIdx ;
1238 }
1239 #endif
1240
1241
1242
1243
1244
1245