Prática recomendada para definir parâmetros de efeito no XNA

13

Quero perguntar se existe uma prática recomendada para definir Effectparâmetros no XNA. Ou, em outras palavras, o que exatamente acontece quando ligo pass.Apply(). Eu posso imaginar vários cenários:

  1. Cada vez que Applyé chamado, todos os parâmetros de efeito são transferidos para a GPU e, portanto, não tem nenhuma influência real com que frequência eu defino um parâmetro.
  2. Cada vez que Applyé chamado, apenas os parâmetros que foram redefinidos são transferidos. Portanto, operações em cache de Set que realmente não definem um novo valor devem ser evitadas.
  3. Cada vez que Applyé chamado, apenas os parâmetros que foram alterados são transferidos. Portanto, o cache de operações Set é inútil.
  4. Toda essa pergunta não tem inicialização porque nenhuma das formas mencionadas tem um impacto notável no desempenho do jogo.

Portanto, a pergunta final: é útil implementar algum cache da operação de conjunto, como:

private Matrix _world;
public Matrix World
{
    get{ return _world; }
    set 
    {
        if (value == world) return;
        _effect.Parameters["xWorld"].SetValue(value);
        _world = value;
    }
}

Agradecendo antecipadamente.

0xBADF00D
fonte
Eu adicionei a tag DirectX, com base em que essa é uma funcionalidade de nível inferior ao XNA.
Andrew Russell
Encontrei provas de que o tópico em questão é MUITO viável. Parece que, se você é inteligente com a maneira como define seus parâmetros de efeito, pode aumentar o número de chamadas de empate (ou seja, a rapidez com que são processadas na CPU) mais de duas vezes. Eu ainda estou no processo de testar isso, você pode ler minha pergunta aqui: gamedev.stackexchange.com/questions/66932/…
cubrman

Respostas:

8

Isso tudo acontece no lado da CPU; portanto, se o cache fosse um recurso útil, especularia que o driver gráfico fosse implementado por si próprio. Não é necessário adicionar sua própria camada de armazenamento em cache.

Meu entendimento é que, sempre que você define um parâmetro e sempre que chama Apply, essas chamadas são passadas para o DirectX em grande parte como estão e, por sua vez, para o driver da GPU no modo de usuário. O driver no modo de usuário pode fazer o que quiser . Todos os três dos seus cenários são possíveis.

(Como o cenário 2 é uma possibilidade, provavelmente é melhor não andar deliberadamente redefinindo parâmetros que não mudam.)

Para ser sincero, não tenho muita certeza do que um motorista típico faz. Principalmente porque nunca é realmente um problema. Eu nunca ouvi falar de alguém que tenha parâmetros de efeito como gargalo. Talvez possa ser, em teoria. Mas há tantas coisas mais comuns com que se preocupar .

Certamente não comece a implementar otimizações como essa sem medir seu desempenho e entender o que está acontecendo.

Além disso, comparar um Matrixcom ==é um vodu ruim. A Matrixé composto por floats, e as comparações de igualdade de ponto flutuante são propensas a falhas em muitos casos.

E, de um modo geral, o padrão if(x != y) x = y;é mais lento do que simplesmente x = y.

Andrew Russell
fonte
Ponto interessante que o motorista deve se preocupar com isso. Obrigado pelo link (e re-links).
0xBADF00D 15/10/12
Recentemente me deparei com o exemplo de instanciação de geometria do msdn . Redefinir as mesmas taxas de classificação (com os mesmos valores) várias vezes por quadro diminui significativamente o processo de renderização em duas ou três vezes. Portanto, o lote em estado é deferencialmente útil. Infelizmente, não tenho certeza se esta situação se aplica também à definição de parâmetros de efeito. Mas eu gostaria de compartilhar minhas informações.
0xBADF00D
4

Uma coisa interessante que encontrei sobre esse tópico.

Do msdn:

Você pode usar a propriedade indexada Parameters em Effect para acessar qualquer parâmetro de efeito, mas isso é mais lento do que usar EffectParameters. Por esse motivo, você deve criar um EffectParameter para cada parâmetro de efeito que muda frequentemente.

e

Criar e atribuir uma instância EffectParameter para cada técnica no Effect é significativamente mais rápido do que usar a propriedade indexada Parameters no Effect.

Isso significa que _effect.Parameters["xWorld"].SetValue(value);é visivelmente mais lento quewordlParam.SetValue(value);

Portanto, você provavelmente deve armazenar em cache parâmetros como este:

public EffectParameter wordlParam;
wordlParam = _effect.Parameters["xWorld"];

Mas não encontrei nenhum benchmark real.

Fontes:

http://msdn.microsoft.com/en-us/library/Microsoft.Xna.Framework.Graphics.EffectParameter%28v=xnagamestudio.40%29.aspx http://msdn.microsoft.com/en-us/library /bb976060%28v=xnagamestudio.31%29.aspx

ziguezague
fonte
Acabei de testar isso no emulador Monogame e WP - posso confirmar que, de fato, há uma diferença significativa (entre 5 e 15% no meu caso). Existem mais truques que ajudam no desempenho?
Konrad