Heestand XYZ
Heestand XYZ

Reputation: 2231

How to pass a texture to a vertex shader? (iOS & Metal) (IOAF code 5)

I want to modify a geo grid with a texture in vertex shader.

I've got a working Metal pipeline.

I pass the MTLTexture in like this:

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

My vertex shader func:

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;
}

This is the error I see:

Execution of the command buffer was aborted due to an error during execution. Discarded (victim of GPU error/recovery) (IOAF code 5)

If I replace float4 c = inTex.sample(s, uv); with float4 c = 0.5; I don't see the error. So it's definitely something with sampling the texture...

Any idea how to solve IOAF code 5?

Update 1:

The error code dose not seem to be related to the texture, the same thing happens when I try to pass a uniform buffer...

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

Update 2:

Edit Scheme -> Run -> Options -> GPU Frame Capture -> Metal

Previously I had it set to Automatically Enabled.

Now I get relevant error logs:

Thread 1: signal SIGABRT

validateFunctionArguments:3469: failed assertion `Vertex Function(particle3DVTX): missing buffer binding at index 1 for in[0].'

Tho I'm crashing before I drawPrimitives or endEncoding...

Update 3:

Here's how I pass the uniform values:

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)

Update 4:

Clean helped. I now see where it's crashing; drawPrimitives. My vertexUnifroms was empty, fixed the bug, and now I've got uniforms!

Upvotes: 1

Views: 1298

Answers (1)

Andrew
Andrew

Reputation: 184

I had the same problem. I discovered that I needed to set Vertex Buffer Bytes with:

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

...the same thing can also be done for the Fragment Buffer Bytes:

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

Upvotes: 1

Related Questions