Problem
I'm trying out the performance shaders for the first time and encountered a runtime problem. The MTLTexture
that MTKTextureLoader
returns seems to be uncompatible with Metal Performance Shaders' MPSImageFindKeypoints
encoder.
The only hint so far that I found is from @warrenm's sample code on MPS that specifies MTKTextureLoaderOptions
just like I did. I did not find any other mentions in the docs.
Any help is highly appreciated.
Error
/BuildRoot/Library/Caches/com.apple.xbs/Sources/MetalImage/MetalImage-121.0.2/MPSImage/Filters/MPSKeypoint.mm:166: failed assertion `Source 0x282ce8fc0 texture type (80) is unsupported
where 0x282ce8fc0 is the MTLTexture
from the texture loader.
As far as I could see there is no MTLTexture type 80, the enum ranges up to 8 or so (not hex).
Code
CGFloat w = CGImageGetWidth(_image);
CGFloat h = CGImageGetHeight(_image);
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
id<MTLCommandQueue> commandQueue = [device newCommandQueue];
NSDictionary* textureOptions = @{ MTKTextureLoaderOptionSRGB: [[NSNumber alloc] initWithBool:NO] };
id<MTLTexture> texture = [[[MTKTextureLoader alloc] initWithDevice:device] newTextureWithCGImage:_image
options:textureOptions
error:nil];
id<MTLBuffer> keypointDataBuffer;
id<MTLBuffer> keypointCountBuffer;
MTLRegion region = MTLRegionMake2D(0, 0, w, h);
id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
MPSImageKeypointRangeInfo rangeInfo = {100,0.5};
MPSImageFindKeypoints* imageFindKeypoints = [[MPSImageFindKeypoints alloc] initWithDevice:device
info:&rangeInfo];
[imageFindKeypoints encodeToCommandBuffer:commandBuffer
sourceTexture:texture
regions:®ion
numberOfRegions:1
keypointCountBuffer:keypointCountBuffer
keypointCountBufferOffset:0
keypointDataBuffer:keypointDataBuffer
keypointDataBufferOffset:0];
[commandBuffer commit];
NSLog(keypointCountBuffer);
NSLog(keypointDataBuffer);
Edit
After converting my image to the correct pixel format I am now initialising the buffers like so:
id<MTLBuffer> keypointDataBuffer = [device newBufferWithLength:maxKeypoints*(sizeof(MPSImageKeypointData)) options:MTLResourceOptionCPUCacheModeDefault];
id<MTLBuffer> keypointCountBuffer = [device newBufferWithLength:sizeof(int) options:MTLResourceOptionCPUCacheModeDefault];
There is no error anymore. But how can I reading the contents now?
((MPSImageKeypointData*)[keypointDataBuffer contents])[0].keypointCoordinate
returns (0,0) for all indexes. Also I don't know how to read the keypointsCountBuffer
. The buffer contents converted to an int value show a higher value than the defined maxKeypoints. I don't see where the docs say what kind of format the count buffer has.
keypointDataBuffer
orkeypointCountBuffer
before encoding the command? Maybe not relevant, but could break things internally such that the assertion is a "sympathetic" error and misleading. Also, thoseNSLog()
calls can't work. They need a format string. – Ken ThomaseskeypointDataBuffer
to the maximum keypoints count that I define in therangeInfo
and try again. Indeed I was expecting maybe getting errors for those logs but I just did not look up how to log MTLBuffers yet. – EnieMPSImageFindKeypoints
needs a texture withMTLPixelFormatR8Unorm
. So After correcting the images pixel format I indeed run into the error that keypointsDataBuffer may not be null – Enie