Obtain function constant index for MTLArgument - metal

MTLRenderPipelineReflection contain lists of MTLArgument's that contains info about name, index, type, access, e.t.c. except any info about function constant binding.
There are MTLFunction and it's dictionary var functionConstantsDictionary: [String : MTLFunctionConstant], that keyed by function constant name(it feels excess because MTLFunctionConstant already contains name). I did not found any info about function constants that in use of argument.
As a result should be something like table [FunctionArgumentName: FunctionConstant]
Is there any info about pipeline that helps to calculate that bindings?
UPD:
fragment float4 fragment_main(VertexOut in [[stage_in]],
texture2d<float> baseColorTexture [[texture(BaseColorTexture), function_constant(hasColorTexture)]],
texture2d<float> normalTexture [[texture(NormalTexture), function_constant(hasNormalTexture)]],
texture2d<float> aoTexture [[texture(AOTexture), function_constant(hasAOTexture)]],
texturecube<float> reflectionTextureCube [[texture(ReflectionTextureCube), function_constant(hasReflectionTextureCube)]]) {
/// Shader code
}
In other words I need to access name of function constant for baseColorTexture argument of this shader function from swift code

Related

Determine the element's type of a buffer in the Metal Shader Language

I use a codegen for generating declarations of Metal shaders and sometimes I do not know the exact types of objects that are passed to shaders.
E.g. I would have this declaration generated automatically:
vertex VertexOut vertexShader(constant Element *array [[buffer(0)]])
When I try to get the element's type of the array I get the error from the compiler:
using T = metal::remove_reference_t<decltype( *array )>;
T test;// <-- ERROR! "Automatic variable qualified with an address space"
Is this possible to "erase" the address space from the type?
What is the best way of getting the type of an array's element in Metal (if it's possible at all)?
As I said in the comment, I think the problem is that remove_reference does exactly what it says: it removes reference, while still leaving the type qualified. You can not declare a variable in device or constant space, so you also need to remove the address space qualifier, similar to how remove_cv_t works. I've written up a couple templates to show you what I mean:
template <typename T>
struct remove_address_space
{
typedef T type;
};
template <typename T>
struct remove_address_space<device T>
{
typedef T type;
};
template <typename T>
struct remove_address_space<constant T>
{
typedef T type;
};
and then you would use it like
using T = remove_address_space<metal::remove_reference_t<decltype( *array )>>::type;
Keep in mind that metal has a lot of address spaces, but for the purposes of writing entry points to functions, I think only the device and constant are relevant.

Passing a Function to an annotation in dart

I want to send a Function as a parameter to an annotation like this:
#JsonKey(fromJson: ...)
final int variable;
where fromJson is a Function, but it gives me this error:
Arguments of a constant creation must be constant expressions.
what is the solution? any help would be greatly appreciated.
You didn't write what you wanted for ..., and that's the part that causes the problem.
The argument to the fromJson parameter must be a compile-time constant value because annotations must be constant.
The only constant function values are top-level or static functions, so you need to declare the function type want, let's say as static:
class MyClass {
#JsonKey(fromJson: _variableFromJson)
final int variable;
static int _variableFromjson(dynamic json) => ...;
...
}
You can't write the function in-line as (fromJson: (json) => ...) because function expressions are not compile-time constant.

Choosing between buffers in a Metal shader

