Ios 优化渲染MTLTexture以显示的性能?

Ios 优化渲染MTLTexture以显示的性能?,ios,performance,metal,mtkview,Ios,Performance,Metal,Mtkview,我用以下代码向显示器演示MTLTexture。这是一个大的(~12k)纹理,大约需要10毫秒来绘制。因为我需要渲染至少30FPS(33ms/帧),所以仅仅显示纹理就要花费将近三分之一的计算时间 有什么技巧可以提高性能并更快地绘制纹理吗?在GPU帧捕获中,它显示了大量的消隐时间。我尝试启用/禁用剔除,但我仍然看到用于剔除的时间相同 vertex TextureMappingVertex mapTexture(unsigned int vertex_id [[ vertex_id ]], const

我用以下代码向显示器演示MTLTexture。这是一个大的(~12k)纹理,大约需要10毫秒来绘制。因为我需要渲染至少30FPS(33ms/帧),所以仅仅显示纹理就要花费将近三分之一的计算时间

有什么技巧可以提高性能并更快地绘制纹理吗?在GPU帧捕获中,它显示了大量的消隐时间。我尝试启用/禁用剔除,但我仍然看到用于剔除的时间相同

vertex TextureMappingVertex mapTexture(unsigned int vertex_id [[ vertex_id ]], constant Uniforms& uniforms [[ buffer(0) ]]) {

    float4x4 renderedCoordinates = float4x4(float4( -1.f, -1.f, 0.f, 1.f ),
                                        float4(  1.f, -1.f, 0.f, 1.f ),
                                        float4( -1.f,  1.f, 0.f, 1.f ),
                                        float4(  1.f,  1.f, 0.f, 1.f ));

    float4x2 textureCoordinates = float4x2(float2( 0.f, 1.f ),
                                       float2( 1.f, 1.f ),
                                       float2( 0.f, 0.f ),
                                       float2( 1.f, 0.f ));
    TextureMappingVertex outVertex;
    outVertex.renderedCoordinate = uniforms.mvp_matrix * renderedCoordinates[vertex_id];
    outVertex.textureCoordinate = textureCoordinates[vertex_id];
    return outVertex;
}

fragment half4 displayTexture(TextureMappingVertex mappingVertex [[ stage_in ]],
                          texture2d<half, access::sample> texture [[ texture(0) ]]) {

    constexpr sampler s(address::clamp_to_edge, filter::nearest);
    return half4(texture.sample(s, mappingVertex.textureCoordinate));
}

func draw(in view: MTKView) {

    guard let commandBuffer = commandQueue.makeCommandBuffer() else { return }
    guard let descriptor = view.currentRenderPassDescriptor else {return}

    let render = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor)
    render?.pushDebugGroup("Render to Screen")
    render?.setRenderPipelineState(renderCanvasPipelineState)
    render?.setFragmentTexture(canvasTexture, index: 0)
    render?.setVertexBuffer(uniformBuffer, offset: 0, index: 0)
    render?.setCullMode(.none)

    render?.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4, instanceCount: 1)
    render?.popDebugGroup()
    render?.endEncoding()

    guard let drawable = view.currentDrawable else { return }
    commandBuffer.present(drawable)

    commandBuffer.commit()
}

