Files
nvidia--tensorrt/plugin/common/kernels/voxelGeneratorKernels.cu
T
wehub-resource-sync c8a779b1bb
Docker Image CI / build-ubuntu2004 (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:36:55 +08:00

413 lines
16 KiB
Plaintext

/*
* SPDX-FileCopyrightText: Copyright (c) 1993-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <iostream>
#include <cuda_runtime_api.h>
namespace nvinfer1
{
namespace plugin
{
__global__ void generateVoxels_kernel(
int max_num_points,
float *points, unsigned int* points_size,
float min_x_range, float max_x_range,
float min_y_range, float max_y_range,
float min_z_range, float max_z_range,
float pillar_x_size, float pillar_y_size, float pillar_z_size,
int grid_y_size, int grid_x_size, int num_point_values,
int max_points_per_voxel,
unsigned int *mask, float *voxels)
{
int point_idx = blockIdx.x * blockDim.x + threadIdx.x;
int batch_idx = point_idx / max_num_points;
int point_idx_in_frame = point_idx % max_num_points;
if(point_idx_in_frame >= points_size[batch_idx]) return;
float px = points[num_point_values * point_idx];
float py = points[num_point_values * point_idx + 1];
float pz = points[num_point_values * point_idx + 2];
float pw = points[num_point_values * point_idx + 3];
float pt;
if (num_point_values == 5) {
pt = points[num_point_values * point_idx + 4];
}
if(px<min_x_range||px>=max_x_range
|| py<min_y_range||py>=max_y_range
|| pz<min_z_range||pz>=max_z_range) return;
int voxel_idx = floorf((px - min_x_range)/pillar_x_size);
int voxel_idy = floorf((py - min_y_range)/pillar_y_size);
unsigned int voxel_index = (batch_idx * grid_y_size + voxel_idy) * grid_x_size + voxel_idx;
unsigned int point_id = atomicAdd(&(mask[voxel_index]), 1);
if(point_id >= max_points_per_voxel) return;
float *address = voxels + (voxel_index*max_points_per_voxel + point_id)*num_point_values;
atomicExch(address+0, px);
atomicExch(address+1, py);
atomicExch(address+2, pz);
atomicExch(address+3, pw);
if (num_point_values == 5) {
atomicExch(address+4, pt);
}
}
__global__ void generateBaseFeatures_kernel(
int batch_size,
unsigned int *mask, float *voxels,
int grid_y_size, int grid_x_size,
unsigned int *pillar_num,
int max_pillar_num,
int max_points_per_voxel,
int num_point_values,
float *voxel_features,
unsigned int *voxel_num_points,
unsigned int *coords)
{
int voxel_id = blockIdx.x * blockDim.x + threadIdx.x;
int voxel_idx = voxel_id % grid_x_size;
int voxel_idy = (voxel_id / grid_x_size) % grid_y_size;
int batch_id = voxel_id / (grid_y_size * grid_x_size);
if (batch_id >= batch_size) return;
unsigned int count = mask[voxel_id];
if( !(count>0) ) return;
count = count<max_points_per_voxel?count:max_points_per_voxel;
int current_pillarId = 0;
current_pillarId = atomicAdd(pillar_num + batch_id, 1);
voxel_num_points[batch_id * grid_y_size * grid_x_size + current_pillarId] = count;
int4 coord = {0, 0, voxel_idy, voxel_idx};
((int4*)coords)[batch_id * max_pillar_num + current_pillarId] = coord;
for (int i=0; i<count; i++){
int inIndex = voxel_id*max_points_per_voxel + i;
int outIndex = (batch_id * grid_x_size * grid_y_size + current_pillarId)*max_points_per_voxel + i;
if (num_point_values == 4) {
((float4*)voxel_features)[outIndex] = ((float4*)voxels)[inIndex];
}
else if (num_point_values == 5) {
for(int k=0; k<5;k++)
voxel_features[5 * outIndex + k] = voxels[5 * inIndex + k];
}
}
}
void generateVoxels_launch(
int batch_size, int max_num_points,
float *points, unsigned int* points_size,
float min_x_range, float max_x_range,
float min_y_range, float max_y_range,
float min_z_range, float max_z_range,
float pillar_x_size, float pillar_y_size, float pillar_z_size,
int grid_y_size, int grid_x_size, int num_point_values,
int max_points_per_voxel,
unsigned int *mask, float *voxels,
cudaStream_t stream)
{
int threadNum = 256;
dim3 blocks((batch_size * max_num_points + threadNum - 1) / threadNum);
dim3 threads(threadNum);
generateVoxels_kernel<<<blocks, threads, 0, stream>>>
(max_num_points,
points, points_size,
min_x_range, max_x_range,
min_y_range, max_y_range,
min_z_range, max_z_range,
pillar_x_size, pillar_y_size, pillar_z_size,
grid_y_size, grid_x_size, num_point_values,
max_points_per_voxel,
mask, voxels);
}
void generateBaseFeatures_launch(
int batch_size,
unsigned int *mask, float *voxels,
int grid_y_size, int grid_x_size,
unsigned int *pillar_num,
int max_pillar_num,
int max_points_per_voxel,
int num_point_values,
float *voxel_features,
unsigned int *voxel_num_points,
unsigned int *coords,
cudaStream_t stream)
{
int blockSize = 1024;
dim3 threads(blockSize);
dim3 blocks((batch_size * grid_y_size * grid_x_size + blockSize - 1) / blockSize);
generateBaseFeatures_kernel<<<blocks, threads, 0, stream>>>
(
batch_size,
mask, voxels, grid_y_size, grid_x_size,
pillar_num,
max_pillar_num,
max_points_per_voxel,
num_point_values,
voxel_features,
voxel_num_points,
coords
);
}
__global__ void generateFeatures_kernel(
int batch_size,
int dense_pillar_num,
float* voxel_features,
unsigned int* voxel_num_points,
unsigned int* coords, unsigned int *params,
float voxel_x, float voxel_y, float voxel_z,
float range_min_x, float range_min_y, float range_min_z,
unsigned int voxel_features_size, unsigned int max_points,
unsigned int max_voxels,
float* features)
{
int warp_size = max_points;
int pillar_idx = blockIdx.x * 4 + threadIdx.x/warp_size;
int point_idx = threadIdx.x % warp_size;
// In case the actual number of points is less than warp_size
// E.g., warp_size=32, max_points=20
if (point_idx >= max_points) return;
int batch_idx = pillar_idx / max_voxels;
if (batch_idx >= batch_size) return;
int pillar_idx_in_frame = pillar_idx % max_voxels;
int dense_pillar_idx = pillar_idx_in_frame + dense_pillar_num * batch_idx;
int pillar_idx_inBlock = threadIdx.x/warp_size;
// Limit number of voxels to max_voxels
unsigned int num_pillars = params[batch_idx] > max_voxels ? max_voxels : params[batch_idx];
// Update max_voxel to actual number
if (pillar_idx_in_frame == 0 && point_idx == 0) {
params[batch_idx] = num_pillars;
}
if (pillar_idx_in_frame >= num_pillars) return;
//load src
__shared__ float pillarSM[4][64][5]; // up to 64 points per pillar
__shared__ float4 pillarSumSM[4]; //4*4
__shared__ int4 cordsSM[4]; //4*4
__shared__ int pointsNumSM[4]; //4
__shared__ float pillarOutSM[4][64][11]; // up to 11 features per point
if (point_idx == 0) {
pointsNumSM[pillar_idx_inBlock] = voxel_num_points[dense_pillar_idx];
cordsSM[pillar_idx_inBlock] = ((int4*)coords)[dense_pillar_idx];
pillarSumSM[pillar_idx_inBlock] = {0,0,0,0};
}
for(int k=0; k<5; k++) {
pillarSM[pillar_idx_inBlock][point_idx][k] = voxel_features[5 * (dense_pillar_idx*max_points + point_idx) + k];
}
__syncthreads();
//calculate sm
if (point_idx < pointsNumSM[pillar_idx_inBlock]) {
atomicAdd(&(pillarSumSM[pillar_idx_inBlock].x), pillarSM[pillar_idx_inBlock][point_idx][0]);
atomicAdd(&(pillarSumSM[pillar_idx_inBlock].y), pillarSM[pillar_idx_inBlock][point_idx][1]);
atomicAdd(&(pillarSumSM[pillar_idx_inBlock].z), pillarSM[pillar_idx_inBlock][point_idx][2]);
}
__syncthreads();
//feature-mean
float4 mean;
float validPoints = pointsNumSM[pillar_idx_inBlock];
mean.x = pillarSumSM[pillar_idx_inBlock].x / validPoints;
mean.y = pillarSumSM[pillar_idx_inBlock].y / validPoints;
mean.z = pillarSumSM[pillar_idx_inBlock].z / validPoints;
mean.x = pillarSM[pillar_idx_inBlock][point_idx][0] - mean.x;
mean.y = pillarSM[pillar_idx_inBlock][point_idx][1] - mean.y;
mean.z = pillarSM[pillar_idx_inBlock][point_idx][2] - mean.z;
//calculate offset
float x_offset = voxel_x / 2.0f + cordsSM[pillar_idx_inBlock].w * voxel_x + range_min_x;
float y_offset = voxel_y / 2.0f + cordsSM[pillar_idx_inBlock].z * voxel_y + range_min_y;
float z_offset = voxel_z / 2.0f + cordsSM[pillar_idx_inBlock].y * voxel_z + range_min_z;
//feature-offset
float4 center;
center.x = pillarSM[pillar_idx_inBlock][point_idx][0] - x_offset;
center.y = pillarSM[pillar_idx_inBlock][point_idx][1] - y_offset;
center.z = pillarSM[pillar_idx_inBlock][point_idx][2] - z_offset;
//store output
if (point_idx < pointsNumSM[pillar_idx_inBlock]) {
for(int k=0; k<5; k++)
pillarOutSM[pillar_idx_inBlock][point_idx][k] = pillarSM[pillar_idx_inBlock][point_idx][k];
pillarOutSM[pillar_idx_inBlock][point_idx][5] = mean.x;
pillarOutSM[pillar_idx_inBlock][point_idx][5 + 1] = mean.y;
pillarOutSM[pillar_idx_inBlock][point_idx][5 + 2] = mean.z;
pillarOutSM[pillar_idx_inBlock][point_idx][5 + 3] = center.x;
pillarOutSM[pillar_idx_inBlock][point_idx][5 + 4] = center.y;
if (5 + 5 < voxel_features_size)
pillarOutSM[pillar_idx_inBlock][point_idx][warp_size + 5] = center.z;
} else {
for (int k = 0; k < voxel_features_size; k++)
pillarOutSM[pillar_idx_inBlock][point_idx][k] = 0;
}
__syncthreads();
for(int i = 0; i < voxel_features_size; i ++) {
int outputSMId = pillar_idx_inBlock*64*11 + point_idx * 11 + i;
int outputId = pillar_idx*max_points*voxel_features_size + point_idx * voxel_features_size + i;
features[outputId] = ((float*)pillarOutSM)[outputSMId] ;
}
}
__global__ void generateFeatures_kernel_4x(
int batch_size,
int dense_pillar_num,
float* voxel_features,
unsigned int* voxel_num_points, unsigned int* coords,
unsigned int *params,
float voxel_x, float voxel_y, float voxel_z,
float range_min_x, float range_min_y, float range_min_z,
unsigned int voxel_features_size, unsigned int max_points,
unsigned int max_voxels,
float* features)
{
int warp_size = max_points;
int pillar_idx = blockIdx.x * 4 + threadIdx.x / warp_size;
int point_idx = threadIdx.x % warp_size;
// In case the actual number of points is less than warp_size
// E.g., warp_size=32, max_points=20
if (point_idx >= max_points) return;
int batch_idx = pillar_idx / max_voxels;
if (batch_idx >= batch_size) return;
int pillar_idx_in_frame = pillar_idx % max_voxels;
int dense_pillar_idx = pillar_idx_in_frame + dense_pillar_num * batch_idx;
int pillar_idx_inBlock = threadIdx.x / warp_size;
// Limit number of voxels to max_voxels
unsigned int num_pillars = params[batch_idx] > max_voxels ? max_voxels : params[batch_idx];
// Update max_voxel to actual number
if (pillar_idx_in_frame == 0 && point_idx == 0) {
params[batch_idx] = num_pillars;
}
if (pillar_idx_in_frame >= num_pillars) return;
//load src
__shared__ float4 pillarSM[4][64]; // up to 64 points per pillar
__shared__ float4 pillarSumSM[4]; //4*4
__shared__ int4 cordsSM[4]; //4*4
__shared__ int pointsNumSM[4]; //4
__shared__ float pillarOutSM[4][64][11]; // up to 11 output features per point
if (point_idx == 0) {
pointsNumSM[pillar_idx_inBlock] = voxel_num_points[dense_pillar_idx];
cordsSM[pillar_idx_inBlock] = ((int4*)coords)[pillar_idx];
pillarSumSM[pillar_idx_inBlock] = {0,0,0,0};
}
pillarSM[pillar_idx_inBlock][point_idx] = ((float4*)voxel_features)[dense_pillar_idx*max_points + point_idx];
__syncthreads();
//calculate sm
if (point_idx < pointsNumSM[pillar_idx_inBlock]) {
atomicAdd(&(pillarSumSM[pillar_idx_inBlock].x), pillarSM[pillar_idx_inBlock][point_idx].x);
atomicAdd(&(pillarSumSM[pillar_idx_inBlock].y), pillarSM[pillar_idx_inBlock][point_idx].y);
atomicAdd(&(pillarSumSM[pillar_idx_inBlock].z), pillarSM[pillar_idx_inBlock][point_idx].z);
}
__syncthreads();
//feature-mean
float4 mean;
float validPoints = pointsNumSM[pillar_idx_inBlock];
mean.x = pillarSumSM[pillar_idx_inBlock].x / validPoints;
mean.y = pillarSumSM[pillar_idx_inBlock].y / validPoints;
mean.z = pillarSumSM[pillar_idx_inBlock].z / validPoints;
mean.x = pillarSM[pillar_idx_inBlock][point_idx].x - mean.x;
mean.y = pillarSM[pillar_idx_inBlock][point_idx].y - mean.y;
mean.z = pillarSM[pillar_idx_inBlock][point_idx].z - mean.z;
//calculate offset
float x_offset = voxel_x / 2.0f + cordsSM[pillar_idx_inBlock].w * voxel_x + range_min_x;
float y_offset = voxel_y / 2.0f + cordsSM[pillar_idx_inBlock].z * voxel_y + range_min_y;
float z_offset = voxel_z / 2.0f + cordsSM[pillar_idx_inBlock].y * voxel_z + range_min_z;
//feature-offset
float4 center;
center.x = pillarSM[pillar_idx_inBlock][point_idx].x - x_offset;
center.y = pillarSM[pillar_idx_inBlock][point_idx].y - y_offset;
center.z = pillarSM[pillar_idx_inBlock][point_idx].z - z_offset;
//store output
if (point_idx < pointsNumSM[pillar_idx_inBlock]) {
pillarOutSM[pillar_idx_inBlock][point_idx][0] = pillarSM[pillar_idx_inBlock][point_idx].x;
pillarOutSM[pillar_idx_inBlock][point_idx][1] = pillarSM[pillar_idx_inBlock][point_idx].y;
pillarOutSM[pillar_idx_inBlock][point_idx][2] = pillarSM[pillar_idx_inBlock][point_idx].z;
pillarOutSM[pillar_idx_inBlock][point_idx][3] = pillarSM[pillar_idx_inBlock][point_idx].w;
pillarOutSM[pillar_idx_inBlock][point_idx][4] = mean.x;
pillarOutSM[pillar_idx_inBlock][point_idx][5] = mean.y;
pillarOutSM[pillar_idx_inBlock][point_idx][6] = mean.z;
pillarOutSM[pillar_idx_inBlock][point_idx][7] = center.x;
pillarOutSM[pillar_idx_inBlock][point_idx][8] = center.y;
pillarOutSM[pillar_idx_inBlock][point_idx][9] = center.z;
} else {
pillarOutSM[pillar_idx_inBlock][point_idx][0] = 0;
pillarOutSM[pillar_idx_inBlock][point_idx][1] = 0;
pillarOutSM[pillar_idx_inBlock][point_idx][2] = 0;
pillarOutSM[pillar_idx_inBlock][point_idx][3] = 0;
pillarOutSM[pillar_idx_inBlock][point_idx][4] = 0;
pillarOutSM[pillar_idx_inBlock][point_idx][5] = 0;
pillarOutSM[pillar_idx_inBlock][point_idx][6] = 0;
pillarOutSM[pillar_idx_inBlock][point_idx][7] = 0;
pillarOutSM[pillar_idx_inBlock][point_idx][8] = 0;
pillarOutSM[pillar_idx_inBlock][point_idx][9] = 0;
}
__syncthreads();
for(int i = 0; i < voxel_features_size; i ++) {
int outputSMId = pillar_idx_inBlock*64*11 + point_idx * 11 + i;
int outputId = pillar_idx*max_points*voxel_features_size + point_idx * voxel_features_size + i;
features[outputId] = ((float*)pillarOutSM)[outputSMId] ;
}
}
int generateFeatures_launch(
int batch_size,
int dense_pillar_num,
float* voxel_features,
unsigned int* voxel_num_points,
unsigned int* coords,
unsigned int *params,
float voxel_x, float voxel_y, float voxel_z,
float range_min_x, float range_min_y, float range_min_z,
unsigned int voxel_features_size, unsigned int max_points,
unsigned int max_voxels, unsigned int num_point_values,
float* features,
cudaStream_t stream)
{
unsigned int warp_size = max_points;
dim3 blocks((batch_size * max_voxels + 3) / 4);
dim3 threads(4*warp_size);
if (num_point_values == 4) {
generateFeatures_kernel_4x<<<blocks, threads, 0, stream>>>
(batch_size,
dense_pillar_num,
voxel_features,
voxel_num_points,
coords,
params,
voxel_x, voxel_y, voxel_z,
range_min_x, range_min_y, range_min_z,
voxel_features_size, max_points,
max_voxels,
features);
}
else {
generateFeatures_kernel<<<blocks, threads, 0, stream>>>
(batch_size,
dense_pillar_num,
voxel_features,
voxel_num_points,
coords,
params,
voxel_x, voxel_y, voxel_z,
range_min_x, range_min_y, range_min_z,
voxel_features_size, max_points,
max_voxels,
features);
}
auto err = cudaGetLastError();
if (cudaSuccess != err) {
fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err));
exit(-1);
}
return err;
}
} // namespace plugin
} // namespace nvinfer1