File indexing completed on 2026-04-09 07:49:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #include <iostream>
0041
0042 #include "SLOG.hh"
0043 #include "SSys.hh"
0044 #include "SStr.hh"
0045 #include "SPath.hh"
0046 #include "NP.hh"
0047 #include "scuda.h"
0048 #include "squad.h"
0049 #include "sqat4.h"
0050 #include "OpticksCSG.h"
0051
0052
0053
0054
0055 #include "Params.h"
0056
0057 #include "CSGFoundry.h"
0058 #include "CSGSolid.h"
0059 #include "CSGPrim.h"
0060 #include "CSGNode.h"
0061
0062 #include "Frame.h"
0063 #include "Six.h"
0064
0065 #include "SGeoConfig.hh"
0066
0067
0068 Six::Six(const char* ptx_path_, const char* geo_ptx_path_, Params* params_)
0069 :
0070 emm(SGeoConfig::EnabledMergedMesh()),
0071 context(optix::Context::create()),
0072 material(context->createMaterial()),
0073
0074 d_pixel(nullptr),
0075 d_isect(nullptr),
0076 d_photon(nullptr),
0077
0078 params(params_),
0079 ptx_path(strdup(ptx_path_)),
0080 geo_ptx_path(strdup(geo_ptx_path_)),
0081 entry_point_index(0u),
0082 optix_device_ordinal(0u),
0083 foundry(nullptr),
0084 pindex(SSys::getenvint("PINDEX", 0))
0085 {
0086 initContext();
0087 initPipeline();
0088 initFrame();
0089 updateContext();
0090 }
0091
0092 void Six::initContext()
0093 {
0094 LOG(info) << " pindex " << pindex ;
0095 context->setRayTypeCount(1);
0096 context->setPrintEnabled(true);
0097 context->setPrintBufferSize(1024);
0098 context->setPrintLaunchIndex(pindex);
0099 context->setEntryPointCount(1);
0100 }
0101
0102 void Six::initPipeline()
0103 {
0104 LOG(info);
0105 context->setRayGenerationProgram( entry_point_index, context->createProgramFromPTXFile( ptx_path , "raygen" ));
0106 context->setMissProgram( entry_point_index, context->createProgramFromPTXFile( ptx_path , "miss" ));
0107 material->setClosestHitProgram( entry_point_index, context->createProgramFromPTXFile( ptx_path , "closest_hit" ));
0108 }
0109
0110 void Six::initFrame()
0111 {
0112 pixel_buffer = context->createBuffer( RT_BUFFER_OUTPUT, RT_FORMAT_UNSIGNED_BYTE4, params->width, params->height);
0113 context["pixel_buffer"]->set( pixel_buffer );
0114 d_pixel = (uchar4*)pixel_buffer->getDevicePointer(optix_device_ordinal);
0115
0116 isect_buffer = context->createBuffer( RT_BUFFER_OUTPUT, RT_FORMAT_FLOAT4, params->width, params->height);
0117 context["isect_buffer"]->set( isect_buffer );
0118 d_isect = (float4*)isect_buffer->getDevicePointer(optix_device_ordinal);
0119
0120 photon_buffer = context->createBuffer( RT_BUFFER_OUTPUT, RT_FORMAT_USER, params->width, params->height);
0121 photon_buffer->setElementSize( sizeof(quad4) );
0122 context["photon_buffer"]->set( photon_buffer );
0123 d_photon = (quad4*)photon_buffer->getDevicePointer(optix_device_ordinal);
0124
0125 LOG(info)
0126 << " params->width " << params->width
0127 << " params->height " << params->height
0128 << " optix_device_ordinal " << optix_device_ordinal
0129 ;
0130 }
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141 void Six::updateContext()
0142 {
0143 LOG(info)
0144 << " params.cameratype " << params->cameratype
0145 << " params.tmin " << params->tmin
0146 ;
0147
0148 context[ "tmin"]->setFloat( params->tmin );
0149 context[ "eye"]->setFloat( params->eye.x, params->eye.y, params->eye.z );
0150 context[ "U" ]->setFloat( params->U.x, params->U.y, params->U.z );
0151 context[ "V" ]->setFloat( params->V.x, params->V.y, params->V.z );
0152 context[ "W" ]->setFloat( params->W.x, params->W.y, params->W.z );
0153 context[ "radiance_ray_type" ]->setUint( 0u );
0154 context[ "cameratype" ]->setUint( params->cameratype );
0155 context[ "raygenmode" ]->setUint( params->raygenmode );
0156
0157
0158 }
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181 template<typename T>
0182 void Six::createContextInputBuffer( T* d_ptr, unsigned num_item, const char* name )
0183 {
0184 LOG(info) << name << " " << d_ptr << ( d_ptr == nullptr ? " EMPTY " : "" );
0185
0186
0187 unsigned type = RT_BUFFER_INPUT ;
0188 RTformat format = RT_FORMAT_USER ;
0189 optix::Buffer buffer = context->createBuffer( type, format, num_item );
0190 buffer->setElementSize( sizeof(T) );
0191 if(d_ptr)
0192 {
0193 buffer->setDevicePointer(optix_device_ordinal, d_ptr );
0194 }
0195 context[name]->set( buffer );
0196 }
0197
0198 template void Six::createContextInputBuffer( CSGNode*, unsigned, const char* ) ;
0199 template void Six::createContextInputBuffer( qat4*, unsigned, const char* ) ;
0200 template void Six::createContextInputBuffer( float*, unsigned, const char* ) ;
0201
0202
0203 void Six::setFoundry(const CSGFoundry* foundry_)
0204 {
0205 foundry = foundry_ ;
0206 createGeom();
0207 }
0208
0209 void Six::createGeom()
0210 {
0211 LOG(info) << "[" ;
0212 createContextInputBuffers();
0213 createGAS();
0214 createIAS();
0215 LOG(info) << "]" ;
0216 }
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235 void Six::createContextInputBuffers()
0236 {
0237 createContextInputBuffer<CSGNode>( foundry->d_node, foundry->getNumNode(), "node_buffer" );
0238 createContextInputBuffer<qat4>( foundry->d_itra, foundry->getNumItra(), "itra_buffer" );
0239 createContextInputBuffer<float4>( foundry->d_plan, foundry->getNumPlan(), "plan_buffer" );
0240 }
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253 optix::Geometry Six::createGeometry(unsigned solid_idx)
0254 {
0255 const CSGSolid* so = foundry->solid.data() + solid_idx ;
0256 unsigned primOffset = so->primOffset ;
0257 unsigned numPrim = so->numPrim ;
0258 CSGPrim* d_pr = foundry->d_prim + primOffset ;
0259
0260 LOG(info)
0261 << " solid_idx " << std::setw(3) << solid_idx
0262 << " numPrim " << std::setw(3) << numPrim
0263 << " primOffset " << std::setw(3) << primOffset
0264 << " d_pr " << d_pr
0265 ;
0266
0267 optix::Geometry solid = context->createGeometry();
0268 solid->setPrimitiveCount( numPrim );
0269 solid->setBoundingBoxProgram( context->createProgramFromPTXFile( geo_ptx_path , "bounds" ) );
0270 solid->setIntersectionProgram( context->createProgramFromPTXFile( geo_ptx_path , "intersect" ) ) ;
0271
0272 optix::Buffer prim_buffer = context->createBuffer( RT_BUFFER_INPUT, RT_FORMAT_USER, numPrim );
0273 prim_buffer->setElementSize( sizeof(CSGPrim) );
0274 prim_buffer->setDevicePointer(optix_device_ordinal, d_pr );
0275 solid["prim_buffer"]->set( prim_buffer );
0276
0277 return solid ;
0278 }
0279
0280 void Six::createGAS()
0281 {
0282 if( solid_selection.size() == 0 )
0283 {
0284 createGAS_Standard();
0285 }
0286 else
0287 {
0288 createGAS_Selection();
0289 }
0290 }
0291
0292 void Six::createGAS_Standard()
0293 {
0294 unsigned num_solid = foundry->getNumSolid();
0295 LOG(info) << "num_solid " << num_solid ;
0296
0297 for(unsigned i=0 ; i < num_solid ; i++)
0298 {
0299 if(SGeoConfig::IsEnabledMergedMesh(i))
0300 {
0301 LOG(info) << " create optix::Geometry solid/ mm " << i ;
0302 optix::Geometry solid = createGeometry(i);
0303 solids[i] = solid ;
0304 }
0305 else
0306 {
0307 LOG(error) << " emm skipping " << i ;
0308 }
0309 }
0310 }
0311
0312 void Six::createGAS_Selection()
0313 {
0314 unsigned num_solid = solid_selection.size() ;
0315 LOG(info) << "num_solid " << num_solid ;
0316 for(unsigned i=0 ; i < num_solid ; i++)
0317 {
0318 unsigned solidIdx = solid_selection[i] ;
0319 optix::Geometry solid = createGeometry(solidIdx);
0320 solids[solidIdx] = solid ;
0321 }
0322 }
0323
0324
0325 optix::Geometry Six::getGeometry(unsigned solid_idx) const
0326 {
0327 unsigned count = solids.count(solid_idx);
0328 LOG_IF(fatal, count == 0) << " FAILED to find solid_idx " << solid_idx ;
0329 assert( count <= 1 ) ;
0330 return solids.at(solid_idx);
0331 }
0332
0333
0334 void Six::createIAS()
0335 {
0336 if( solid_selection.size() == 0 )
0337 {
0338 createIAS_Standard();
0339 }
0340 else
0341 {
0342 createIAS_Selection();
0343 }
0344 }
0345
0346 void Six::createIAS_Standard()
0347 {
0348 unsigned num_ias = foundry->getNumUniqueIAS() ;
0349 for(unsigned i=0 ; i < num_ias ; i++)
0350 {
0351 unsigned ias_idx = 0 ;
0352 optix::Group ias = createIAS(ias_idx);
0353 groups.push_back(ias);
0354 }
0355 }
0356
0357 void Six::createIAS_Selection()
0358 {
0359 unsigned ias_idx = 0 ;
0360 optix::Group ias = createSolidSelectionIAS( ias_idx, solid_selection );
0361 groups.push_back(ias);
0362 }
0363
0364 optix::Group Six::createIAS(unsigned ias_idx)
0365 {
0366 unsigned tot_inst = foundry->getNumInst();
0367 unsigned num_inst = foundry->getNumInstancesIAS(ias_idx, emm);
0368 LOG(info)
0369 << " ias_idx " << ias_idx
0370 << " tot_inst " << tot_inst
0371 << " num_inst " << num_inst
0372 << " emm(hex) " << std::hex << emm << std::dec
0373 ;
0374 assert( num_inst > 0);
0375
0376 std::vector<qat4> inst ;
0377 foundry->getInstanceTransformsIAS(inst, ias_idx, emm );
0378 assert( inst.size() == num_inst );
0379
0380 optix::Group ias = createIAS(inst);
0381 return ias ;
0382 }
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392 optix::Group Six::createSolidSelectionIAS(unsigned ias_idx, const std::vector<unsigned>& solid_selection)
0393 {
0394 unsigned num_select = solid_selection.size() ;
0395 assert( num_select > 0 );
0396 float mxe = foundry->getMaxExtent(solid_selection);
0397
0398
0399 std::vector<qat4> inst ;
0400 int ins_idx = 0 ;
0401 unsigned middle = num_select/2 ;
0402
0403 for(unsigned i=0 ; i < num_select ; i++)
0404 {
0405 int ii = int(i) - int(middle) ;
0406
0407 int gas_idx = solid_selection[i] ;
0408 int sensor_identifier = -1 ;
0409 int sensor_index = -1 ;
0410
0411 qat4 q ;
0412 q.setIdentity(ins_idx, gas_idx, sensor_identifier, sensor_index );
0413 q.q3.f.x = 2.0*mxe*float(ii) ;
0414
0415 inst.push_back(q);
0416 ins_idx += 1 ;
0417 }
0418
0419 optix::Group ias = createIAS(inst);
0420 return ias ;
0421 }
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443 optix::Group Six::createIAS(const std::vector<qat4>& inst )
0444 {
0445 unsigned num_inst = inst.size() ;
0446 LOG(info) << " num_inst " << num_inst ;
0447
0448 const char* accel = "Trbvh" ;
0449 optix::Acceleration instance_accel = context->createAcceleration(accel);
0450 optix::Acceleration group_accel = context->createAcceleration(accel);
0451
0452 optix::Group group = context->createGroup();
0453 group->setChildCount( num_inst );
0454 group->setAcceleration( group_accel );
0455
0456 for(unsigned i=0 ; i < num_inst ; i++)
0457 {
0458 const qat4& qc = inst[i] ;
0459
0460 int ins_idx, gas_idx, sensor_identifier, sensor_index ;
0461 qc.getIdentity(ins_idx, gas_idx, sensor_identifier, sensor_index );
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475 const float* qcf = qc.cdata();
0476 qat4 q(qcf);
0477 q.clearIdentity();
0478
0479 optix::Transform xform = context->createTransform();
0480 bool transpose = true ;
0481 xform->setMatrix(transpose, q.data(), 0);
0482 group->setChild(i, xform);
0483
0484
0485 optix::GeometryInstance pergi = createGeometryInstance(gas_idx, ins_idx);
0486 optix::GeometryGroup perxform = context->createGeometryGroup();
0487 perxform->addChild(pergi);
0488 perxform->setAcceleration(instance_accel) ;
0489 xform->setChild(perxform);
0490 }
0491 return group ;
0492 }
0493
0494 optix::GeometryInstance Six::createGeometryInstance(unsigned gas_idx, unsigned ins_idx)
0495 {
0496
0497 optix::Geometry solid = getGeometry(gas_idx);
0498 optix::GeometryInstance pergi = context->createGeometryInstance() ;
0499 pergi->setMaterialCount(1);
0500 pergi->setMaterial(0, material );
0501 pergi->setGeometry(solid);
0502 pergi["identity"]->setUint(ins_idx);
0503 return pergi ;
0504 }
0505
0506 void Six::setTop(const char* spec)
0507 {
0508 char c = spec[0];
0509 assert( c == 'i' || c == 'g' );
0510 int idx = atoi( spec + 1 );
0511
0512 LOG(info) << "spec " << spec ;
0513 if( c == 'i' )
0514 {
0515 assert( idx < int(groups.size()) );
0516 optix::Group grp = groups[idx];
0517 context["top_object"]->set( grp );
0518 }
0519 else if( c == 'g' )
0520 {
0521 assert( idx < int(solids.size()) );
0522
0523 optix::GeometryGroup gg = context->createGeometryGroup();
0524 gg->setChildCount(1);
0525
0526 unsigned identity = 1u + idx ;
0527 optix::GeometryInstance pergi = createGeometryInstance(idx, identity);
0528 gg->setChild( 0, pergi );
0529 gg->setAcceleration( context->createAcceleration("Trbvh") );
0530
0531 context["top_object"]->set( gg );
0532 }
0533 }
0534
0535 void Six::launch(unsigned width, unsigned height, unsigned depth)
0536 {
0537 LOG(info) << "[ width " << width << " height " << height << " depth " << depth ;
0538 context->launch( entry_point_index , width, height, depth );
0539 LOG(info) << "]" ;
0540 }
0541