Why does adding nodes with custom SCNPrograms make SceneKit pause 5ms between didApplyConstraints and willRenderScene?

The SceneKit rendering loop is well documented here https://developer.apple.com/documentation/scenekit/scnscenerendererdelegate and here https://www.raywenderlich.com/1257-scene-kit-tutorial-with-swift-part-4-render-loop. However neither of these documents explains what SceneKit does between calls to didApplyConstraints and willRenderScene.


I've noticed that SceneKit is pausing 3-5ms between calling didApplyConstraints and willRenderScene. I've narrowed it down to having a few hundred nodes in my scene which all have (the same) custom SCNProgram. If I remove the SCNProgram the time between didApplyConstraints and willRenderScene drops to less than half a millisecond. Does anyone know what SceneKit might be doing with that time? Presumably something I've done in my scene or the way I've set up the SCNProgram is causing it to have to do some extra work. It would be great to understand how so I can change my code to avoid it.


I don't think I'm doing unusual in my SCNProgram, it's a really simple one. Here's how I set it up:


let device = MTLCreateSystemDefaultDevice()!
let library = device.makeDefaultLibrary()
glowProgram = SCNProgram()
glowProgram.library = library
glowProgram.vertexFunctionName = "emissionGlowVertex"
glowProgram.fragmentFunctionName = "emissionGlowFragment"

...

glowMaterial = SCNMaterial()
glowMaterial.program = glowProgram
let emissionImageProperty = SCNMaterialProperty(contents: emissionImage)
glowMaterial.setValue(emissionImageProperty, forKey: "tex")


Here's the Metal shader itself:


#include <metal_stdlib>
using namespace metal;
#include <SceneKit/scn_metal>

struct NodeConstants {
    float4x4 modelTransform;
    float4x4 modelViewProjectionTransform;
};

struct EmissionGlowVertexIn {
    float3 pos [[attribute(SCNVertexSemanticPosition)]];
    float2 uv [[attribute(SCNVertexSemanticTexcoord0)]];
};

struct EmissionGlowVertexOut {
    float4 pos [[position]];
    float2 uv;
};

vertex EmissionGlowVertexOut emissionGlowVertex(EmissionGlowVertexIn in [[stage_in]],
                                               constant NodeConstants &scn_node [[buffer(1)]]) {
    EmissionGlowVertexOut out;
    out.pos = scn_node.modelViewProjectionTransform * float4(in.pos, 1) + float4(0, 0, -0.01, 0);
    out.uv = in.uv;
    return out;
}

constexpr sampler linSamp = sampler(coord::normalized, address::clamp_to_zero, filter::linear);

fragment half4 emissionGlowFragment(EmissionGlowVertexOut in [[stage_in]],
                                    texture2d<half, access::sample> tex [[texture(0)]]) {
    return tex.sample(linSamp, in.uv);
}


Any help much appreciated!

Replies

Hello,


I was unable to reproduce this issue, I recommend that you file a Technical Support Incident using the form at https://developer.apple.com/support/technical/, as any solution here is likely going to be specific to your app.