在Metal中手动设置1D纹理

时间:2014-11-02 00:39:59

标签: ios swift gpgpu metal

我正在尝试手动填充 1D纹理并将该纹理传递给计算着色器(这些是我想通过代码设置的2个像素,它们不代表任何图像)。

由于当前少量的Metal示例,我可以找到的所有示例都处理 2D纹理,它通过将加载的UIImage转换为原始字节数据来加载纹理,但创建了假的UIImage对我来说就像是一个黑客。

这是我开始的“天真”方式 -

...
var manualTextureData: [Float] = [ 1.0, 0.0, 0.0, 1.0,
                                   0.0, 0.0, 1.0, 1.0 ];
let region: MTLRegion = MTLRegionMake1D(0, textureDescriptor.width);
myTexture.replaceRegion(region, mipmapLevel: 0, withBytes: &manualTextureData, bytesPerRow: 0);

但是Metal无法识别着色器中的那些值(除第一个值外,它会获得空纹理)。

我很快意识到Float数组可能必须转换为字节数组(例如UInt8),但无法找到从[Float]转换为[UInt8]的方法

我考虑的另一个可能的选择是使用CVPixelBuffer对象,但这也是解决问题的方法。

那么解决这个问题的正确方法是什么?

提前致谢。

  • 请注意我不熟悉 Objective-C ,因此我不确定使用CVPixelBuffer / UIImage是否被夸大为什么应该是直的前进。

4 个答案:

答案 0 :(得分:0)

如果你想要一个float纹理,bytesPerRow的宽度应该是4倍,因为float的大小为4个字节。金属复制内存,不关心值。这是你的任务; - )

类似的东西:

myTexture.replaceRegion(region, mipmapLevel: 0, withBytes: &manualTextureData, bytesPerRow: manualTextureData.count * sizeof(Float));

答案 1 :(得分:0)

我没有看到你使用1D纹理传递数据的任何理由。相反,我只会传递一个缓冲区。像这样:

var dataBuffer:MTLBuffer? = device.newBufferWithBytes(&manualTextureData, length: sizeOf(manualTextureData), options: MTLResourceOptions.OptionCPUCacheModeDefault)

然后你把它挂钩到你的renderCommandEncoder

renderCommandEncoder.setFragmentBuffer(dataBuffer, offset: 0, atIndex: 1)//Note that if you want this buffer to be passed to you vertex shader you should use setVertexBuffer

然后在着色器中,您应该添加像const device float* bufferPassed [[ buffer(1) ]]

这样的参数

然后在着色器实现中使用它:

float firstFloat = bufferPassed[0];

这将完成工作。

答案 2 :(得分:0)

并没有真正回答您的问题,但您可以在金属着色器中定义一个数组,而不是将值作为纹理传递。

类似的东西:

constant float manualData[8] = { 1.0, 0.0, 0.0, 1.0,
                               0.0, 0.0, 1.0, 1.0 };

vertex float4 world_vertex(unsigned int vid[[vertex_id]], ...) {
    int manualIndex = vid % 8;
    float manualValue = manualData[manualIndex];
    // something deep and meaningful here...
    return float4(manualValue);
}

答案 3 :(得分:0)

请原谅我的简短回复,但您可能会发现使用Swift和Metal查看我的实验很有用。我在Swift中创建了一个粒子系统,它作为粒子结构的一维数组传递给Metal计算着色器。通过使用posix_memalign,我可以消除在Metal和Swift之间传递数组所造成的瓶颈。

我在博客上发表了大量文章:http://flexmonkey.blogspot.co.uk/search/label/Metal

我希望这会有所帮助。

西蒙