如何在Metal中将一系列float3值从CPU传递到GPU?

时间:2017-11-15 10:49:45

标签: ios metal metal-performance-shaders

我需要将颜色值作为数组传递给着色器。现在我将它作为结构RGBColors传递并将其作为一个结构接收它并且它工作正常。

但我希望在着色器中将其作为float3值接收。但是一旦我将它改成float3它就会表现得很奇怪而且开始闪烁,它没有给我正确的颜色。

这是我用来设置片段缓冲区的代码,

func setFragmentBuffer(_ values: [Float], at index: Int) {
     let bufferValues = values
     let datasize = 16 * values.count / 3

     let colorBuffer = device.makeBuffer(bytes: bufferValues, length: datasize, options: [])
     renderEncoder.setFragmentBuffer(colorBuffer, offset: 0, at: index)
}

这是RGBColors的结构

struct RGBColors {
    var r: Float
    var g: Float
    var b: Float

    func floatBuffers() -> [Float] {
        return [r,g,b]
    }
}

从这个结构中,我将创建一个Float值数组并将其设置为片段缓冲区。

代码let datasize = 16 * values.count / 3我给出了值16,因为虽然C ++中的float数据类型是4字节,但simd中的float3是16字节。

在着色器中我正在实现方法

fragment float4
singleShader(RasterizerData in [[stage_in]],
                   texture2d<half> sourceTexture [[ texture(0) ]],
                   const device float3 &rgbColor [[ buffer(1) ]]
{
    constexpr sampler textureSampler (mag_filter::linear,
                                      min_filter::linear);

    // Sample the texture and return the color to colorSample
    const half4 colorSample = sourceTexture.sample (textureSampler, in.textureCoordinate);

    float4 outputColor;


    float red = colorSample.r * rgbColor.r;
    float green = colorSample.g * rgbColor.g;
    float blue =  colorSample.b * rgbColor.b;

    outputColor = float4(red, green,blue, colorSample.a);
    outputColor = float4((outputColor.rgb * param1 + param2) / 4, colorSample.a);
    return outputColor;
}

最后我没有得到正确的输出颜色。

如何将float3 simd数据类型与swift Float数据类型相匹配。有人可以建议我吗?

修改:

我找到了一个关于如何从float3创建MTLBuffer的解决方案,这里是代码:

func setFragmentBuffer(_ values: [float3], at index: Int) {
    var valueBuffer = values

    let bufferCreated = device.makeBuffer(length: MemoryLayout.size(ofValue: valueBuffer[0]) * 2 * valueBuffer.count , options: [])
    let bufferPointer = bufferCreated.contents()

    memcpy(bufferPointer, &valueBuffer, 16 * valueBuffer.count)
    renderEncoder.setFragmentBuffer(bufferCreated, offset: 0, at: index)
}

此代码完美无缺。但仍然在代码let bufferCreated = device.makeBuffer(length: MemoryLayout.size(ofValue: valueBuffer[0]) * 2 * valueBuffer.count , options: [])中,您可以看到长度应该乘以 2 因子,以使代码正常工作。

为什么应该有一个乘数来使它工作?我不明白这一点。有人可以建议我吗?

0 个答案:

没有答案