func initializeCanvasRenderPipelineState() {
    let library = Renderer.device.makeDefaultLibrary()
    let pipelineDescriptor = MTLRenderPipelineDescriptor()
    pipelineDescriptor.sampleCount = 1
    pipelineDescriptor.rasterSampleCount = 1
    pipelineDescriptor.colorAttachments[0].pixelFormat = .rgba8Unorm
    pipelineDescriptor.depthAttachmentPixelFormat = .invalid
    pipelineDescriptor.vertexFunction = library?.makeFunction(name: "mapTexture")
    pipelineDescriptor.fragmentFunction = library?.makeFunction(name: "displayTexture")

    pipelineDescriptor.colorAttachments[0].isBlendingEnabled = false

    do {
        try renderCanvasPipelineState = Renderer.device.makeRenderPipelineState(descriptor: pipelineDescriptor)
    }
    catch {
        assertionFailure("Failed creating a render state pipeline. Can't render the texture without one.")
        return
    }
}
vertex TextureMappingVertex贴图纹理(无符号整数顶点id[[vertex_id]],常量制服和制服[[buffer(0)]){
float4x4 renderedCoordinates=float4x4(float4(-1.f,-1.f,0.f,1.f),
浮动4(1.f,-1.f,0.f,1.f),
浮动4(-1.f,1.f,0.f,1.f),
浮动4(1.f,1.f,0.f,1.f));
float4x2纹理坐标=float4x2(float2(0.f,1.f),
浮动2(1.f,1.f),
浮动2(0.f,0.f),
浮动2(1.f,0.f));
TextureMappingVertex outVertex;
outVertex.renderedCoordinate=uniforms.mvp_矩阵*renderedCoordinates[vertex_id];
outVertex.TextureCoordination=纹理坐标[顶点id];
返回顶点;
}
fragment half4 displayTexture(TextureMappingVertex贴图顶点[[stage_in]],
纹理2D纹理[[纹理(0)]){
constexpr采样器s(地址:钳制到边缘,过滤器:最近);
返回half4(纹理.sample(s,mappingVertex.textureCoordinate));
}
func绘图(视图中:MTKView){
guard let commandBuffer=commandQueue.makeCommandBuffer()else{return}
guard let descriptor=view.currentRenderPassDescriptor else{return}
让render=commandBuffer.makeRenderCommandEncoder(描述符:描述符)
渲染?.pushDebugGroup(“渲染到屏幕”)
render?.setRenderPipelineState(renderCanvasPipelineState)
render?.setFragmentTexture(CanvaTexture,索引:0)
render?.setVertexBuffer(uniformBuffer,偏移量:0,索引:0)
渲染?.setCullMode(.none)
render?.drawPrimitives(类型:.triangleStrip,vertexStart:0,vertexCount:4,instanceCount:1)
render?.popDebugGroup()
渲染?.endEncoding()
guard let drawable=view.currentDrawable else{return}
commandBuffer.present(可提取)
commandBuffer.commit()
}
func initializeCanvasRenderPipelineState(){
let library=Renderer.device.makeDefaultLibrary()
让pipelineDescriptor=MTLRenderPipelineDescriptor()
pipelineDescriptor.sampleCount=1
pipelineDescriptor.rasterSampleCount=1
pipelineDescriptor.colorAttachments[0]。pixelFormat=.rgba8Unorm
pipelineDescriptor.DepthatAttachmentPixelFormat=。无效
pipelineDescriptor.vertexFunction=library?.makeFunction(名称:“mapTexture”)
pipelineDescriptor.fragmentFunction=library?.makeFunction(名称:“displayTexture”)
pipelineDescriptor.colorAttachments[0]。isBlendingEnabled=false
做{
尝试renderCanvasPipelineState=Renderer.device.makeRenderPipelineState(描述符:pipelineDescriptor)
}
抓住{
assertionFailure(“创建渲染状态管道失败。没有管道无法渲染纹理。”)
返回
}
}

制服.mvp\U矩阵是如何设置的?您是否总是正面绘制四边形,只是缩放和平移x和y(并围绕z旋转?),以获得所需的零件?或者,您是否有可能绕其他轴旋转?我想你可以通过画一个没有延伸到窗口外的四边形来避免剔除,而是调整纹理坐标来选择你想要采样的纹理部分;我只是缩放和平移,没有旋转。如果有帮助,我可以添加代码。有趣。所以保持四边形静止,但平移/缩放纹理坐标?所以我现在只是做了一些实验,硬连接纹理坐标,如果显示完整的纹理,性能实际上没有任何提高。但当我将纹理放大到2倍时,速度大约是2倍。我不确定它是否值得实现,因为我认为大多数情况下都会显示完整的纹理。还有什么我可以试试的吗?你的用例真的需要3D吗?或者你“仅仅”需要在屏幕上显示一个纹理(变换)吗?严格来说,它本质上只是显示一个图像。