金属计算内核中的Mipmap采样器(不是顶点或片段着色器)

时间:2018-01-16 02:45:31

标签: swift metal compute-shader mipmaps

我有一个源纹理(480x480)是使用mipmapped设置为true创建的(错误检查已删除到简单的帖子),以及dest纹理(100x100):

pilfotgnirts

定义了采样器:

// source texture
var textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: MTLPixelFormat.r8Unorm, width: Int(480), height: Int(480), mipmapped: true)
textureDescriptor.usage = .unknown // .shaderWrite .shaderRead
srcTexture = metalDevice!.makeTexture(descriptor: textureDescriptor)
// Dest texture
textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: MTLPixelFormat.r8Unorm, width: Int(100), height: Int(100), mipmapped: false)
textureDescriptor.usage = .shaderWrite
destTexture = metalDevice!.makeTexture(descriptor: textureDescriptor)

我用图像填充了src纹理。

然后生成了mipmap:

let samplerDescriptor = MTLSamplerDescriptor()
samplerDescriptor.magFilter = .linear
samplerDescriptor.minFilter = .linear
samplerDescriptor.rAddressMode = .clampToZero
samplerDescriptor.sAddressMode = .clampToZero
samplerDescriptor.tAddressMode = .clampToZero
samplerDescriptor.normalizedCoordinates = true
textureSampler = metalDevice!.makeSamplerState(descriptor: samplerDescriptor)

在同一个命令缓冲区中,运行调整大小内核:

let blitEncoder = metalCommandBuffer!.makeBlitCommandEncoder()
blitEncoder!.pushDebugGroup("Dispatch mipmap kernel")
blitEncoder!.generateMipmaps(for: srcTexture!);
blitEncoder!.popDebugGroup()
blitEncoder!.endEncoding()

计算内核是(记住,这不是一个片段着色器,它会自动知道如何设置mipmap级别的细节):

let computeEncoder = metalCommandBuffer!.makeComputeCommandEncoder()
computeEncoder!.pushDebugGroup("Dispatch resize image kernel")
computeEncoder!.setComputePipelineState(resizeImagePipeline)
computeEncoder!.setTexture(srcTexture, index: 0)
computeEncoder!.setTexture(destTexture, index: 1)
computeEncoder!.setSamplerState(textureSampler, index: 0)
let threadGroupCount = MTLSizeMake(20, 10, 1)
let threadGroups = MTLSizeMake(destTexture!.width / threadGroupCount.width, destTexture!.height / threadGroupCount.height, 1)
computeEncoder!.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount)
computeEncoder!.popDebugGroup()
computeEncoder!.endEncoding()

无论lod设置为什么,我都会得到完全相同的像素化结果。为什么mipmapping不工作? 感谢您提供的任何帮助。

1 个答案:

答案 0 :(得分:0)

如果您想选择(或偏向)LOD,您的采样器必须指定 mip 过滤器(不同于 min mag 过滤器):

samplerDescriptor.mipFilter = .nearest

在此上下文中使用.nearest将使用您似乎正在寻找的双线性过滤捕捉到最近的LOD并从中取样。您还可以指定.linear,它将使用三线性过滤在两个最近的级别之间进行插值。