Including Header Files in Multiple Metal Files

I am in the process of adding some light tracing and vertex connecting to the very fun path tracer project.

To make things manageable, I would like to include files such as AreaLight.h and BSDF.h to two or more Metal Files. However, this generates a linking error that seems to say I have multiple declarations of the same function.

I have done some searching and reading, but haven’t managed to find the correct way to #include the headers. I am already including an Objective C header to Swift files in the project.

I am sorry that this is such a naive question, but is there a ‘best way’ to do this?

Thanks so much,
John Lobe

Hi John

I’m not sure which chapter you’re referring to - do you mean Chapter 21, Metal Performance Shaders?

If so, you have the Bridging Header ShaderTypes.h. You can create a new header file called AreaLight.h, and cut and paste the AreaLight struct into that.

In ShaderTypes.h, you’d add:

#include "AreaLight.h"

after including simd.h.

If you have a multiple declarations error, check that you’re not using the same name in multiple files.

Hey, thanks Caroline

I think I get your explanation. But in this case, I want to include a lot of headers ( with many helper functions ) into 2 or more Metal files. Like…

// ////////// * ////////// *
// Light-Sampling.metal
// ////////// * ////////// *

#import <metal_stdlib>
#import <simd/simd.h>
#import <MetalPerformanceShaders/MetalPerformanceShaders.h>
#include “Shader-Types.h”
#include “General-Helper-Functions.h”
#include “Light-Helper-Functions.h”
#include “VCM-Helper-Functions.h”
#include “BSDF-Helper-Functions.h”
#include “Frame-Helper-Functions.h”

… Then a bunch of Metal Kernel Functions related to Light Paths

But in a different Metal File…

// ////////// * ////////// *
// Camera-Sampling.metal
// ////////// * ////////// *

#import <metal_stdlib>
#import <simd/simd.h>
#import <MetalPerformanceShaders/MetalPerformanceShaders.h>
#include “Shader-Types.h”
#include “General-Helper-Functions.h”
#include “Light-Helper-Functions.h”
#include “VCM-Helper-Functions.h”
#include “BSDF-Helper-Functions.h”
#include “Frame-Helper-Functions.h”

… Then a bunch of Metal Kernel Functions related to Camera Paths

I have tried various C-Based conditions to avoid duplicate function definitions, but haven’t had any luck. The Metal files won’t easily coexist using the same set of headers (?)

If I’m missing the obvious, please do let me know!
Thanks so much,
John Lobe

I’ve just tried this.

I’ve separated out my metal functions in two different .metal files.

I’ve moved the structs that both metal files use into Structs.h.

I’ve created a Functions.metal with a simple multiply function in it. I’ve created a Functions.h with the declaration of that multiply function.

At the top of my two different .metal files, I have this:

#include <metal_stdlib>
using namespace metal;

#import "Common.h"
#import "Structs.h"
#import "Functions.h"

I can access all structs and the multiply function from my two metal files with the shader functions, for example the multiply function like this: out.position.x = myMultiply(out.position.x, 1);

I’ve used #import instead of #include here - I’m not sure of the difference, but both seem to work equally in my case.

Functions.metal looks like this:

#include <metal_stdlib>
using namespace metal;

#import "Common.h"
#import "Functions.h"


float myMultiply(float a, float b) {
  return a * b;
}

Functions.h looks like this:

#ifndef Functions_h

#define Functions_h

float myMultiply(float a, float b);

#endif /* Functions_h */

Does this replicate yours in a simple case?
Can you start more simply and work upwards?

Btw, to make your code look like code in your posts, you can surround it with triple back ticks :slight_smile:

2 Likes

Hi Caroline,

Yes, this seems to work and makes sense too! I started with your example and have been carefully adding functions back into the project. I had been fully defining many functions in header files. In retrospect, that was not clear.

Perhaps a day will come when we can code to the device using Swift :slight_smile:

Thank you so much! The Metal by Tutorials book has created a lot of fun & interesting questions.
John Lobe

I’m really glad you’re enjoying it :slight_smile:

Ran into the same issue today. This worked. Didn’t know .h/.metal worked liked though it makes sense when it’s all built into the metal library

1 Like