iOS Metal requires constant in fragment function - ios

I'm trying to understand Apple's Metal and converting some old opengl shaders. I'm stuck in an error that appears only in one project and not the others. I wanted to ask if there is a compiler option or something like that, that I do not know and can cause this error.
So... I've got an audio visualizer for a music player that I wrote sometime ago using opengl on ndk for Android. I converted the shader to metal on an empty project. The fragment method signature is like this:
fragment float4 spectrum_fragment_func(
Vertex vert [[stage_in]],
device Fragment *uniforms [[buffer(0)]],
device float *left [[buffer(1)]],
device float *right [[buffer(2)]]
)
I'm updating the Fragment object in code. It has a "time" value and needs to be updated for the effects to take place, meaning I cannot use constant values.
Shader compiles and works without any problems on the test application, that simply has a ViewController and my MTKView class.
When I copy the classes and shaders as-is to another project, I start getting this error:
/Volumes/Additional/Projects/.../Visuals/Shaders.metal:31:189:
Pointer argument to fragment function must be const
If I convert the Fragment variable to constant, this time error appears for the next value in the signature. It seems that in this project, something is changed and does not accept any other types of variables but only consts...
If anyone had a similar problem, or know how to solve this I'm stuck and need some help.

Related

sampler2DArray on IOS OpenGLES3.0

We're upgrading (!) our code on IOS from OpenGLES2.0 to OpenGLES3.0 so we can use texture arrays.
We build against OpenGLES3.0 defines and open a GL3.0 context, and I can initialise a texture array fine, but the shader code gives an error on this line when I compile it at runtime.
uniform sampler2DArray mySamplerName;
It complains about a "syntax error" on mySamplerName as if it doesn't understand sampler2DArray as a keyword
If I use
uniform sampler3D mySamplerName;
it compiles ok, but that's not what I want.
Yes, I know OpenGL is deprecated, but does anyone know if this should work on IOS ?
Thanks
Shaun

Metal functions failing to compile with Xcode 8

Since moving to Xcode 8 and iOS10, my metal based app fails to run at all. On launch I get the error: "Compiler failed with XPC_ERROR_CONNECTION_INTERRUPTED"
This appears two to three times in the console before crashing due to a MTLComputePipelineState not being successfully created and throwing an error when calling the MTLDevice function makeComputePipelineState(function:). The only changes I have made to the project is to update to Swift 3.0, but the console seems to imply a compiler error, which due to the crash I'm assuming is down to some metal code not compiling properly.
Any help would be appreciated, this is ageing me prematurely.
UPDATE:
I've located the line causing the trouble in the .metal file:
int gi1 = permMod12[ii+i1+perm[jj+j1+perm[kk+k1]]];
permMod12 is a static constant array declared as:
static constant int permMod12 [512] = {7,4,5,7...}
perm is similarly static and constant:
static constant int perm [512] = {151,160...}
The variables ii, i1, jj, j1, kk and k1 are all integers calculated in the same kernel.
The kernel is quite large so I'll post a link to the GitHub location. It's the functions called simplex3D and simplex4D that are causing the issue. These are very similar so only focus on one of them, they are carbon copies but 4D has another stretch of variables running (ll, l1, l etc).
The issue certainly seems to be with looking up these arrays with calculated variables as when I change the variables to simple literals there is no error.
The kernel needs to be executed in order to get the error to occur.
Any help with this new info would be great.
I also encountered the same error: "Compiler failed with XPC_ERROR_CONNECTION_INTERRUPTED". The issue was resolved. It stemmed from attempted use of 'threadgroup bool' type variables. Refactoring the code to use 'threadgroup short' variables in place of the boolean resolved the error. (Could not find in the Metal Version 2 specification if bool type is or is not a valid threadgroup type.)
I've encountered this situation, and it seems that there is no unique solution to solve this problem. In my case, the problem was occurred when a texture that uses a normalized coordinate sampler also uses read() function. When I switch read() function to sample() this weird error was removed. I hope your problem were solved already.

Qt 5.5 Video shader issue on iOS

