Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
365 views
in Technique[技术] by (71.8m points)

metal - Equivalent of MPSImageLanczosScale before MacOS 10.13

I am using MPSImageLanczosScale to scale image texture (initiated from CVPixelBufferRef) using Metal framework. The issue is MPSImageLanczosScale is only available from 10.13. But my application supports from 10.11. I can not stop supporting the lower OS versions since there are still many users using those versions. Is there any alternative way of scaling the image using Metal(or using any other way)?

Note: I am using Metal as I need GPU based image scaling to avoid any cpu consumption. So I'm looking for a GPU based image scaling solution.

Including the current implementation for your reference.

-(CVImageBufferRef)rescaleGPU:(CVImageBufferRef)sourceImageBuffer {
    CVReturn error;

    CGFloat backingScaleFactor = [[NSScreen mainScreen] backingScaleFactor];

    CVMetalTextureRef textureRef;
    error = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _videoTextureCache, sourceImageBuffer, NULL, MTLPixelFormatBGRA8Unorm, g_screenWidth * backingScaleFactor, g_screenHeight * backingScaleFactor, 0, &textureRef);

    id <MTLTexture> _metalTexture = CVMetalTextureGetTexture(textureRef);

    id<MTLTexture> _destinationTexture = [_device newTextureWithDescriptor:self.textureDescriptor];

    id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
    [self.scaleFilter encodeToCommandBuffer:commandBuffer sourceTexture:_metalTexture destinationTexture:_destinationTexture];

    id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];
    [blitEncoder synchronizeTexture:_destinationTexture slice:0 level:0];
    [blitEncoder endEncoding];

    [commandBuffer commit];
    [commandBuffer waitUntilCompleted];
    

    void* destData = malloc(scaleHeight * scaleWidth * 4);

    [_destinationTexture getBytes:destData bytesPerRow:scaleWidth * 4 fromRegion:self.destinationRegion mipmapLevel:0];
    
    CVPixelBufferCreateWithBytes(kCFAllocatorDefault, scaleWidth, scaleHeight, kCVPixelFormatType_32BGRA, destData, scaleWidth * 4, NULL, NULL, NULL, &finalBuffer);

    CVBufferRelease(textureRef);
    [_destinationTexture release];
    free(destData);
    
    return finalBuffer;
}
question from:https://stackoverflow.com/questions/65938956/equivalent-of-mpsimagelanczosscale-before-macos-10-13

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can fall back to MPSImageBilinearScale for users that are on versions that don't have the MPSImageLanczosScale. It will be lower quality, but you won't have to roll your own resize and also won't have to abandon existing users that didn't update their OS.

Make scaleFilter member of your class be of type MPSImageScale*

if (@available(macOS 10.13, *))
{
    self.scaleFilter = [[MPSImageLanczosScale alloc] initWithDevice:device];
}
else 
{
    self.scaleFilter = [[MPSImageBilinearScale alloc] initWithDevice:device];
}

They have the same base interface MPSUnaryImageKernel so you won't have to change other parts of the code, at least from what I can tell.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...