PeterHiber
Topic Author
Posts: 2
Joined: 30 Apr 2021, 09:42

Engine integration (iOS, Metal, sokol_gfx)

30 Apr 2021, 09:57

Hi everyone!

We have a custom cross-platform engine that is deployed pretty much everywhere (Windows, Web via emscripten, iOS, etc). As our rendering layer we are using sokol_gfx (https://github.com/floooh/sokol), which basically is a wrapper around opengl/d3d11/metal.

Up til now we have been able to integrate sokol_gfx rendering with platform specific renderers in the Noesis App Framework, example of our D3D11 integration:
// Grab D3D11 stuff from sokol
ID3D11DeviceContext* ctx =
	reinterpret_cast<ID3D11DeviceContext*>(const_cast<void*>(sapp_d3d11_get_device_context()));
ID3D11RenderTargetView* rtv =
	reinterpret_cast<ID3D11RenderTargetView*>(const_cast<void*>(sapp_d3d11_get_render_target_view()));
ID3D11DepthStencilView* dsv =
	reinterpret_cast<ID3D11DepthStencilView*>(const_cast<void*>(sapp_d3d11_get_depth_stencil_view()));

// Set D3D11 render targets and clear for noesis app framework
ctx->OMSetRenderTargets(1, &rtv, dsv);
float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
ctx->ClearDepthStencilView(dsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

// Rendering is done in the active framebuffer
state->view->GetRenderer()->Render();

// Signal to sokol_gfx that we have directly called the underlying 3D API.
sg_reset_state_cache();
This has worked fine until now, but now we are starting to expand to iOS and are hitting a road block with the Metal integration. We think we have managed to extract the following metal context members from sokol:
id<MTLDevice> device = (__bridge id<MTLDevice>)sapp_metal_get_device();
id<CAMetalDrawable> drawable = (__bridge id<CAMetalDrawable>)sapp_metal_get_drawable();
MTLRenderPassDescriptor* renderPassDescriptor = (__bridge MTLRenderPassDescriptor*)sapp_metal_get_renderpass_descriptor();
But it has not at all been obvious how to go from there to running the Application Framework's Metal renderer. This is on us of course (we are not super familiar with either objective-c or Metal).

We are wondering if there are any easier / more minimal metal integrations samples we could look at?

Thanks for the help and have a nice day! :)
 
User avatar
jsantos
Site Admin
Posts: 4123
Joined: 20 Jan 2012, 17:18
Contact:

Re: Engine integration (iOS, Metal, sokol_gfx)

30 Apr 2021, 10:44

Hi Peter, welcome to our forums!
Up til now we have been able to integrate sokol_gfx rendering with platform specific renderers in the Noesis App Framework, example of our D3D11 integration:
Let me clarify a few things first, the Noesis App Framework is the layer on top on Noesis that we created for our examples. This layer is in charge of launching the application, creating the render context (using classes deriving from RenderContext), creating the main window (using classes deriving from Display) and entering the main loop. I would say this is the functionality that sokol_gfx provides, so you don't need our App Framework. At least we don't recommend using it in production but using it as a starting point.

So instead of using our context classes, I think you should be using the API provided by sokol_gfx for setting the main render target, clearing it, etc.

Also we recommend creating a new RenderDevice implemented in terms of sokol_gfx, we don't have an implementation for this yet.

I am not very familiar with sokol_gfx, so maybe I am wrong regarding these comments.
But it has not at all been obvious how to go from there to running the Application Framework's Metal renderer. This is on us of course (we are not super familiar with either objective-c or Metal).
Metal is a bit tricky and I strongly recommend getting familiar with the basic API because it is quite different to traditional APIs like D3D11. Our MTLRenderDevice is implemented expecting the following:
  • You must pass the frame command buffer (Metal requires a command buffer per frame) to our renderer before doing RenderOffscreen
  • You must pass a render command encoder (this is associated to the main render target and it is also created by frame) before doing Render.
renderer->UpdateRenderTree();
device->SetCommandBuffer(commands);
renderer->RenderOffscreen();

commandEncoder = [commands renderCommandEncoderWithDescriptor:passDescriptor];
device->SetOnScreenEncoder(commandEncoder, colorFormat, stencilFormat, sampleCount);
renderer->Render();
You are totally right, we should have a minimum MTL sample in our SDK. Could you please file a ticket about it?
 
PeterHiber
Topic Author
Posts: 2
Joined: 30 Apr 2021, 09:42

Re: Engine integration (iOS, Metal, sokol_gfx)

30 Apr 2021, 13:51

Hi and thanks for the quick response! :)

You are absolutely right regarding sokol_gfx, we definitely should make an implementation of RenderDevice using sokol_gfx. But since we had managed to interop sokol_gfx with the default renderer on our other platforms, we were hoping to do the same on iOS in order to save some time. Deadlines and all that you know. ;)

We'll have to think a bit about how to progress I think, we could attempt the Metal integration some more, or we could give up and spend the effort implementing RenderDevice.
 
User avatar
jsantos
Site Admin
Posts: 4123
Joined: 20 Jan 2012, 17:18
Contact:

Re: Engine integration (iOS, Metal, sokol_gfx)

03 May 2021, 16:46

But since we had managed to interop sokol_gfx with the default renderer on our other platforms, we were hoping to do the same on iOS in order to save some time. Deadlines and all that you know. ;)
Yes of course :) It makes a lot of sense.
We'll have to think a bit about how to progress I think, we could attempt the Metal integration some more, or we could give up and spend the effort implementing RenderDevice.
First, I would go without implementing a RenderDevice because that can take time. In fact, I would wait till 3.1 is out because we are changing the API a bit (just making it easier to implement).

Who is online

Users browsing this forum: No registered users and 1 guest