Setting up Metal cpp with GLFW and ImGUI

Dear experts, I'm working on adding UI for my cpp based path tracer renderer. I want to create metal cpp device and pass it to renderer, but also I want to use ImGui and GLFW (for window manager and input events handling). I've found solution how I can mix obj c code that requires by GLFW window setup and cpp code: https://github.com/ikryukov/MetalCppImGui

// Here is key thing for integration GLFW with Metal Cpp    
// GLFW supports only obj c window handle    
NSWindow *nswin = glfwGetCocoaWindow(window);    
CA::MetalLayer* layer = CA::MetalLayer::layer();    
layer->setDevice(device);    
layer->setPixelFormat(MTL::PixelFormatBGRA8Unorm);    // bridge to obj c here because NSWindow expetcs objc  
CAMetalLayer* l = (__bridge CAMetalLayer*)layer;
nswin.contentView.layer = l;    
nswin.contentView.wantsLayer = YES;

Is there any official way to handle event in Metal cpp without objective c support? Maybe MetalKit will have such features in future?

Replies

I recommend checking out our video Program Metal in C++ with metal-cpp which gives some pointers on using C++ and Objective-C code together.

It sounds like you are specifically referring to window events like mouse and keyboard movement? If so, then I think you are on the right track in your solution. Libraries like ImGui and GLFW will mix Objective-C code with C++ in a .mm file to solve this language interaction. In general, you can write a C++ interface in your .hpp file and put your implementation in a .mm file where you can mix C++ and Objective-C. Then you use your interface with your C++ code. It's also helpful to use the Pointer to Implementation (PIMPL) pattern if you need to create a C++ class that needs to store Objective-C pointers. Please see the code below for a simple example. In your case, you may want to receive the window events in Objective-C and then forward the handling to a C++ class. One main advantage to this method is that you don't need to wrap any additional Objective-C libraries that you'd like to use.

#pragma once

// A forward declaration to the class/struct that stores the private implementation.
class PrivateImplementation;

/// A class that uses the pointer-to-implementation (PIMPL) design pattern.
class PublicClass {
public:
    PublicClass();
    ~PublicClass();

    // Other C++ member variables and functions go here.

private:
    // A pointer to the implementation class that stores the Objective-C member variables.
    PrivateImplementation* pImpl;
};

And use the Objective-C code in the .mm file.

#include <Metal/Metal.h>
#include "PublicClass.hpp"

class PrivateImplementation {
    // Member variables that are Objective-C objects go here.

    // An example texture object.
    id<MTLTexture> exampleTextureObject;
};

/// Allocates the private implementation class.
PublicClass::PublicClass() {
    pImpl = new PrivateImplementation();
}

/// Deallocates the private implementation class.
PublicClass::~PublicClass() {
    delete pImple;
}