I have a dictionary file for the SCNSceneView.technique as below:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>targets</key>
<dict>
<key>rt_0</key>
<dict>
<key>size</key>
<string>128x256</string>
<key>type</key>
<string>color</string>
</dict>
<key>rt_1</key>
<dict>
<key>size</key>
<string>128x256</string>
<key>type</key>
<string>color</string>
</dict>
</dict>
<key>passes</key>
<dict>
<key>pass_final</key>
<dict>
<key>draw</key>
<string>DRAW_QUAD</string>
<key>program</key>
<string>doesntexist</string>
<key>metalVertexShader</key>
<string>pass_through_vertex</string>
<key>metalFragmentShader</key>
<string>pass_through_fragment_final</string>
<key>inputs</key>
<dict>
<key>colorSampler</key>
<string>COLOR</string>
<key>blurSampler</key>
<string>rt_1</string>
<key>aPos</key>
<string>vertexSymbol</string>
</dict>
<key>outputs</key>
<dict>
<key>color</key>
<string>COLOR</string>
</dict>
</dict>
<key>pass_vert</key>
<dict>
<key>draw</key>
<string>DRAW_QUAD</string>
<key>program</key>
<string>doesntexist</string>
<key>metalVertexShader</key>
<string>pass_through_vertex</string>
<key>metalFragmentShader</key>
<string>pass_through_fragment_vert</string>
<key>inputs</key>
<dict>
<key>colorSampler</key>
<string>COLOR</string>
<key>aPos</key>
<string>vertexSymbol</string>
</dict>
<key>outputs</key>
<dict>
<key>color</key>
<string>rt_0</string>
</dict>
</dict>
<key>pass_hori</key>
<dict>
<key>draw</key>
<string>DRAW_QUAD</string>
<key>program</key>
<string>doesntexist</string>
<key>metalVertexShader</key>
<string>pass_through_vertex</string>
<key>metalFragmentShader</key>
<string>pass_through_fragment_hori</string>
<key>inputs</key>
<dict>
<key>colorSampler</key>
<string>rt_0</string>
<key>aPos</key>
<string>vertexSymbol</string>
</dict>
<key>outputs</key>
<dict>
<key>color</key>
<string>rt_1</string>
</dict>
</dict>
</dict>
<key>sequence</key>
<array>
<string>pass_vert</string>
<string>pass_hori</string>
<string>pass_vert</string>
<string>pass_hori</string>
<string>pass_final</string>
</array>
<key>symbols</key>
<dict>
<key>vertexSymbol</key>
<dict>
<key>semantic</key>
<string>vertex</string>
</dict>
</dict>
<key>reflectionResolutionScaleFactor</key>
<string>0.5</string>
</dict>
</plist>
The metal file for passes in the technique file is as below:
#include <metal_stdlib>
using namespace metal;
#include <SceneKit/scn_metal>
struct custom_vertex_t
{
float4 position [[attribute(SCNVertexSemanticPosition)]];
};
constexpr sampler s = sampler(coord::normalized,
address::repeat,
filter::linear);
constexpr sampler sClamp = sampler(coord::normalized,
filter::linear);
struct out_vertex_t
{
float4 position [[position]];
float2 uv;
};
vertex out_vertex_t pass_through_vertex(custom_vertex_t in [[stage_in]])
{
out_vertex_t out;
out.position = in.position;
out.uv = float2((in.position.x + 1.0) * 0.5 , (in.position.y + 1.0) * -0.5 + 1.0);
return out;
};
// http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
constant float offset[] = { 0.0, 1.0, 2.0, 3.0, 4.0 };
constant float weight[] = { 0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162 };
fragment half4 pass_through_fragment_hori(out_vertex_t vert [[stage_in]],
texture2d<float, access::sample> colorSampler [[texture(0)]])
{
float4 FragmentColor = colorSampler.sample( s, vert.uv) * weight[0];
for (int i=1; i<5; i++) {
FragmentColor += colorSampler.sample( sClamp, ( vert.uv + float2(offset[i], 0.0)/224.0 ) ) * weight[i];
FragmentColor += colorSampler.sample( sClamp, ( vert.uv - float2(offset[i], 0.0)/224.0 ) ) * weight[i];
}
return half4(FragmentColor);
}
fragment half4 pass_through_fragment_vert(out_vertex_t vert [[stage_in]],
texture2d<float, access::sample> colorSampler [[texture(0)]])
{
float4 FragmentColor = colorSampler.sample( s, vert.uv) * weight[0];
for (int i=1; i<5; i++) {
FragmentColor += colorSampler.sample( sClamp, ( vert.uv + float2(0.0, offset[i])/224.0 ) ) * weight[i];
FragmentColor += colorSampler.sample( sClamp, ( vert.uv - float2(0.0, offset[i])/224.0 ) ) * weight[i];
}
return half4(FragmentColor);
};
fragment half4 pass_through_fragment_final(out_vertex_t vert [[stage_in]],
texture2d<float, access::sample> colorSampler [[texture(0)]],
texture2d<float, access::sample> blurSampler [[texture(1)]])
{
float4 FragmentColor = colorSampler.sample( s, vert.uv);
float4 BlurColor = blurSampler.sample( s, vert.uv) * 0.5;
FragmentColor.xyz += BlurColor.xyz;
return half4(FragmentColor);
}
Basically the technique is a post process blur filter with chained passes for a sceneView, it worked fine under iOS11 and Xcode9 before. But after iOS12, I am receiving these error codes:
[SceneKit] Error: Pass XXX(all passes included) is not linked to the rendering graph and will be ignored check it's input/output
It seems that the vertex and fragment metal methods are not linked yet. But I don't know what has changed under iOS 12 and Xcode10.
Does anyone know how to fix the code?