|
| 1 | +#include "MRCudaPointsProject.cuh" |
| 2 | +#include "MRCudaPointsProject.h" |
| 3 | + |
| 4 | +#include "MRCudaBasic.cuh" |
| 5 | +#include "MRCudaBasic.h" |
| 6 | +#include "MRCudaMath.h" |
| 7 | +#include "MRCudaPointCloud.h" |
| 8 | + |
| 9 | +#include "MRMesh/MRAffineXf3.h" |
| 10 | +#include "MRMesh/MRBitSet.h" |
| 11 | +#include "MRMesh/MRChunkIterator.h" |
| 12 | +#include "MRMesh/MRProgressCallback.h" |
| 13 | + |
| 14 | +static_assert( sizeof( MR::Cuda::PointsProjectionResult ) == sizeof( MR::PointsProjectionResult ) ); |
| 15 | + |
| 16 | +namespace MR::Cuda |
| 17 | +{ |
| 18 | + |
| 19 | +Expected<std::vector<MR::PointsProjectionResult>> findProjectionOnPoints( const PointCloud& pointCloud, |
| 20 | + const std::vector<Vector3f>& points, const FindProjectionOnPointsSettings& settings ) |
| 21 | +{ |
| 22 | + std::vector<MR::PointsProjectionResult> results; |
| 23 | + PointsProjector projector; |
| 24 | + return projector.setPointCloud( pointCloud ) |
| 25 | + .and_then( [&] { return projector.findProjections( results, points, settings ); } ) |
| 26 | + .transform( [&] { return results; } ); |
| 27 | +} |
| 28 | + |
| 29 | +Expected<void> PointsProjector::setPointCloud( const PointCloud& pointCloud ) |
| 30 | +{ |
| 31 | + if ( auto res = copyDataFrom( pointCloud ) ) |
| 32 | + { |
| 33 | + data_ = std::move( *res ); |
| 34 | + return {}; |
| 35 | + } |
| 36 | + else |
| 37 | + { |
| 38 | + return unexpected( std::move( res.error() ) ); |
| 39 | + } |
| 40 | +} |
| 41 | + |
| 42 | +Expected<void> PointsProjector::findProjections( std::vector<MR::PointsProjectionResult>& results, |
| 43 | + const std::vector<Vector3f>& points, const FindProjectionOnPointsSettings& settings ) const |
| 44 | +{ |
| 45 | + if ( !data_ ) |
| 46 | + return unexpected( "No reference point cloud is set" ); |
| 47 | + |
| 48 | + const auto totalSize = points.size(); |
| 49 | + const auto bufferSize = maxBufferSize( getCudaSafeMemoryLimit(), totalSize, sizeof( float3 ) + sizeof( PointsProjectionResult ) ); |
| 50 | + |
| 51 | + DynamicArray<float3> cudaPoints; |
| 52 | + CUDA_LOGE_RETURN_UNEXPECTED( cudaPoints.resize( bufferSize ) ); |
| 53 | + |
| 54 | + DynamicArray<PointsProjectionResult> cudaResult; |
| 55 | + CUDA_LOGE_RETURN_UNEXPECTED( cudaResult.resize( bufferSize ) ); |
| 56 | + |
| 57 | + results.resize( totalSize ); |
| 58 | + |
| 59 | + DynamicArray<uint64_t> cudaValid; |
| 60 | + if ( settings.valid ) |
| 61 | + { |
| 62 | + assert( points.size() <= settings.valid->size() ); |
| 63 | + std::vector<uint64_t> validVec; |
| 64 | + boost::to_block_range( *settings.valid, std::back_inserter( validVec ) ); |
| 65 | + CUDA_LOGE_RETURN_UNEXPECTED( cudaValid.fromVector( validVec ) ); |
| 66 | + } |
| 67 | + |
| 68 | + const auto cudaXf = settings.xf ? fromXf( *settings.xf ) : Matrix4{}; |
| 69 | + |
| 70 | + if ( !reportProgress( settings.cb, 0.60f ) ) |
| 71 | + return unexpectedOperationCanceled(); |
| 72 | + |
| 73 | + const auto cb1 = subprogress( settings.cb, 0.60f, 1.00f ); |
| 74 | + const auto iterCount = chunkCount( totalSize, bufferSize ); |
| 75 | + size_t iterIndex = 0; |
| 76 | + |
| 77 | + for ( const auto [offset, size] : splitByChunks( totalSize, bufferSize ) ) |
| 78 | + { |
| 79 | + const auto cb2 = subprogress( cb1, iterIndex++, iterCount ); |
| 80 | + |
| 81 | + CUDA_LOGE_RETURN_UNEXPECTED( cudaPoints.copyFrom( points.data() + offset, size ) ); |
| 82 | + |
| 83 | + findProjectionOnPointsKernel( cudaResult.data(), data_->data(), cudaPoints.data(), settings.valid ? cudaValid.data() : nullptr, cudaXf, settings.upDistLimitSq, settings.loDistLimitSq, settings.skipSameIndex, size, offset ); |
| 84 | + CUDA_LOGE_RETURN_UNEXPECTED( cudaGetLastError() ); |
| 85 | + if ( !reportProgress( cb2, 0.33f ) ) |
| 86 | + return unexpectedOperationCanceled(); |
| 87 | + |
| 88 | + CUDA_LOGE_RETURN_UNEXPECTED( cudaResult.copyTo( results.data() + offset, size ) ); |
| 89 | + if ( !reportProgress( cb2, 1.00f ) ) |
| 90 | + return unexpectedOperationCanceled(); |
| 91 | + } |
| 92 | + |
| 93 | + return {}; |
| 94 | +} |
| 95 | + |
| 96 | +size_t findProjectionOnPointsHeapBytes( const PointCloud& pointCloud, size_t pointsCount ) |
| 97 | +{ |
| 98 | + constexpr size_t cMinCudaBufferSize = 1 << 24; // 16 MiB |
| 99 | + return |
| 100 | + pointCloudHeapBytes( pointCloud ) |
| 101 | + + std::min( ( sizeof( float3 ) + sizeof( PointsProjectionResult ) ) * pointsCount, cMinCudaBufferSize ); |
| 102 | +} |
| 103 | + |
| 104 | +} // namespace MR::Cuda |
0 commit comments