我正在将PoissonRecon代码here集成到我自己的网格操作代码中,但由于每个位移指令中的“非法指令”错误,我无法在x64中编译集成代码。泊松码的八叉树生成。
我正在使用Visual Studio 2015,只有在x64中编译时才会出现问题,并且仅在处于发布模式时(即,它在x86调试和发布以及x64调试中工作)。
作为其中一个bitshift指令的示例,以下内容在Octree.inl的顶部定义:
template< class NodeData > const int OctNode< NodeData >::DepthShift=5;
template< class NodeData > const int OctNode< NodeData >::OffsetShift = ( sizeof(long long)*8 - DepthShift ) / 3;
template< class NodeData > const int OctNode< NodeData >::DepthMask=(1<<DepthShift)-1; // This variable is correct
template< class NodeData > const int OctNode< NodeData >::OffsetMask=(1<<OffsetShift)-1; // This variable is also correct
template< class NodeData > const int OctNode< NodeData >::OffsetShift1=DepthShift;
template< class NodeData > const int OctNode< NodeData >::OffsetShift2=OffsetShift1+OffsetShift;
template< class NodeData > const int OctNode< NodeData >::OffsetShift3=OffsetShift2+OffsetShift;
这些变量用于以下函数:
template< class NodeData >
inline unsigned long long OctNode< NodeData >::Index( int depth , const int offset[3] )
{
unsigned long long idx=0;
idx |= ( ( (unsigned long long)(depth ) ) & DepthMask );
idx |= ( ( (unsigned long long)(offset[0]) ) & OffsetMask ) << OffsetShift1;
idx |= ( ( (unsigned long long)(offset[1]) ) & OffsetMask ) << OffsetShift2;
idx |= ( ( (unsigned long long)(offset[2]) ) & OffsetMask ) << OffsetShift3;
return idx;
}
此功能在
行中断idx |= ( ( (unsigned long long)(offset[0]) ) & OffsetMask ) << OffsetShift1;
我进一步分解并发现问题本身是位移,即(var)<<OffsetShift1;
,但这会导致“非法指令”错误。
请注意,OffsetShift1只是“5”,所以这相当于(var)<<5;
,它可以按预期工作。
一种可能的解决方法是在顶部简单地#define
所有这些变量(这确实解决了问题),但这并不能解决其他位移问题,如下所示:
void _startAndWidth( const TreeOctNode* node , Point3D< Real >& start , Real& width ) const
{
LocalDepth d ; LocalOffset off;
_localDepthAndOffset( node , d , off );
if (d >= 0) width = Real(1.0 / (1 << d));
else width = Real( 1.0 * (1<<(-d)) );
for( int dd=0 ; dd<DIMENSION ; dd++ ) start[dd] = Real( off[dd] ) * width;
}
我试过static_cast<long long>
一切,但这不是溢出问题。更奇怪的是,如果我在位移前(在释放模式下)中断然后突出显示操作,调试器会告诉我正确的结果(例如,d = 5
中的_startAndWidth
,所以{{1在调试器中返回32)但实际上单步执行操作会导致“非法指令”错误。
由于程序在调试模式下正常工作,我尝试在发布模式下删除所有优化,但我仍然得到相同的错误。我发现的唯一解决方法是用1 << d
代替所有的位移操作,虽然这样做,但它似乎是pow()
荒谬的。
答案 0 :(得分:1)
事实证明,重建代码附带的.sln文件是使用AVX2设置的,我的机器上不支持。
转到Configuration Properties >> C/C++ >> Code Generation
并为AVX设置“启用增强指令集”解决了这个问题。
汇编代码现在显示“SHL”而不是“SHLX”,因此“非法指令”是实际的SHLX命令不可用,而不是参数进入SHLX的问题。