ti-enxame.com

Traçando caminhos e aceleração de hardware

Estou traçando um caminho bastante amplo na minha visão e estou enfrentando alguns problemas de desempenho. Atualmente, o caminho tem 32.000 pontos, mas meu aplicativo deve ser escalado para pelo menos 128.000 pontos. Eu realmente não posso fazer nada sobre o tamanho do caminho, pois os conjuntos de dados são grandes e eu preciso exibir o caminho inteiro de uma só vez e permitir o zoom.

Estou usando um Nexus 10 executando Android 4.2, que tem a aceleração de hardware ativada por padrão para aplicativos que não o desativam explicitamente.

O caminho é criado com o seguinte código (omiti algumas configurações e outras partes irrelevantes):

dataPath.moveTo(0, offset - (float) data[leftLimit]/ scalingFactor);
        for (int i = leftLimit; i < rightLimit; ++i) {
            x = (i - leftLimit) * dx;
            y = offset - (float) data[i]/ scalingFactor;
            dataPath.lineTo(x, y);
        }

E então desenhado no método onDraw():

canvas.drawColor(Color.WHITE);
canvas.drawPath(dataPath, linePaint);

Avaliei o tempo necessário para desenhar minha visão usando adb Shell dumpsys gfxinfo Com e sem aceleração de hardware e, para minha surpresa, a aceleração de hardware é muito mais lenta:

Com aceleração de hardware:

enter image description here

Sem aceleração de hardware:

enter image description here

A versão acelerada por hardware leva cerca de 200 a 300 ms por quadro, a maioria gasta no estágio Process. A versão não acelerada leva cerca de 50 ms, com 2/3 no estágio Draw e 1/3 no estágio do processo.

Obviamente, mesmo a minha versão mais rápida, sem aceleração de hardware, ainda é lenta demais para atingir 60 qps ou até mesmo quase não pode ser usada quando eu mudo para conjuntos de dados maiores.

A ideia de renderizar o caminho para um bitmap e depois transformá-lo apenas para caber na tela também é problemática no meu caso. Eu preciso dar suporte ao zoom muito longe no caminho e, para ativar o zoom sem que a qualidade do caminho piore muito, eu precisaria renderizar bitmaps de tamanho grande do caminho (e provavelmente teria limites de memória e limites de tamanho de textura). E ao aumentar o zoom, eu teria que criar imagens mais recentes de apenas partes do caminho ou mudar para renderizar o caminho diretamente, o que provavelmente levaria a atrasos maiores que a taxa de quadros se o desempenho ainda fosse semelhante ao que eu tenho direito agora.

O que eu estou querendo saber agora é

  • Desenhar linhas/caminhos é apenas algo em que a GPU é ruim e que não se deve tentar acelerar o hardware, ou provavelmente estou fazendo algo errado que causa o mau desempenho?
  • Há algo que eu possa fazer para traçar caminhos tão grandes com desempenho aceitável?
36
Mad Scientist

Desenhar linhas/caminhos é apenas algo em que a GPU é ruim e que não se deve tentar acelerar o hardware, ou provavelmente estou fazendo algo errado que causa o mau desempenho?

Os caminhos são sempre renderizados usando a CPU. Quando o aplicativo é acelerado por hardware, isso significa que o renderizador primeiro desenha seu caminho usando a CPU em um bitmap, depois carrega esse bitmap como textura na GPU e, finalmente, desenha a textura na tela.

As linhas são totalmente aceleradas por hardware. Em vez de usar um Path, recomendo que você use Canvas.drawLines() neste caso.

Há algo que eu possa fazer para traçar caminhos tão grandes com desempenho aceitável?

Você deve usar Canvas.drawLines() ou transformar o caminho em um Bitmap que você gerencia.

49
Romain Guy

Parece que você pode estar enfrentando um gargalo geral na GPU. Dê uma olhada nos seguintes links:

Como tornar o desenho da rota mais eficiente

desempenho do caminho da tela do Android em tempo real

Mudando da tela para o OpenGL

Especialmente o primeiro, que sugere que você faça um bitmap e desenhe-o. Parece que você pode obter um desempenho melhor se mudar para o openGL. Pode haver alguma maneira mágica de fazer com que o método existente funcione, mas não estou ciente disso no momento.

O motivo pelo qual você está vendo o comportamento é provavelmente porque você envia todos os dados para a GPU entre cada sorteio. Você deve armazená-lo em cache na GPU e usar a tradução em vez disso. Não recriando os dados e enviando tudo para a GPU. Você provavelmente está ligado a E/S , o que significa que a taxa de transmissão entre a CPU e a GPU é o que está limitando seu desempenho. Não posso ter 100% de certeza disso com base nos dados que você forneceu, mas esse é o meu melhor palpite. Tente diferentes técnicas de cache, principalmente o png-cache do link # 1.

5
Automatico

Desenhar um caminho envolverá mais do que "dizer" à GPU para desenhar linhas. Um caminho tem muitas características, por exemplo, como as extremidades das linhas são tratadas ou que uma linha é pontilhada, algo que é não GPU acelerado. Provavelmente existe outro hickup quando você encontra muitas linhas que tornam a combinação de aceleração de CPU e GPU mais lenta. A solução sugerida acima para ir para canvas.drawLines ao invés de canvs.drawPath e tente não usar um método sofisticado Paint pode ajudar.

Se isso não ajudar, você pode tentar usar um GLSurfaceView e renderizar linhas diretamente nele. Isso envolverá algum conhecimento do OpenGL ES, mas não deve ser incrivelmente difícil de fazer e pode ser muito mais eficaz.

3
Arne Bergene Fossaa