Anybody have a workaround for using the "#extension" preprocessor directive with an SKShader? In addition to SKShader(fileNamed: <nameOfFile>), I've tried using "#extension" in SKShader(source: <String>) and SKShader(source: <String>, uniforms: <[SKUniform]>) and they don't compile either. This happens even with PrefersOpenGL=YES (and also with PrefersOpenGL=NO).
I filed an Apple Bug Reporter bug and an official Apple Technical Support Incident request. Apple tech support summarily told me that they would not look at this problem because it pertained to the beta versions of iOS and Xcode. I will try (likely) to reproduce them on non-beta versions of iOS and Xcode. This is an important problem with SKShader because it doesn't allow the programmable blending extension to be compiled.
Here are the details of the problem:
PLATFORM AND VERSION
iOS 10.2 and Xcode Version 8.2 beta (8C30a) on an iPhone 6s plus
DESCRIPTION OF PROBLEM
I described this in Apple Bug Reporter #29429243 and uploaded a project example that reproduces the problem.
Summary:
Trying to compile a shader file with "#extension EXT_shader_framebuffer_fetch : require" as the source for an SKShader fails. This happens even with PrefersOpenGL=YES.
Here is info from the Open GL ES Analyzer:
Shader #2 - Your application unsuccessfully attempted to compile a shader. See the info log below:
Info Log:
ERROR: 0:1: '' : syntax error: preprocessor command must not be preceded by any other statement in that line
0 0x10029bf5c
1 Jet xglCompileShader(unsigned int*, unsigned int, char const*, std::__1::basic_string, std::__1::allocator >**)
2 Jet jet_context_OpenGL::create_function_from_source(char const*, char const*, jet_function_type, std::__1::basic_string, std::__1::allocator >**)
3 SpriteKit __50-[SKShader _makeBackingProgramWithImplementation:]_block_invoke
4 SpriteKit ___Z27SKCPerformResourceOperationU13block_pointerFvNSt3__110shared_ptrI11jet_contextEEE_block_invoke
5 libdispatch.dylib _dispatch_client_callout
6 libdispatch.dylib _dispatch_barrier_sync_f_invoke
7 SpriteKit SKCPerformResourceOperation(void (std::__1::shared_ptr) block_pointer)
8 SpriteKit -[SKShader _makeBackingProgramWithImplementation:]
9 SpriteKit -[SKShader _backingProgram]
10 SpriteKit SKCRenderer::flushCurrentBatch()
11 SpriteKit SKCRenderer::expandRenderGroup(std::__1::shared_ptr const&, std::__1::shared_ptr const&)
12 SpriteKit SKCRenderer::expandRenderPass(std::__1::shared_ptr const&, std::__1::shared_ptr const&)
13 SpriteKit SKCRenderer::render(SKCNode*, float vector[4], std::__1::shared_ptr const&, unsigned int vector[4], matrix_float4x4, bool, NSDictionary*, SKCStats*, SKCStats*, double)
14 SpriteKit __59-[SKView _renderSynchronouslyForTime:preRender:postRender:]_block_invoke
15 SpriteKit -[SKView _renderSynchronouslyForTime:preRender:postRender:]
16 SpriteKit -[SKView layoutSubviews]
17 UIKit -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
18 QuartzCore -[CALayer layoutSublayers]
19 QuartzCore CA::Layer::layout_if_needed(CA::Transaction*)
20 QuartzCore CA::Layer::layout_and_display_if_needed(CA::Transaction*)
21 QuartzCore CA::Context::commit_transaction(CA::Transaction*)
22 QuartzCore CA::Transaction::commit()
23 QuartzCore CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*)
24 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
25 CoreFoundation __CFRunLoopDoObservers
26 CoreFoundation CFRunLoopRunSpecific
27 UIKit -[UIApplication _run]
28 UIKit UIApplicationMain
29 BlendShader 0x10008d43c
30 libdyld.dylib start
STEPS TO REPRODUCE
Steps to Reproduce:
Zip file attached in #29429243 that reproduces problem.
Here are the steps:
1. Create a SpriteKit app
2. Add a createShader() function to the didMove()
3. In createShader(), create an SKShader with a source file that includes the #extension directive, namely:
"#extension EXT_shader_framebuffer_fetch : require
void main() {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}"
4. Create an SKSpriteNode and set its shader property to the SKShader.
5. Add the SKSpriteNode to the scene.
Expected Results:
Expect the shader to compile
Actual Results:
Encounter following shader compile error:
ERROR: 0:1: '' : syntax error: preprocessor command must not be preceded by any other statement in that line
Note The Metal version equivalent of programmable blending from 4.7 in https://developer.apple.com/metal/metal-shading-language-specification.pdf does not compile either (with PrefersOpenGL=NO or PrefersOpenGL=YES):
#include
using namespace metal;
fragment half4
paint_grayscale(half4 dst_color [[color(0)]])
{
// RGB to grayscale
half lum = dot(dst_color.rgb,
half3(0.30h, 0.59h, 0.11h));
return half4(lum, lum, lum, 1.0h);
}
I get a "SKShader 'shader_blend.fsh' failed to compile:"
Please let me know if you have a workaround!
Thank you!