What is the correct usage of sampler lod_options (MSL) in Metal shader? - ios

I'm trying to learn MSL through the Metal Shading Language Specification, and saw that you can set LOD options when sampling a texture by specifying the options in the sample function. This is one of the examples given in the spec:
Tv sample(sampler s, float2 coord, lod_options options, int2 offset = int2(0)) const
lod_options include bias, level, gradient2d, etc.
I've looked all over but cannot find the usage syntax for this. Are these named arguments? Is lod_options a struct? For example, if I want to specify the LOD level, what is the correct way to do it? I know these options can also be specified in the sampler object itself, but if I want to do it here, what would be the right syntax to do so?

There is no lod_options type as such; you can think of it as a placeholder for one of the bias, level, gradient2d, etc. types. Each of these types is a different struct, which allows the Metal standard library to have an overloaded variant of the sample function for each such option.
To specify, for example, the mipmap level to sample, you'd provide a parameter of level type:
float4 color = myTexture.sample(mySampler, coords, level(1));

Related

How to write into specific mipmap using Metal kernel?

When using GLSL, it's easy writing into specific mipmap level.
But I found out it seems missing in Metal shading language.
Well, I might be wrong. Maybe there are some workaround.
You have two options here:
If you are using Metal 2.3 or higher, you can use void write(Tv color, uint2 coord, uint lod = 0) or void write(Tv color, ushort2 coord, ushort lod = 0) methods on metal::texture2d. The problem is, that even with Metal 2.3 lod must be 0 on Intel and AMD GPUs.
To work around that limitation, you can make an MTLTexture view using newTextureViewWithPixelFormat:textureType:levels:slices: (https://developer.apple.com/documentation/metal/mtltexture/1515409-newtextureviewwithpixelformat?language=objc) for the level you want to write.

Most efficient way to store normals in gltf files?

I am looking at most efficient way to store normals in gltf files, we would like to use them for webgl 1 flat and smooth shading.
Is there support for different normal precision?
We prefer to not duplicate all vertices in order to have normals because or meshes are huge.
I just found this
KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes
NORMAL "VEC3" 5126 (FLOAT) Normalized XYZ vertex normals
so I assume there is a single way?
Thanks for your help
Flat normals: The most efficient way to store flat normals is to omit them entirely. From the glTF specification, in the Meshes section,
"When normals are not specified, client implementations should calculate flat normals."
Smooth normals: You are correct, the core glTF specification requires that normals use 5126 / float32 precision. If you need other options, enable the KHR_mesh_quantization extension (extension spec) on your model, which allows for additional types (int16 normalized or int8 normalized). The gltfpack library can apply these optimizations automatically, or you can modify the model directly.

How to specify LOD bias in Metal?

I'm rewriting an OpenGL filter from the Android version of the app I'm currently working at in Metal. It uses the following texture lookup function:
vec4 texture2D(sampler2D sampler, vec2 coord, float bias)
Assuming my filter kernel function looks like this:
float4 fname(sampler src) {
...
}
The texture lookup call would be the following:
src.sample(coord)
But how can I pass the bias parameter? (the sample function takes only 1 argument)
I'm afraid Core Image only supports 2D textures – no mipmapping and LOD selection. Only bilinear sampling is available.
If you need different LODs, you need to pass different samplers to your kernel and do the interpolation yourself.

Z-Value, Z-Near and Z-Far Within Kernel Function

While loading texture within kernel function in Metal, is it possible to find the default z-value (if it exists at all) of the texture being sampled, the z-near and z-far values (likewise, if these values exist at all when the kernel is used instead of the normal pipeline using shaders) of the space in which the texture resides?
What I am trying to understand is:
When sampling a texture within kernel function, is it possible for us to change (or set) the z value of the texture before writing it? I have not been able to find this information along with the z-near and z-far values (is it even possible that we define these values manually when using the kernel function?) from the documentation.
Thanks.

In the Accelerate Framework is it safe to use the same reference for both input and output?

I'm using the accelerate framework to create a fast vector and matrix library. Is it safe to use the same float array as both an input and an output? Is the code below safe?
Vec3f& Vec3f::operator+=(const Vec3f& rhs)
{
// this->xyz is input and output. Have I crossed the beams?
vDSP_vadd(this->xyz, 1, rhs.xyz, 1, this->xyz, 1, 3);
return *this;
}
The full answer to this question is a bit complicated, because the "Accelerate framework" is made up of lots of smaller libraries. Broadly speaking, for "simple" vDSP functions (those that do work linear in their input buffers), like vDSP_vadd, yes it is safe to use the functions "in-place" (i.e. where one of the input buffers is also the output buffer).
However, I should point out that you don't want to use vDSP_vadd to add vectors of length 3. That requires just three scalar operations, or a single vector operation; even the simplest scalar implementation will be done before you can even make the function call to vDSP_vadd. What you're actually looking for is <simd/simd.h>, which contains SIMD implementations of small (2-, 3-, 4-dimension) vector and matrix arithmetic for iOS and OS X. The operator overloads are already defined there for you, so you may not need to actually do much yourself:
#include <simd/simd.h>
using namespace simd;
float3 x = { 0, 1, 2 };
float3 y = { 1, 1, 1 };
float3 z = 2*x - y;
... etc
The main benefit for using the Accelerate Framework is to capitalise on its ability to optimise against the ARM architecture.
IMPORTANT: To achieve the best possible performance, the vDSP routines perform no error checking and return no completion codes. All arguments are assumed to be specified and passed correctly, and these responsibilities lie with the caller
For an in depth look at how it does this the WWDC 2013 Session 713 is exceptionally informative.
Is the code below safe? - I'm not sure, however for optimal performance I wouldn't recommend it.

Resources