I'm working with Qt(especially 5.5) on iOS device not simulator
I'm just add Video object to QML code for play HLS stream like below.
Video {
id: livePlayer
anchors.fill: parent
source: "http://content.jwplatform.com/manifests/vM7nH0Kl.m3u8"
autoPlay: true
}
But Qt returns me bug with log like below
Failed to find shader ":/qtmultimediaquicktools/shaders/rgbvideo.vert"
Failed to find shader ":/qtmultimediaquicktools/shaders/rgbvideo.frag"
QOpenGLShader::link: "ERROR: Compiled vertex shader was corrupt.\nERROR: Compiled fragment shader was corrupt.\n"
shader compilation failed:
"ERROR: Compiled vertex shader was corrupt.\nERROR: Compiled fragment shader was corrupt.\n"
QOpenGLShader::link: "ERROR: Compiled vertex shader was corrupt.\nERROR: Compiled fragment shader was corrupt.\n"
QOpenGLShaderProgram::uniformLocation( qt_Matrix ): shader program is not linked
QOpenGLShaderProgram::uniformLocation( rgbTexture ): shader program is not linked
QOpenGLShaderProgram::uniformLocation( opacity ): shader program is not linked
I was doing somethings what I can -Clean, Run QMake, etc-
But its useless.
Give me some help plz.
Thanks have a good day.
This is a temporary bug in the Qt 5.5 branch.
To fix it with the current 5.5 snapshots, add this to your main() function:
Q_INIT_RESOURCE(qtmultimediaquicktools);
The issue is already fixed in the current 5.5 branch of Qt, find the fix here or wait for the next snapshot.

Which is the best way to handle OpenGLES shaders as part of an API for iOS?

Working on an API for iOS, I wrote a couple of shaders that are very important for the API. These shaders are in the form of vsh and fsh files. Now, working on real projects with the API , I discovered that when we add the folder with the API source to an Xcode iOS project, we have to do an additional step, consisting in adding the file to "Copy Bundle Resources" in the Build Phases tab of the project configuration. So, we are thinking in a best way to handle this issue (and with "best" I meant that step shouldn't exist at all!) since the shaders are loaded as strings to the GPU, so, what will be the best way to handle these shaders in the API?
One way to avoid having to bundle the shader files with your framework or static library is to embed them as string constants. I do this in this project using the following macros:
#define STRINGIZE(x) #x
#define STRINGIZE2(x) STRINGIZE(x)
#define SHADER_STRING(text) # STRINGIZE2(text)
This lets me then do something like the following:
NSString *const kGPUImagePassthroughFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
}
);
and use that NSString constant to provide the shader for my programs where needed. Shader files are then not needed, which simplifies the distribution process.
You don't get as specific of syntax highlighting in Xcode as you do for dedicated vertex and fragment shader files, but you do get basic C coloring.

Loading GLSL shader without using any Apple APIs

What is a good way to load a GLSL shader using C/C++ without using Objective-C or any Apple APIs?
I am currently using the following method, which is from the iPhone 3D Programming book, but it says that it is not recommended for production code:
Simple.vsh
const char* SimpleVertexShader = STRINGIFY
(
// Shader code...
);
RenderingEngine.cpp
#define STRINGIFY(A) #A
#include "Simple.vsh"
// ...
glShaderSource( shaderHandle, 1, &SimpleVertexShader, 0 );
If you want to load your shaders from files in your app bundle, you can get the file paths using the NSBundle object (in Objective-C), or using the CoreFoundation CFBundle object (in pure C).
Either way, you are using Apple-specific APIs. The only thing you're getting by using CFBundle instead of NSBundle is more boilerplate code.
If you don't want to use any Apple APIs, then your options are to embed your shaders as literal strings, or connect to a server on the Internet and download them (using the Unix socket API).
What you really need to do is define an interface by which your RenderingEngine gets the source code for its shaders, and implement that interface using the appropriate platform-specific API on each platform to which your port the RenderingEngine. The interface can be something super simple like this:
RenderingEngineShaderSourceInterface.h
#ifdef __cplusplus
extern "C" {
#endif
// You are responsible for freeing the C string that this function returns.
extern char const *RenderingEngine_shaderSourceForName(char const *name);
#ifdef __cplusplus
}
#endif
Then you create RenderingEngineShaderSource_Windows.cpp, RenderingEngineShaderSource_iOS.m, RenderingEngineShaderSource_Linux.cpp, etc. Each one implements RenderingEngine_shaderSourceForName using the appropriate API for that platform.
I use one of two methods. If it's a short shader, I may just put it code:
const char shader[] =
"uniform vec4 blah;\n" // Note, no semicolon here - it does the right thing
"main ()\n"
"{\n"
...rest of code
"}\n";
Or, if it's longer or going to be re-used in other places, I'll put it into a text file in the resources and read the text file at run time. You can get to it via [NSBundle pathForResource:ofType:].
Consider a C++ raw string literal; no STRINGIFY is needed since the newer features of C++ allow you to do similar things without macro.
I'd retype a good example but here is one.

Resources