Pointers in MSL

Hello!

I have to use a specific pattern with pointers for a shader and I am not sure what's wrong. The shader renders with artefacts.

Seems to be something messed up with the pointers and the UVs.

Here is a simplified version:

    float3 outColor;
    float2 uv;
};

device Context *ContextInit(float3 color, float2 uv) {
    device Context *context = nullptr;
    context->outColor = color;
    context->uv = uv;
    return context;
}

void drawSomething(device Context &context) {
    float d = length(context.uv);
    context.outColor *= d;
}

void manupulateUV(device Context &context, float2 uv) {
    uv +=0.5;
    float d = length(sin(uv));
    context.outColor -=d;
}

fragment float4 pointer(VertexOut input[[stage_in]]) {
    
    float2 uv = input.textureCoordinate;
    
    device Context *context = ContextInit(float3(1, 0, 0), uv);
    
    drawSomething(*context);

    return float4(context->outColor.x, context->outColor.y, 0, 1);

}

The function ContextInit that you have looks suspicious. You're initializing context to nullptr and then proceeding to initialize fields and ultimately returning that nullptr. Maybe you can rewrite your code to avoid the device Context * and instead directly use Context (allocated in thread address space).

I second the above. You are writing to a null pointer, which is undefined behavior. There is no standard way to allocate device memory in Metal. Use local storage (value instead of pointer) if you only need the context for the invocation of the shader, or implement your own bump allocator from a pre-allocated data buffer if you need the context to escape the shader invocation.

@Graphics and Games Engineer @jcookie Thank you both! Kind of failing to make it work. I am trying to imitate the glsl in out so I can draw on top of context without returning it. Can you please let me know how to do it?

Tried to use the thread address space but still drawSomething returns black, not the circular ramp it supposed to return.

Example in the reply.

Thanks for the comments, here is what I tried, but still getting black output from drawSomething.

`struct Context { float3 outColor; float2 uv; };

thread Context ContextInit(float3 color, float2 uv) { Context context; context.outColor = color; context.uv = uv;

return context;

}

void drawSomething(Context context) { float d = length(context.uv); context.outColor *= d; }

fragment float4 pointer(VertexOut input[[stage_in]]) {

float2 uv = input.textureCoordinate;
thread Context context = ContextInit(float3(1, 0, 0), uv);
context.outColor = float3(0,1,0);
drawSomething(context);
return float4(context.outColor.x, context.outColor.y, 0, 1);

}`

Ok got it!

This is what I ended up using! Thank you both!

    float3 outColor;
    float2 uv;
};

void drawSomething(thread Context *context) {
    float d = length(context->uv);
    context->outColor *= d;
}

fragment float4 pointer(VertexOut input[[stage_in]]) {
    
    float2 uv = input.textureCoordinate;
    
    Context context;
    context.outColor = float3(0.5, 0.5, 0.0);
    context.uv = uv;
    drawSomething(&context);

    return float4(context.outColor.x, context.outColor.y, 0, 1);

}
Pointers in MSL
 
 
Q