我希望能够定义一个MTLBuffer并将数据直接填充到缓冲区中(或尽可能高效地)。

如果执行以下操作,则着色器中使用的值为1.0和2.0(分别用于X和Y),而不是在创建MTLBuffer之后设置的3.0和4.0。

int bufferLength = 128 * 128;

float pointBuffer[bufferLength * 2]; // 2 for X and Y

//Populate array with test values
for (int i = 0; i < (bufferLength * 2); i += 2) {
    pointBuffer[i] = 1.0;       //X
    pointBuffer[i + 1] = 2.0;   //Y
}

id<MTLBuffer> pointDataBuffer = [device newBufferWithBytes:&pointBuffer length:sizeof(pointBuffer) options:MTLResourceOptionCPUCacheModeDefault];

//Populate array with updated test values
for (int i = 0; i < (bufferLength * 2); i += 2) {
    pointBuffer[i] = 3.0;       //X
    pointBuffer[i + 1] = 4.0;   //Y
}

//In the (Swift) class with the pipeline:
commandEncoder!.setBuffer(pointDataBuffer, offset: 0, index: 4)

根据文档,似乎我需要调用didModifyRange:,但pointDataBuffer似乎无法识别选择器。

有没有一种方法可以更新数组而不必重新创建MTLBuffer?

最佳答案

-newBufferWithBytes:...复制传入的字节数。它不会一直引用它们。因此,对pointBuffer的后续更改不会影响它。

但是,像这样的缓冲区(存储模式不是 private 的)可以通过-contents方法访问其存储。因此,您可以执行以下操作:

float *points = pointDataBuffer.contents;
for (int i = 0; i < (bufferLength * 2); i += 2) {
    points[i] = 3.0;       //X
    points[i + 1] = 4.0;   //Y
}

不过要小心。 CPU和GPU相对于彼此异步运行。如果GPU可能正在处理引用该缓冲区的命令,则从CPU对其进行修改可能会干扰这些命令的操作。因此,您将需要采取步骤来同步对缓冲区的访问,否则将避免同时进行CPU和GPU访问。

09-05 08:17