Оптимизировать производительность рендеринга MTLTexture для отображения? - PullRequest
0 голосов
/ 29 января 2020

Я представляю текстуру MTL на дисплей со следующим кодом. Это большая (~ 12k) текстура, на рисование которой уходит около 10 мс. Так как мне нужно визуализировать по крайней мере 30FPS (33 мс / кадр), мне требуется почти одна треть моего вычислительного времени, чтобы отобразить текстуру.

Есть ли какие-нибудь хитрости для увеличения производительности и ускорения рисования текстуры? В GPU Frame Capture он показывает много времени для отбраковки. Я попытался включить / отключить отбор, но все еще вижу, что это же время используется для отбраковки.

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
    }
}
...