I'm struggling with porting my OpenGL application to Metal. In my old app, I used to bind two buffers, one with vertices and respective colours and one with vertices and respective textures, and switch between the two based on some app logic. Now in Metal I've started with the Hello Triangle example where I tried running this vertex shader
vertex RasterizerData
vertexShader(uint vertexID [[vertex_id]],
constant AAPLVertex1 *vertices1 [[buffer(AAPLVertexInputIndexVertices1)]],
constant AAPLVertex2 *vertices2 [[buffer(AAPLVertexInputIndexVertices2)]],
constant bool &useFirstBuffer [[buffer(AAPLVertexInputIndexUseFirstBuffer)]])
{
float2 pixelSpacePosition;
if (useFirstBuffer) {
pixelSpacePosition = vertices1[vertexID].position.xy;
} else {
pixelSpacePosition = vertices2[vertexID].position.xy;
}
...
and this Objective-C code
bool useFirstBuffer = true;
[renderEncoder setVertexBytes:&useFirstBuffer
length:sizeof(bool)
atIndex:AAPLVertexInputIndexUseFirstBuffer];
[renderEncoder setVertexBytes:triangleVertices
length:sizeof(triangleVertices)
atIndex:AAPLVertexInputIndexVertices1];
(where AAPLVertexInputIndexVertices1 = 0, AAPLVertexInputIndexVertices2 = 1 and AAPLVertexInputIndexUseFirstBuffer = 3), which should result in vertices2 never getting accessed, but still I get the error: failed assertion 'Vertex Function(vertexShader): missing buffer binding at index 1 for vertices2[0].'
Everything works if I replace if (useFirstBuffer) with if (true) in the Metal code. What is wrong?
When you're hard-coding the conditional, the compiler is smart enough to eliminate the branch that references the absent buffer (via dead-code elimination), but when the conditional must be evaluated at runtime, the compiler doesn't know that the branch is never taken.
Since all declared buffer parameters must be bound, leaving the unreferenced buffer unbound trips the validation layer. You could bind a few "dummy" bytes at the Vertices2 slot (using -setVertexBytes:length:atIndex:) when not following that path to get around this. It's not important that the buffers have the same length, since, after all, the dummy buffer will never actually be accessed.
In the atIndex argument, you call the code with the values AAPLVertexInputIndexUseFirstBuffer and AAPLVertexInputIndexVertices1 but in the Metal code the values AAPLVertexInputIndexVertices1 and AAPLVertexInputIndexVertices2 appear in the buffer() spec. It looks like you need to use AAPLVertexInputIndexVertices1 instead of AAPLVertexInputIndexUseFirstBuffer in your calling code.

No member named 'read' in 'metal::texturecube'

According to Apple's Metal shading language specification, texture cubes have a read method,
read(uint2 coord, uint face, uint lod = 0) const
However, when I try to build this shader, I get a compiler error,
fragment half4 passFragment(VertexInOut inFrag [[stage_in]],
texturecube<float, access::read> tex [[ texture(0) ]])
{
float4 out = tex.read(uint2(0,0), uint(0));
return half4(out);
}
The error is,
No member named 'read' in 'metal::texturecube<float, metal::access::read>'
If I remove the access qualifier, then I get,
No member named 'read' in 'metal::texturecube<float, metal::access::sample>'
I also tried changing the type from float to int or short, but I get the same error. Frustrating that there's no header to look at...
Any ideas?
It appears that texturecube::read() is only available on macOS.
There are, in fact, headers available. Look in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/lib/clang/3.5/include/metal.
In the metal_texture header, you'll see that the declaration of read() is inside of a preprocessor conditional (#if) and is only declared if the macro __HAVE_TEXTURE_CUBE_READ__ is defined. On macOS, that's defined in the metal_config header. On iOS, it's not defined.

Is there a function in Emgucv to find non-zero pixels?

There is a function called findNonZero to find the position of non-zero pixels in Opencv. I am wondering is there is something similar in Emgucv?
I am afraid there dosen't seems to be one but you can always invoke the OpenCV functions directly using the CvInvoke.
The syntax to invoke the above mentioned function will be
CvInvoke.findNonZero();// pass the suitable parameters in the function suitably
This this post to find out more.
//
// Summary:
// Find the location of the non-zero pixel
//
// Parameters:
// src:
// The source array
//
// idx:
// The output array where the location of the pixels are sorted
public static void FindNonZero(IInputArray src, IOutputArray idx);
invoke it on CvInvoke.FindNonZero(src, outputImage);

Resources