在某些目标c类中,我有一个缓冲区,由两个连续的金属管道使用。一个内核根据图像的rgb亮度处理值并写入可变缓冲区,然后根据第一个中的数据绘制波形图。它基于此处描述的osx着色器USING METAL PERFORMANCE SHADERS WITH CORE IMAGE。
我设法将这个从osx转换为IOS,这很有效,但我现在正试图将其转换为swift,以便将来更灵活。我还有其他我想写的过滤器,翻译过程也教会了我很多金属管道的工作原理。
这是它崩溃的地方。它绘制的图形有一条水平彩色线条上下飘动。关闭但没有雪茄。我想知道它是否与如何在swift vs objective c中创建缓冲区有关。这是原作的一个例子:
size_t columnBufSize = sizeof(UInt64)*inputTexture.width*inputTexture.height;
id<MTLBuffer> columnDataRed = [kDevice newBufferWithLength:columnBufSize options:0];
但是当我快速翻译它时,它的表现并不像预期的那样。
let columnBufSize: size_t = MemoryLayout<UInt64>.size * inputTexture!.width * inputTexture!.height
let columnDataRed: MTLBuffer = kDevice.makeBuffer( length: columnBufSize, options: .storageModeShared)!
看起来只有最后一个值传递给第二个computeEncoder。
我错过了什么?
完成,这是目标c
中的完整代码+ (BOOL)processWithInputs:(NSArray<id<CIImageProcessorInput>> *)inputs arguments:(NSDictionary<NSString *,id> *)arguments output:(id<CIImageProcessorOutput>)output error:(NSError * _Nullable *)error
{
id<MTLComputePipelineState> renderComputerState = kParadeComputePipelineState;
id<CIImageProcessorInput> input = inputs.firstObject;
id<MTLCommandBuffer> commandBuffer = output.metalCommandBuffer;
commandBuffer.label = @"com.martinhering.WaveformKernel";
id<MTLTexture> inputTexture = input.metalTexture;
id<MTLTexture> outputTexture = output.metalTexture;
MTLSize threadgroupCount = MTLSizeMake(inputTexture.width, inputTexture.height, 1);
MTLSize _threadgroupSize = MTLSizeMake(16, 16, 1);
threadgroupCount.width = (inputTexture.width + _threadgroupSize.width - 1) / _threadgroupSize.width;
threadgroupCount.height = (inputTexture.height + _threadgroupSize.height - 1) / _threadgroupSize.height;
size_t columnBufSize = sizeof(UInt64)*inputTexture.width*inputTexture.height;
id<MTLBuffer> columnDataRed = [kDevice newBufferWithLength:columnBufSize options:0];
id<MTLBuffer> columnDataGreen = [kDevice newBufferWithLength:columnBufSize options:0];
id<MTLBuffer> columnDataBlue = [kDevice newBufferWithLength:columnBufSize options:0];
id<MTLComputeCommandEncoder> computeEncoder;
computeEncoder = [commandBuffer computeCommandEncoder];
[computeEncoder setComputePipelineState:kWaveformComputePipelineState];
[computeEncoder setTexture:inputTexture atIndex:0];
[computeEncoder setBuffer:columnDataRed offset:0 atIndex:0];
[computeEncoder setBuffer:columnDataGreen offset:0 atIndex:1];
[computeEncoder setBuffer:columnDataBlue offset:0 atIndex:2];
[computeEncoder setSamplerState:kSamplerState atIndex:0];
[computeEncoder dispatchThreadgroups:threadgroupCount
threadsPerThreadgroup:_threadgroupSize];
[computeEncoder endEncoding];
computeEncoder = [commandBuffer computeCommandEncoder];
[computeEncoder setComputePipelineState:renderComputerState];
[computeEncoder setTexture:inputTexture atIndex:0];
[computeEncoder setTexture:outputTexture atIndex:1];
[computeEncoder setBuffer:columnDataRed offset:0 atIndex:0];
[computeEncoder setBuffer:columnDataGreen offset:0 atIndex:1];
[computeEncoder setBuffer:columnDataBlue offset:0 atIndex:2];
[computeEncoder setSamplerState:kSamplerState atIndex:0];
[computeEncoder dispatchThreadgroups:threadgroupCount
threadsPerThreadgroup:_threadgroupSize];
[computeEncoder endEncoding];
return YES;
}
这是我的翻译
override class func process(with inputs: [CIImageProcessorInput]?, arguments: [String : Any]?, output: CIImageProcessorOutput) throws {
guard
let kDevice = device,
let commandBuffer = output.metalCommandBuffer,
let input = inputs?.first,
let defaultLibrary: MTLLibrary = kDevice.makeDefaultLibrary()
else {
return
}
let samplerDescriptor = MTLSamplerDescriptor()
let kSamplerState = kDevice.makeSamplerState(descriptor: samplerDescriptor)
samplerDescriptor.sAddressMode = .clampToEdge
samplerDescriptor.tAddressMode = .clampToEdge
samplerDescriptor.minFilter = .nearest
samplerDescriptor.magFilter = .nearest
samplerDescriptor.normalizedCoordinates = false
var kWaveformComputePipelineState: MTLComputePipelineState?
var kParadeComputePipelineState: MTLComputePipelineState?
if let aFunction = defaultLibrary.makeFunction(name: "scope_waveform_compute") {
kWaveformComputePipelineState = try? kDevice.makeComputePipelineState(function: aFunction)
}
if let aFunction = defaultLibrary.makeFunction(name: "scope_waveform_parade") {
kParadeComputePipelineState = try? kDevice.makeComputePipelineState(function: aFunction)
}
commandBuffer.label = "com.martinhering.WaveformKernel"
weak var inputTexture: MTLTexture? = input.metalTexture
weak var outputTexture: MTLTexture? = output.metalTexture
var threadgroupCount: MTLSize = MTLSizeMake(inputTexture!.width, inputTexture!.height, 1)
let threadgroupSize: MTLSize = MTLSizeMake(16, 16, 1)
threadgroupCount.width = (inputTexture!.width + threadgroupSize.width - 1) / threadgroupSize.width
threadgroupCount.height = (inputTexture!.height + threadgroupSize.height - 1) / threadgroupSize.height
let columnBufSize: size_t = MemoryLayout<UInt64>.size * inputTexture!.width * inputTexture!.height
let columnDataRed: MTLBuffer = kDevice.makeBuffer( length: columnBufSize, options: .storageModeShared)!
let columnDataGreen: MTLBuffer = kDevice.makeBuffer( length: columnBufSize, options: .storageModeShared)!
let columnDataBlue: MTLBuffer = kDevice.makeBuffer( length: columnBufSize, options: .storageModeShared)!
weak var computeEncoder: MTLComputeCommandEncoder?
computeEncoder = commandBuffer.makeComputeCommandEncoder()
computeEncoder?.setComputePipelineState(kWaveformComputePipelineState!)
computeEncoder?.setTexture(inputTexture, index: 0)
computeEncoder?.setBuffer(columnDataRed, offset: 0, index: 0)
computeEncoder?.setBuffer(columnDataGreen, offset: 0, index: 1)
computeEncoder?.setBuffer(columnDataBlue, offset: 0, index: 2)
computeEncoder?.setSamplerState(kSamplerState, index: 0)
computeEncoder?.dispatchThreadgroups(threadgroupCount, threadsPerThreadgroup: threadgroupSize)
computeEncoder?.endEncoding()
computeEncoder = commandBuffer.makeComputeCommandEncoder()
computeEncoder?.setComputePipelineState(kParadeComputePipelineState!)
computeEncoder?.setTexture(inputTexture, index: 0)
computeEncoder?.setTexture(outputTexture, index: 1)
computeEncoder?.setBuffer(columnDataRed, offset: 0, index: 0)
computeEncoder?.setBuffer(columnDataGreen, offset: 0, index: 1)
computeEncoder?.setBuffer(columnDataBlue, offset: 0, index: 2)
computeEncoder?.setSamplerState(kSamplerState, index: 0)
computeEncoder?.dispatchThreadgroups(threadgroupCount, threadsPerThreadgroup: threadgroupSize)
computeEncoder?.endEncoding()
//返回true
}
答案 0 :(得分:0)
非常感谢Ken Thomases;最后这很简单。
在创建samplerState之前,必须设置采样器描述符的属性。
sum()