Filling in a MTLAccelerationStructureInstanceDescriptor

While translating the Accelerating Ray Tracing Using Metal sample project into Swift, I have run into an issue within the createAccelerationStructures function.

I am trying to fill in the first three rows of the instance transformation matrix. In the Objective C example, it looks like:

Code Block
for (int column = 0; column < 4; column)
for (int row = 0; row < 3; row)
instanceDescriptors[instanceIndex].transformationMatrix.columns[column][row] = instance.transform.columns[column][row];

The matrix targeted is a MTLPackedFloat4x3. It has defied me pulling out the needed elements from my instance transform and placing them in the descriptor. I have tried the obvious:

Code Block
for column in 0..<( 4 )
{
for row in 0..<( 3 )
{
anInstanceDescriptorPointer.pointee.transformationMatrix.columns[column][row] = aNodeInstance.transform.columns[column][row]
}
}

I have tried more obscure ideas related to simd matrices and Swift. The compiler errors generally warn me that MTLPackedFloat4x3 has no subscripts.

Question - Is there an accepted way to assign three rows from the instance transform to the descriptor transformationMatrix in Swift?

Thank you for your earlier help with all of this. I should mention that the new intersector feature in Metal has worked really well for me when feeding it a primitiveaccelerationstructure. Very elegant! But using instances seems to offer more flexibility going forward.

Thank you very much!

Replies


The compiler errors generally warn me that MTLPackedFloat4x3 has no subscripts.

Columns in MTLPackedFloat4x3 are represented as a fixed-sized C-array, and imported into Swift as a tuple.
So, you need to access each column by tuple member access like .0, .1, .2 or .3.
Or else access whole columns as a tuple.

I would do it in this way.

First, prepare an initializer taking SIMD matrix.
Code Block
extension MTLPackedFloat4x3 {
init(_ mat4x4: matrix_float4x4) {
self.init(columns: (
MTLPackedFloat3(mat4x4[0]),
MTLPackedFloat3(mat4x4[1]),
MTLPackedFloat3(mat4x4[2]),
MTLPackedFloat3(mat4x4[3])
))
}
}
extension MTLPackedFloat3 {
init(_ vec4: simd_float4) {
self.init()
self.elements = (vec4[0], vec4[1], vec4[2])
}
}

And set whole transformationMatrix at once.
Code Block
            anInstanceDescriptorPointer.pointee.transformationMatrix =  MTLPackedFloat4x3(aNodeInstance.transform)




That is pretty interesting in a few different ways - And it compiles!
Thanks so much for your response & solution, particularly in the WWDC aftermath ~ JL

@OOPer, thx for sharing your code. 

@JL, in a one-to-one port of Apple‘s ray tracer sample (Accelerating ray tracing using Metal) one would use the transpose of the matrix because the sample uses row-first order and MTLAccelerationStructureInstanceDescriptor.transformationMatrix expects column-first.

anInstanceDescriptorPointer.pointee.transformationMatrix = MTLPackedFloat4x3(aNodeInstance.transform.transpose)

Without transpose the render result seems to be a single Cornell Box but in fact are nine instances stacked at the same position. 

A bit late, but in case anyone else will come across…