Distinction b/w using references and pointers as function arguments

Hey! Let me start by saying I intensely enjoy going through the tutorials in this book. I have graphics background, yet in each chapter learn something new or solidify my knowledge. Great!

I have two questions with regards to Chapter 10:

  1. In the fragment_main shader function definition:
fragment float4 fragment_main(
  constant Params &params [[buffer(ParamsBuffer)]],
  constant Light *lights [[buffer(LightBuffer)]])
{
  // ...
}

Why do we use reference for params and pointer to lights? I have some lightweight C++ knowledge and AFAIK in Metal Shading Language they have the same semantics, i.e. references and pointers can be interchanged?

Furthermore, both are set in Swift via the renderEncoder.setFragmentBytes method via UnsafeRawPointer

var lights = scene.lighting.lights
renderEncoder.setFragmentBytes(
  &lights,
  length: MemoryLayout<Light>.stride * lights.count,
  index: LightBuffer.index
)

encoder.setFragmentBytes(
  &params,
  length: MemoryLayout<Params>.stride,
  index: ParamsBuffer.index)
  1. When we construct the separate 3x3 normal world matrix, in the book this code snippet is used:

Screenshot 2022-10-07 at 12.01.45

However this does not transpose and inverse the uniforms.modelMatrix. In fact, in MathLibrary.swift there exists this method, which seems correct:

extension float3x3 {
  init(normalFrom4x4 matrix: float4x4) {
    self.init()
    columns = matrix.upperLeft.inverse.transpose.columns
  }
}

However it is not used anywhere in this lesson.

Thanks in advance!

Thanks for the kind words about the book :slight_smile:

  1. Why do we use reference for params and pointer to lights ?

params is a single structure, whereas lights is an array.

  1. Normal matrix

A couple of articles on normal matrices:

http://www.lighthouse3d.com/tutorials/glsl-12-tutorial/the-normal-matrix/
https://paroj.github.io/gltut/Illumination/Tut09%20Normal%20Transformation.html

However, I took the easy way out :slight_smile: and am using linear scaling, so all of that is unnecessary, and you can just take the upper left of the model matrix.

1 Like

Thank you for the reply, Caroline.

I understand that params is a single structure, while lights is an array. Is this the only reason? Because I can use a pointer to params too instead of a ref and then access it’s properties with params->lightsCount for example.

Do I understand correctly we use references for params here only for brevity and simplified syntax?

1 Like

As you say, you could do it with a pointer and access the properties indirectly.

Both of them send a buffer to the GPU in the same way, so it’s just the way you’re accessing the buffer on the GPU, and I don’t know C++ internals well enough to say whether one way is more efficient than the other.

Personally, I prefer the . syntax over ->. And Apple doesn’t use indirection in shaders (that I’ve noticed).

Thank you Caroline. I will hijack this thread to let you know that the Metal book is absolute treasure. The amount of resources packed in it makes my subscription well worth. You really don’t skim on any techniques.

1 Like