将值写入 iOS Metal 中的 float4x4 矩阵 - 替换现有浮点值

如何解决将值写入 iOS Metal 中的 float4x4 矩阵 - 替换现有浮点值

我正在尝试制作一个缓冲区来计算均匀间隔网格的某些单元格中的粒子/点(每个粒子都将根据其位置添加一个单元格中)。然后将每个粒子的索引存储在与每个单元格对应的 float4x4 矩阵中,以供稍后查找。我正在使用原子计数器为每个单元格添加一个粒子数,以便粒子数不超过 16,并使用此计数器将粒子索引依次添加到矩阵中。

当行数或列数>4,即下一列/行时,位置[0]处的索引写入0.0。我不确定这是否与在 float4x4 矩阵中覆盖列的方式有关,或者是否与为 float4x4 分配内存/指针的方式有关。基本上,我只想按顺序添加和更改单个值,而不影响矩阵中的现有值。

非常感谢任何帮助,非常感谢!

这是内核:

kernel void findCellandCount(  device Particle *particles [[ buffer(0) ]],volatile device atomic_uint *cellCountArray [[buffer(1)]],device float4x4* cellIndicesBuffer [[ buffer(2) ]],uint id [[ thread_position_in_grid ]]) {
  
    uint particleIndex = id;
    
    Particle particle = particles[particleIndex];

    const float cellSize = Params().cellWidth;

*// GET CELL INDEX:*

    int2 cellIndex = int2(fast::floor(particle.position.x / cellSize),fast::floor(particle.position.y / cellSize)); 

    uint flatCellIndex = GetFlatCellIndex(cellIndex,numberGridCells); // this is in the range 0-15 (16 cells)
    
    // This is a counter to store particle count in each cell // this is reset to zero each frame:
    int cellCounter = atomic_fetch_add_explicit(&cellCountArray[flatCellIndex],1,memory_order_relaxed);
        
    if (cellCounter < 16) { // i.e. count is less than 4x4 float matrix 

        uint a = cellCounter % 4;
        uint b = cellCounter / 4;

    //m[index][column][row]

        cellIndicesBuffer[flatCellIndex][a][b] = id; // this writes the particle index to the float4x4
 
    }
  
}

这是单元格的输出

Cell:  3 cell indices:  simd_float4x4([[23.0,0.0,0.0],[25.0,[44.0,[61.0,0.0]])

^ 这个输出符合预期,4 个索引存储在前 4 行

Cell:  8 cell indices:  simd_float4x4([[0.0,38.0,[0.0,39.0,42.0,63.0,0.0]])

^ 这里存储了 8 个索引,但位置 [0] 处的值被 0.0 覆盖/替换。

Cell:  9 cell indices:  simd_float4x4([[0.0,35.0,45.0,[13.0,[28.0,0.0]])

^ 这里存储了 6 个索引,但第一个位置的值再次被覆盖。

解决方法

认为我知道发生了什么。在您的代码中

cellIndicesBuffer[flatCellIndex][a][b] = id;

我认为那条线的效果本质上是这样的:

float4x4 temp = cellIndicesBuffer[flatCellIndex];
temp[a][b] = id;
cellIndicesBuffer[flatCellIndex] = temp;

虽然您使用 atomic_uint 来防止 cellCountArray 数组元素上的数据竞争,但您并没有使用 cellIndicesBuffer 元素来防止它,这样做会有问题无论如何都是为了性能。

我认为,问题源于 float4x4 是 SIMD 类型 - 本质上是 struct。我建议它将整个内容读入 gpu 线程本地内存(可能是寄存器),更新元素,然后将整个内容写回数组,覆盖可能已写入的 float4x4 元素由其他线程在中间时间。为避免这种情况,您只需要处理要更新的元素,而无需通过 float4x4,您可以通过将 cellIndicesBuffer 重新转换为 float* 来实现。

auto i = flatCellIndex * 16 + a * 4 + b;
reinterpret_cast<device float*>(cellIndicesBuffer)[i] = id;

如果您打算在继续下一列之前使用连续的 cellCounter 值填充每一列,您可以消除 ab

auto i = flatCellIndex * 16 + cellCounter;
reinterpret_cast<device float*>(cellIndicesBuffer)[i] = id;

我应该提到,负责任的 C++ 程序员可能对我在这里使用 reinterpret_cast 感到畏缩是正确的。如果您不需要在着色器函数中的其他任何地方专门使用 cellIndicesBuffer 作为 device float4x4*,而您在代码中没有提供,最好将参数类型更改为 { {1}}。那么您就不必执行device float*。您不需要对 Swift 代码进行任何更改。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?