Hi,I am trying to port a program to use argument buffers in Swift. I have a very simple argument buffer filled on the CPU and used inside the vertex shader. The buffer contains only a single color as a float4 and a transformation matrix as a float4x4. I am able to use the color value without problem, but I am not able to use the float4x4, the content of it is always corrupted (I used an idendity matrix).I followed the "Basic Argument Buffers" documentation page, and even made a minimal program to reproduce the bug, and the problem persists. What is really strange is that I tried to pass other kinds of constants (integers, floats, float4) that all work very well, I only appear to have problems with float4x4 matrices. For example I tried to pass four float4 as the columns of my matrix and to re-assemble them inside the shader and although it is probably horrible, it works quite well.The argument buffer is in shared mode (I have an intel integrated card with shared memory), but I tried to use didModifyRange() on the buffer anyway, without success. My card is ok with Metal version 2 and the argument buffers should be supported.Any advice will be very appreciated to help me spot my error. Thanks for your time.Here is my problematic shader :#include <metal_stdlib>
using namespace metal;
typedef struct {
float4 position;
float4 color;
} VertexIn;
typedef struct {
float4 position [[ position ]];
float4 color;
} VertexOut;
// Here is my argument buffer
typedef struct {
float4 color [[id(0)]]; // This value can be used without problem.
float4x4 mvp [[id(1)]]; // This value is always corrupt (even if I change the id).
// This is a desperate attempt to get the four columns of the mvp matrix.
// The values are correct.
//float4 a [[id(2)]], b [[id(3)]], c [[id(4)]], d [[id(5)]];
} VertexArgs;
vertex VertexOut color_vertex(
const device VertexArgs& args [[ buffer(1) ]],
const device VertexIn* vertices [[ buffer(0) ]],
uint vid [[ vertex_id ]]) {
VertexOut out;
// This works well, although ugly, I build the matrix from
// four columns :
// float4x4 mvp = float4x4(args.a, args.b, args.c, args.d);
// out.position = mvp * vertices[vid].position;
// This won't work, args.mvp is corrupted:
out.position = args.mvp * vertices[vid].position;
// I ignore the vertices color, to test the color
// from the argument buffer, it works well.
out.color = args.color;
return out;
}
fragment half4 color_fragment(VertexOut in [[ stage_in ]]) {
return half4(in.color.r, in.color.g, in.color.b, in.color.a);
}Here us the way I create the argument buffer on the CPU :argencoder = vertexFunction.makeArgumentEncoder(bufferIndex: 1)
argbuffer = device.makeBuffer(length: argencoder.encodedLength, options: .storageModeShared)!
argencoder.setArgumentBuffer(argbuffer, offset: 0)Here is the way I update the argument buffer on the CPU :var color = float4(1, 0, 0, 1)
var matrix = float4x4(float4(1,0,0,0), float4(0,1,0,0), float4(0,0,1,0), float4(0,0,0,1))
argencoder.constantData(at: 0).copyMemory(from: &color, byteCount: MemoryLayout.stride)
argencoder.constantData(at: 1).copyMemory(from: &matrix, byteCount: MemoryLayout.stride)
argbuffer.didModifyRange(0 ..< argencoder.encodedLength)I don't copy/paste here the full swift program as it is almost 200 lines.