As you might know, Metal Shading Language
allows few ways to read pixel data from texture2d
in the kernel function. It can be either simple read(short2 coord)
or sample(float2 coord, [different additional parameters])
. But I noticed, that when it comes to writing something into texture, there's only write
method.
And the problem here is that sample
method allows to sample from certain mipmap level which is very convenient. Developer just needs to create a sampler with mipFilter
and use normalized coordinates.
But what if I want to write into certain mipmap
level of the texture? The thing is that write
method doesn't have mipmap
parameter the way sample
method has and I cannot find any alternative for that.
I'm pretty sure there should be a way to choose mipmap
level for writing data to the texture, because Metal Performance Shaders
framework has solutions where mipmaps of textures are being populated.
Thanks in advance!
You can do this with texture views.
The purpose of texture views is to reinterpret the contents of a base texture by selecting a subset of its levels and slices and potentially reading/writing its pixels in a different (but compatible) pixel format.
The -newTextureViewWithPixelFormat:textureType:levels:slices:
method on the MTLTexture
protocol returns a new instance of id<MTLTexture>
that has the first level specified in the levels
range as its base mip level. By creating one view per mip level you wish to write to, you can "target" each level in the original texture.
For example, to create a texture view on the second mip level of a 2D texture, you might call the method like this:
id<MTLTexture> viewTexture =
[baseTexture newTextureViewWithPixelFormat:baseTexture.pixelFormat
textureType:baseTexture.textureType
levels:NSMakeRange(1, 1)
slices:NSMakeRange(0, 1)];
When binding this new texture as an argument, its mip level 0
will correspond to mip level 1
of its base texture. You can therefore use the ordinary texture write
function in a shader to write to the selected mip level:
myShaderTexture.write(color, coords);