如何将纹理传递到顶点着色器? (iOS和金属)(IOAF代码5)

时间:2018-09-23 11:06:22

标签: ios textures metal vertex-shader

我想用顶点着色器中的纹理修改地理网格。

我有一条正在运行的Metal管道。

我这样传递MTLTexture

commandEncoder.setVertexTexture(texture, index: 0)
commandEncoder.setVertexSamplerState(sampler, index: 0)

我的顶点着色器功能:

vertex VertexOut distort3DVTX(const device VertexIn* vertecies [[ buffer(0) ]],
                              unsigned int vid [[ vertex_id ]],
                              texture2d<float> inTex [[ texture(0) ]],
                              sampler s [[ sampler(0) ]]) {

    VertexIn vtxIn = vertecies[vid];
    float x = vtxIn.position[0];
    float y = vtxIn.position[1];

    float u = x / 2 + 0.5;
    float v = y / 2 + 0.5;
    float2 uv = float2(u, v);
    float4 c = inTex.sample(s, uv);

    VertexOut vtxOut;
    vtxOut.position = float4(x + (c.r - 0.5), y + (c.g - 0.5), 0, 1);
    vtxOut.texCoord = vtxIn.texCoord;

    return vtxOut;
}

这是我看到的错误:

  

由于执行期间发生错误,命令缓冲区的执行被中止。丢弃(GPU错误/恢复的受害者)(IOAF代码5)

如果我将float4 c = inTex.sample(s, uv);替换为float4 c = 0.5;,则看不到错误。因此,绝对可以对纹理进行采样...

有什么办法解决IOAF code 5吗?

更新1:

错误代码似乎与纹理无关,当我尝试传递统一缓冲区时也会发生同样的事情...

const device Uniforms& in [[ buffer(1) ]]

更新2:

编辑方案->运行->选项-> GPU帧捕获->金属

以前,我将其设置为Automatically Enabled

现在我得到了相关的错误日志:

  

线程1:信号SIGABRT

     

validateFunctionArguments:3469:断言失败'顶点功能(particle3DVTX):缺少in [0]在索引1处的缓冲区绑定。'

drawPrimitivesendEncoding之前我崩溃了……

更新3:

这是我传递统一值的方式:

var vertexUnifroms: [Float] = ...
let size = MemoryLayout<Float>.size * vertexUnifroms.count
guard let uniformsBuffer = metalDevice.makeBuffer(length: size, options: []) else {
    commandEncoder.endEncoding()
    throw RenderError.uniformsBuffer
}
let bufferPointer = uniformsBuffer.contents()
memcpy(bufferPointer, &vertexUnifroms, size)
commandEncoder.setVertexBuffer(uniformsBuffer, offset: 0, index: 1)

更新4:

清洁帮助。我现在看到崩溃的地方; drawPrimitives。我的vertexUnifroms是空的,已修复了该错误,现在我已经有了制服!

1 个答案:

答案 0 :(得分:1)

我有同样的问题。我发现我需要使用以下命令设置顶点缓冲区字节:

commandEncoder.setVertexBytes(&vertexUniforms, length: MemoryLayout<VertexUniforms>.size, index: 1)

...对于片段缓冲区字节也可以执行相同的操作:

commandEncoder.setFragmentBytes(&fragmentUniforms, length: MemoryLayout<FragmentUniforms>.size, index: 1)