Copyright (c) 2023 Advanced Micro Devices, Inc. Todos os direitos reservados.
É concedida permissão, gratuitamente, a qualquer pessoa que obtenha uma cópia deste software e dos arquivos de documentação associados (o "Software"), para negociar o Software sem restrições, incluindo, sem limitação, os direitos de usar, copiar, modificar, mesclar , publicar, distribuir, sublicenciar e/ou vender cópias do Software, e permitir que as pessoas a quem o Software é fornecido o façam, sujeito às seguintes condições: O aviso de direitos autorais acima e este aviso de permissão serão incluídos em todas as cópias ou partes substanciais do Software.
O SOFTWARE É FORNECIDO "COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO ÀS GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UM DETERMINADO FIM E NÃO VIOLAÇÃO. EM HIPÓTESE ALGUMA OS AUTORES OU DETENTORES DE DIREITOS AUTORAIS SERÃO RESPONSÁVEIS POR QUALQUER RECLAMAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM UMA AÇÃO DE CONTRATO, ATO ILÍCITO OU DE OUTRA FORMA, DECORRENTE DE, OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTRAS NEGOCIAÇÕES NO SOFTWARE.
FSR2 usa feedback temporal para reconstruir imagens de alta resolução enquanto mantém e até melhora a qualidade da imagem em comparação com a renderização nativa.
O FSR2 pode permitir “desempenho prático” para operações de renderização caras, como ray tracing de hardware.
HLSL
CS_6_2
CS_6_6*
* - CS_6_6 é usado em alguns hardwares que suportam frentes de onda de 64 larguras.
Para usar o FSR2 você deve seguir os passos abaixo:
Clique duas vezes em GenerateSolutions.bat
no diretório build
.
Abra a solução correspondente à sua API e crie a solução.
Copie a biblioteca API de bin/ffx_fsr2_api
para a pasta que contém uma pasta em seu projeto que contém bibliotecas de terceiros.
Copie a biblioteca correspondente ao backend FSR2 que você deseja usar, por exemplo: bin/ffx_fsr2_api/ffx_fsr2_api_dx12_x64.lib
para DirectX12.
Copie os seguintes arquivos principais de cabeçalho da API de src/ffx-fsr2-api em seu projeto: ffx_fsr2.h
, ffx_types.h
, ffx_error.h
, ffx_fsr2_interface.h
, ffx_util.h
, shaders/ffx_fsr2_common.h
e shaders/ffx_fsr2_resources.h
. Deve-se tomar cuidado para manter a estrutura de diretórios relativa no destino da cópia do arquivo.
Copie os arquivos de cabeçalho para o backend da API de sua escolha, por exemplo, para DirectX12 você copiaria dx12/ffx_fsr2_dx12.h
e dx12/shaders/ffx_fsr2_shaders_dx12.h
. Deve-se tomar cuidado para manter a estrutura de diretórios relativa no destino da cópia do arquivo.
Inclua o arquivo de cabeçalho ffx_fsr2.h
em sua base de código onde você deseja interagir com o FSR2.
Crie um back-end para sua API de destino. Por exemplo, para DirectX12 você deve chamar ffxFsr2GetInterfaceDX12
. Um buffer temporário deve ser alocado com o tamanho retornado chamando ffxFsr2GetScratchMemorySizeDX12
e o ponteiro para esse buffer passado para ffxFsr2GetInterfaceDX12
.
Crie um contexto FSR2 chamando ffxFsr2ContextCreate
. A estrutura dos parâmetros deve ser preenchida de acordo com a configuração da sua aplicação. Consulte a documentação de referência da API para obter mais detalhes.
Cada quadro você deve chamar ffxFsr2ContextDispatch
para iniciar cargas de trabalho FSR2. A estrutura dos parâmetros deve ser preenchida de acordo com a configuração da sua aplicação. Consulte a documentação de referência da API para obter mais detalhes e certifique-se de que o campo frameTimeDelta
seja fornecido em milissegundos.
Quando seu aplicativo estiver encerrando (ou você desejar destruir o contexto por outro motivo), você deverá chamar ffxFsr2ContextDestroy
. A GPU deve estar ociosa antes de chamar esta função.
A tremulação de subpixel deve ser aplicada à matriz de projeção do seu aplicativo. Isso deve ser feito ao realizar a renderização principal da sua aplicação. Você deve usar a função ffxFsr2GetJitterOffset
para calcular os deslocamentos precisos de jitter. Consulte a seção Tremulação da câmera para obter mais detalhes.
Para obter a melhor qualidade de upscaling, é altamente recomendável preencher a máscara reativa e a máscara de transparência e composição de acordo com nossas diretrizes. Você também pode usar ffxFsr2ContextGenerateReactiveMask
como ponto de partida.
Os aplicativos devem expor modos de escalabilidade em sua interface de usuário na seguinte ordem: Qualidade, Balanceado, Desempenho e (opcionalmente) Ultra Desempenho.
Os aplicativos também devem expor um controle deslizante de nitidez para permitir que os usuários finais obtenham qualidade adicional.
Para conveniência dos usuários finais, a API FSR2 fornece uma série de taxas de escala predefinidas que são nomeadas.
Qualidade | Fator de escala por dimensão |
---|---|
Qualidade | 1,5x |
Equilibrado | 1,7x |
Desempenho | 2,0x |
Ultradesempenho | 3,0x |
Recomendamos fortemente que os aplicativos adotem taxas de nomenclatura e escalamento consistentes em sua interface de usuário. Isso é para garantir que a experiência do usuário seja consistente para os usuários do seu aplicativo, que podem ter experiência com outros aplicativos usando FSR2.
Dependendo do hardware alvo e da configuração operacional, o FSR2 operará em diferentes níveis de desempenho.
A tabela abaixo resume o desempenho medido do FSR2 em uma variedade de hardware no DX12.
Resolução alvo | Qualidade | RX 7900 XTX | RX 6950 XT | RX 6900 XT | RX 6800 XT | RX6800 | RX 6700 XT | RX 6650 XT | RX 5700 XT | RX Vega 56 | RX 590 |
---|---|---|---|---|---|---|---|---|---|---|---|
3840x2160 | Qualidade (1,5x) | 0,7ms | 1,1ms | 1,2ms | 1,2ms | 1,4ms | 2,0ms | 2,8ms | 2,4ms | 4,9ms | 5,4ms |
Equilibrado (1,7x) | 0,6ms | 1,0ms | 1,0ms | 1,1ms | 1,4ms | 1,8ms | 2,6ms | 2,2ms | 4,1ms | 4,9ms | |
Desempenho (2x) | 0,6ms | 0,9ms | 1,0ms | 1,0ms | 1,3ms | 1,7ms | 2,3ms | 2,0ms | 3,6ms | 4,4ms | |
Ultraperf. (3x) | 0,5ms | 0,8ms | 0,8ms | 0,9ms | 1,1ms | 1,5ms | 1,8ms | 1,7ms | 2,9ms | 3,7ms | |
2560x1440 | Qualidade (1,5x) | 0,3ms | 0,5ms | 0,5ms | 0,5ms | 0,7ms | 0,9ms | 1,2ms | 1,1ms | 1,9ms | 2,3ms |
Equilibrado (1,7x) | 0,3ms | 0,5ms | 0,5ms | 0,5ms | 0,6ms | 0,8ms | 1,1ms | 1,0ms | 1,7ms | 2,1ms | |
Desempenho (2x) | 0,3ms | 0,4ms | 0,4ms | 0,4ms | 0,6ms | 0,8ms | 0,9ms | 0,9ms | 1,5ms | 1,9ms | |
Ultraperf. (3x) | 0,2ms | 0,4ms | 0,4ms | 0,4ms | 0,5ms | 0,7ms | 0,8ms | 0,8ms | 1,2ms | 1,7ms | |
1920x1080 | Qualidade (1,5x) | 0,2ms | 0,3ms | 0,3ms | 0,3ms | 0,4ms | 0,5ms | 0,6ms | 0,6ms | 1,0ms | 1,3ms |
Equilibrado (1,7x) | 0,2ms | 0,3ms | 0,3ms | 0,3ms | 0,4ms | 0,5ms | 0,6ms | 0,6ms | 0,9ms | 1,2ms | |
Desempenho (2x) | 0,2ms | 0,2ms | 0,2ms | 0,3ms | 0,3ms | 0,5ms | 0,5ms | 0,5ms | 0,8ms | 1,1ms | |
Ultraperf. (3x) | 0,1ms | 0,2ms | 0,2ms | 0,2ms | 0,3ms | 0,4ms | 0,4ms | 0,4ms | 0,7ms | 0,9ms |
Os números são arredondados para o 0,1 ms mais próximo e não têm sharpness
adicional e estão sujeitos a alterações.
O uso do FSR2 requer que alguma memória local da GPU adicional seja alocada para consumo pela GPU. Ao usar a API FSR2, essa memória é alocada quando o contexto FSR2 é criado, e isso é feito por meio de uma série de retornos de chamada que compõem a interface backend. Esta memória é usada para armazenar superfícies intermediárias que são calculadas pelo algoritmo FSR2, bem como superfícies que são persistentes em muitos quadros da aplicação. A tabela abaixo inclui a quantidade de memória usada pelo FSR2 sob diversas condições operacionais. A coluna "Conjunto de trabalho" indica a quantidade total de memória usada pelo FSR2 enquanto o algoritmo está sendo executado na GPU; esta é a quantidade de memória que o FSR2 exigirá para ser executado. A coluna "Memória persistente" indica quanto da coluna "Conjunto de trabalho" deve ser deixado intacto para os quadros subsequentes do aplicativo; esta memória armazena os dados temporais consumidos pelo FSR2. A coluna "Memória aliasável" indica quanto da coluna "Conjunto de trabalho" pode ser alias por superfícies ou outros recursos usados pelo aplicativo fora dos limites operacionais do FSR2.
Você pode assumir o controle da criação de recursos no FSR2 substituindo as partes de criação e destruição de recursos da interface backend do FSR2 e encaminhando os sinalizadores de alias. Isto significa que para uma integração perfeita do FSR2, é necessária memória adicional igual à coluna "Memória persistente" da tabela abaixo, dependendo de suas condições de operação.
Resolução | Qualidade | Conjunto de trabalho (MB) | Memória persistente (MB) | Memória aliasável (MB) |
---|---|---|---|---|
3840x2160 | Qualidade (1,5x) | 448 MB | 354 MB | 93 MB |
Equilibrado (1,7x) | 407 MB | 330 MB | 77 MB | |
Desempenho (2x) | 376MB | 312 MB | 63MB | |
Ultradesempenho (3x) | 323 MB | 281 MB | 42MB | |
2560x1440 | Qualidade (1,5x) | 207MB | 164 MB | 43MB |
Equilibrado (1,7x) | 189 MB | 153 MB | 36 MB | |
Desempenho (2x) | 172 MB | 143 MB | 29MB | |
Ultradesempenho (3x) | 149 MB | 130MB | 19MB | |
1920x1080 | Qualidade (1,5x) | 115MB | 90MB | 24MB |
Equilibrado (1,7x) | 105 MB | 85MB | 20MB | |
Desempenho (2x) | 101MB | 83MB | 18 MB | |
Ultradesempenho (3x) | 84 MB | 72MB | 11 MB |
Os números são aproximações, arredondados para o MB mais próximo usando uma GPU RX 6700XT em DX12 e estão sujeitos a alterações.
Para obter detalhes sobre como gerenciar os requisitos de memória do FSR2, consulte a seção deste documento que trata do gerenciamento de memória.
FSR2 é um algoritmo temporal e, portanto, requer acesso aos dados do quadro atual e do quadro anterior. A tabela a seguir enumera todas as entradas externas exigidas pelo FSR2.
A coluna de resolução indica se os dados devem estar na resolução 'renderizada' ou na resolução de 'apresentação'. A resolução 'renderizada' indica que o recurso deve corresponder à resolução na qual o aplicativo está executando sua renderização. Por outro lado, 'apresentação' indica que a resolução do alvo deve corresponder àquela que será apresentada ao usuário. Todos os recursos são do quadro renderizado atual, para aplicativos DirectX(R)12 e Vulkan(R) todos os recursos de entrada devem ser transferidos para
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
eVK_ACCESS_SHADER_READ_BIT
respectivamente antes de chamarffxFsr2ContextDispatch
.
Nome | Resolução | Formatar | Tipo | Notas |
---|---|---|---|---|
Buffer de cores | Renderizar | APPLICATION SPECIFIED | Textura | O buffer de cores de resolução de renderização para o quadro atual fornecido pelo aplicativo. Se o conteúdo do buffer de cores estiver em HDR (alta faixa dinâmica), o sinalizador FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE deverá ser definido no campo flags da estrutura FfxFsr2ContextDescription . |
Buffer de profundidade | Renderizar | APPLICATION SPECIFIED (1x FLOAT) | Textura | O buffer de profundidade de resolução de renderização para o quadro atual fornecido pelo aplicativo. Os dados devem ser fornecidos como um único valor de ponto flutuante, cuja precisão está sob o controle do aplicativo. A configuração da profundidade deve ser comunicada ao FSR2 através do campo flags da estrutura FfxFsr2ContextDescription ao criar o FfxFsr2Context . Você deve definir o sinalizador FFX_FSR2_ENABLE_DEPTH_INVERTED se seu buffer de profundidade estiver invertido (ou seja, intervalo [1..0]) e deverá definir o sinalizador FFX_FSR2_ENABLE_DEPTH_INFINITE se seu buffer de profundidade tiver um plano distante infinito. Se o aplicativo fornecer o buffer de profundidade no formato D32S8 , o FSR2 ignorará o componente estêncil do buffer e criará um recurso R32_FLOAT para endereçar o buffer de profundidade. No hardware GCN e RDNA, os buffers de profundidade são armazenados separadamente dos buffers de estêncil. |
Vetores de movimento | Renderização ou apresentação | APPLICATION SPECIFIED (2x FLOAT) | Textura | Os vetores de movimento 2D para o quadro atual fornecidos pelo aplicativo no intervalo [ (<-width, -height> .. <width, height> ]. Se seu aplicativo renderizar vetores de movimento com um intervalo diferente, você pode usar o campo motionVectorScale de a estrutura FfxFsr2DispatchDescription para ajustá-los para corresponder ao intervalo esperado para FSR2 Internamente, o FSR2 usa quantidades de 16 bits para representar vetores de movimento em muitos casos, o que significa que embora vetores de movimento com maior precisão possam ser fornecidos, FSR2 não se beneficiará do aumento de precisão. A resolução do buffer de vetor de movimento deve ser igual à resolução de renderização, a menos que o sinalizador FFX_FSR2_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS seja definido no campo flags do FfxFsr2ContextDescription estrutura ao criar o FfxFsr2Context , caso em que deverá ser igual à resolução da apresentação. |
Máscara reativa | Renderizar | R8_UNORM | Textura | Como algumas áreas de uma imagem renderizada não deixam pegada no buffer de profundidade ou incluem vetores de movimento, o FSR2 fornece suporte para uma textura de máscara reativa que pode ser usada para indicar ao FSR2 onde estão essas áreas. Bons exemplos disso são partículas ou objetos com mistura alfa que não escrevem vetores de profundidade ou movimento. Se este recurso não estiver definido, então a lógica de detecção de alterações de sombreamento do FSR2 tratará esses casos da melhor maneira possível, mas para obter resultados ideais, este recurso deverá ser definido. Para obter mais informações sobre a máscara reativa, consulte a seção Máscara reativa. |
Exposição | 1x1 | R32_FLOAT | Textura | Uma textura 1x1 contendo o valor de exposição calculado para o quadro atual. Este recurso é opcional e pode ser omitido se o sinalizador FFX_FSR2_ENABLE_AUTO_EXPOSURE estiver definido no campo flags da estrutura FfxFsr2ContextDescription ao criar o FfxFsr2Context . |
Todas as entradas fornecidas na resolução de renderização, exceto vetores de movimento, devem ser renderizadas com jitter. Os vetores de movimento não devem ter jitter aplicado, a menos que o sinalizador FFX_FSR2_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION
esteja presente.
É altamente recomendável que um buffer de profundidade infinita invertido seja usado com o FSR2. No entanto, são suportadas configurações alternativas de buffer de profundidade. Um aplicativo deve informar a API FSR2 sobre sua configuração de buffer de profundidade definindo os sinalizadores apropriados durante a criação do FfxFsr2Context
. A tabela abaixo contém os sinalizadores apropriados.
Bandeira FSR2 | Observação |
---|---|
FFX_FSR2_ENABLE_DEPTH_INVERTED | Um bit indicando que os dados do buffer de profundidade de entrada fornecidos estão invertidos [max..0]. |
FFX_FSR2_ENABLE_DEPTH_INFINITE | Um bit que indica que os dados do buffer de profundidade de entrada fornecidos estão usando um plano distante infinito. |
Uma parte fundamental de um algoritmo temporal (seja antialiasing ou upscaling) é o fornecimento de vetores de movimento. FSR2 aceita vetores de movimento em 2D que codificam o movimento de um pixel no quadro atual até a posição desse mesmo pixel no quadro anterior. FSR2 espera que os vetores de movimento sejam fornecidos pelo aplicativo no intervalo [ <-width, -height> .. <width, height> ]; isso corresponde ao espaço da tela. Por exemplo, um vetor de movimento para um pixel no canto superior esquerdo da tela com um valor de <largura, altura> representaria um movimento que atravessasse toda a largura e altura das superfícies de entrada, originando-se do canto inferior direito .
Se seu aplicativo calcular vetores de movimento em outro espaço - por exemplo, espaço de coordenadas de dispositivo normalizado - você poderá usar o campo motionVectorScale
da estrutura FfxFsr2DispatchDescription
para instruir o FSR2 a ajustá-los para corresponder ao intervalo esperado para FSR2. Os exemplos de código abaixo ilustram como os vetores de movimento podem ser dimensionados para o espaço da tela. O exemplo de código HLSL e C++ abaixo ilustra como os vetores de movimento do espaço NDC podem ser dimensionados usando a API do host FSR2.
// GPU: Example of application NDC motion vector computation
float2 motionVector = (previousPosition.xy / previousPosition.w) - (currentPosition.xy / currentPosition.w);
// CPU: Matching FSR 2.0 motionVectorScale configuration
dispatchParameters.motionVectorScale.x = ( float )renderWidth;
dispatchParameters.motionVectorScale.y = ( float )renderHeight;
Internamente, o FSR2 usa quantidades de 16 bits para representar vetores de movimento em muitos casos, o que significa que, embora vetores de movimento com maior precisão possam ser fornecidos, o FSR2 atualmente não se beneficiará do aumento da precisão. A resolução do buffer de vetor de movimento deve ser igual à resolução de renderização, a menos que o sinalizador FFX_FSR2_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS
seja definido no campo flags
da estrutura FfxFsr2ContextDescription
ao criar o FfxFsr2Context
, caso em que deve ser igual à resolução da apresentação.
O FSR2 realizará um upscaling de melhor qualidade quando mais objetos fornecerem seus vetores de movimento. Portanto, é aconselhável que todos os objetos opacos, testados alfa e mesclados alfa escrevam seus vetores de movimento para todos os pixels cobertos. Se efeitos de sombreamento de vértice forem aplicados - como UVs de rolagem - esses cálculos também deverão ser levados em consideração no cálculo do movimento para obter os melhores resultados. Para objetos com combinação alfa, também é altamente recomendável que o valor alfa de cada pixel coberto seja armazenado no pixel correspondente na máscara reativa. Isso permitirá que o FSR2 execute um melhor manuseio de objetos combinados alfa durante o upscaling. A máscara reativa é especialmente importante para objetos com combinação alfa, onde escrever vetores de movimento pode ser proibitivo, como partículas.
No contexto do FSR2, o termo "reatividade" significa quanta influência as amostras renderizadas para o quadro atual têm sobre a produção da imagem final ampliada. Normalmente, as amostras renderizadas para o quadro atual contribuem com uma quantidade relativamente modesta para o resultado calculado pelo FSR2; no entanto, existem exceções. Para produzir os melhores resultados para objetos com mistura alfa e movimento rápido, o FSR2 exige que o estágio Reprojetar e acumular se torne mais reativo para esses pixels. Como não há uma boa maneira de determinar, a partir de vetores de cor, profundidade ou movimento, quais pixels foram renderizados usando a combinação alfa, o FSR2 tem melhor desempenho quando os aplicativos marcam explicitamente essas áreas.
Portanto, é fortemente encorajado que os aplicativos forneçam uma máscara reativa ao FSR2. A máscara reativa orienta o FSR2 sobre onde ele deve reduzir sua dependência de informações históricas ao compor o pixel atual e, em vez disso, permite que as amostras do quadro atual contribuam mais para o resultado final. A máscara reativa permite que o aplicativo forneça um valor de [0.0..1.0], onde 0,0 indica que o pixel não é totalmente reativo (e deve usar a estratégia de composição FSR2 padrão) e um valor de 1,0 indica que o pixel deve ser totalmente reativo. reativo. Esta é uma faixa de ponto flutuante e pode ser adaptada para diferentes situações.
Embora existam outras aplicações para a máscara reativa, a principal aplicação da máscara reativa é produzir melhores resultados de aumento de escala de imagens que incluem objetos com mistura alfa. Um bom proxy para reatividade é, na verdade, o valor alfa usado ao compor um objeto mesclado com alfa na cena; portanto, os aplicativos devem gravar alpha
na máscara reativa. Deve-se notar que é improvável que um valor reativo próximo de 1 produza bons resultados. Portanto, recomendamos fixar o valor reativo máximo em cerca de 0,9.
Se uma máscara reativa não for fornecida para FSR2 (definindo o campo reactive
de FfxFsr2DispatchDescription
como NULL
), uma textura 1x1 gerada internamente com um valor reativo limpo será usada.
Para ajudar os aplicativos a gerar a máscara reativa e a máscara de transparência e composição, o FSR2 fornece uma API auxiliar opcional. Nos bastidores, a API lança um sombreador de computação que calcula esses valores para cada pixel usando uma heurística baseada em luminância.
Os aplicativos que desejam fazer isso podem chamar a função ffxFsr2ContextGenerateReactiveMask
e devem passar duas versões do buffer de cores, uma contendo apenas geometria opaca e a outra contendo objetos opacos e mesclados alfa.
Além da máscara reativa, o FSR2 permite que o aplicativo indique áreas de outras renderizações especializadas que devem ser consideradas durante o processo de aumento de escala. Exemplos dessa renderização especial incluem áreas de reflexos traçados por raios ou texturas animadas.
Enquanto a máscara Reativa ajusta o equilíbrio de acumulação, a máscara Transparência e composição ajusta os mecanismos de proteção do histórico de pixels. A máscara também remove o efeito do fator de instabilidade de luminância. Um pixel com valor 0 na máscara Transparência e composição não executa nenhuma modificação adicional no bloqueio desse pixel. Por outro lado, um valor 1 indica que o bloqueio desse pixel deve ser completamente removido.
Se uma máscara de Transparência e composição não for fornecida ao FSR2 (definindo o campo transparencyAndComposition
de FfxFsr2DispatchDescription
como NULL
), uma textura 1x1 gerada internamente com um valor de transparência e composição limpos será usada.
FSR2.2 inclui um recurso experimental para gerar máscara reativa e máscara de transparência e composição automaticamente. Para habilitar isso, o campo enableAutoReactive
de FfxFsr2DispatchDescription
precisa ser definido como 'TRUE' e uma cópia apenas das partes opacas do backbuffer precisa ser fornecida em 'colorOpaqueOnly'. O FSR2 gerará e usará automaticamente a máscara reativa e a máscara de transparência e composição internamente. As máscaras são geradas em uma passagem computacional analisando a diferença do buffer de cores com e sem geometria transparente, bem como comparando-o com o quadro anterior. Com base no resultado desses cálculos, cada pixel recebe valores de máscara reativa e máscara de transparência e composição. Para usar a geração automática das máscaras, os seguintes 4 valores para dimensionar e limitar a intensidade das máscaras também devem ser fornecidos (observe que os valores padrão mencionados são valores iniciais sugeridos, mas devem ser ajustados por título):
Este recurso tem como objetivo ajudar na integração do FSR2.2 em um novo mecanismo ou título. No entanto, para obter a melhor qualidade, ainda recomendamos renderizar você mesmo a máscara reativa e a máscara de transparência e composição, pois espera-se que gerar esses valores com base no material seja mais confiável do que gerá-los automaticamente a partir da imagem final.
Observe que esse recurso ainda está em fase experimental e pode mudar significativamente no futuro.
FSR2 fornece dois valores que controlam a exposição usada ao realizar o upscaling. Eles são os seguintes:
O valor de exposição deve corresponder ao que o aplicativo usa durante quaisquer passagens subsequentes de mapeamento de tons realizadas pelo aplicativo. Isso significa que o FSR2 operará de forma consistente com o que provavelmente será visível na imagem final do mapeamento de tons.
Em vários estágios do algoritmo FSR2 descrito neste documento, o FSR2 calculará seu próprio valor de exposição para uso interno. Vale a pena notar que todas as saídas do FSR2 terão esse mapeamento de tons interno invertido antes da saída final ser gravada. O que significa que o FSR2 retorna resultados no mesmo domínio do sinal de entrada original.
Valores de exposição mal selecionados podem ter um impacto drástico na qualidade final do upscaling do FSR2. Portanto, é recomendado que FFX_FSR2_ENABLE_AUTO_EXPOSURE
seja usado pelo aplicativo, a menos que haja um motivo específico para não fazê-lo. Quando FFX_FSR2_ENABLE_AUTO_EXPOSURE
é definido no campo flags
da estrutura FfxFsr2ContextDescription
, o cálculo de exposição mostrado no código HLSL abaixo é usado para calcular o valor de exposição, que corresponde à resposta de exposição do filme ISO 100.
float ComputeAutoExposureFromAverageLog ( float averageLogLuminance)
{
const float averageLuminance = exp (averageLogLuminance);
const float S = 100.0f ; // ISO arithmetic speed
const float K = 12.5f ;
const float exposureIso100 = log2 ((averageLuminance * S) / K);
const float q = 0.65f ;
const float luminanceMax = ( 78.0f / (q * S)) * pow ( 2.0f , exposureIso100);
return 1 / luminanceMax;
}
O objetivo principal do FSR2 é melhorar o desempenho de renderização de aplicativos usando um algoritmo de aumento de escala temporal que depende de uma série de entradas. Portanto, sua colocação no pipeline é fundamental para garantir o equilíbrio certo entre a mais alta qualidade visual e ótimo desempenho.
Com qualquer abordagem de aumento de escala de imagem, é importante entender como colocar outros algoritmos de espaço de imagem em relação ao algoritmo de aumento de escala. Colocar esses outros efeitos de espaço de imagem antes do upscaling tem a vantagem de serem executados em uma resolução mais baixa, o que obviamente confere uma vantagem de desempenho ao aplicativo. No entanto, pode não ser apropriado para algumas classes de técnicas de espaço de imagem. Por exemplo, muitas aplicações podem introduzir ruído ou granulação na imagem final, talvez para simular uma câmera física. Fazer isso antes de um upscaler pode fazer com que o upscaler amplifique o ruído, causando artefatos indesejáveis na imagem ampliada resultante. A tabela a seguir divide técnicas comuns de espaço de imagem em tempo real em duas colunas. 'Pós-processamento A' contém todas as técnicas que normalmente seriam executadas antes do upscaling do FSR2, o que significa que todas elas seriam executadas na resolução de renderização. Por outro lado, a coluna 'Pós-processamento B' contém todas as técnicas recomendadas para execução após o FSR2, o que significa que seriam executadas em uma resolução de apresentação maior.
Pós-processamento A | Pós-processamento B |
---|---|
Reflexões do espaço de tela | Grão de filme |
Oclusão ambiental do espaço de tela | Aberração cromática |
Denoisers (sombra, reflexos) | Vinheta |
Exposição (opcional) | Mapeamento de tons |
Florescer | |
Profundidade de campo | |
Desfoque de movimento |
Observe que as recomendações aqui são apenas para orientação e dependem das características precisas da implementação do seu aplicativo.
Embora seja possível gerar os recursos intermediários apropriados, compilar o código do shader, definir as ligações e enviar os despachos, é muito mais fácil usar a API do host FSR2 que é fornecida.
Para usar a API, você deve vincular as bibliotecas FSR2 (mais sobre quais em breve) e incluir o arquivo de cabeçalho ffx_fsr2.h
, que por sua vez possui as seguintes dependências de cabeçalho:
ffx_assert.h
ffx_error.h
ffx_fsr2_interface.h
ffx_types.h
ffx_util.h
Para usar a API FSR2, você deve vincular ffx_fsr2_api_x64.lib
que fornecerá os símbolos para as APIs voltadas para o aplicativo. No entanto, a API do FSR2 possui um backend modular, o que significa que diferentes APIs gráficas e plataformas podem ser direcionadas através do uso de um backend correspondente. Portanto, você deve incluir ainda a biblioteca de back-end que atende aos seus requisitos, referenciando a tabela abaixo.
Alvo | Nome da biblioteca |
---|---|
DirectX(R)12 | ffx_fsr2_dx12_x64.lib |
Vulkan(R) | ffx_fsr2_vk_x64.lib |
Observe que a arquitetura modular da API FSR2 permite a implementação de back-ends personalizados. Consulte a seção Back-end modular para obter mais detalhes.
Para começar a usar a API, o aplicativo deve primeiro criar uma estrutura FfxFsr2Context
. Essa estrutura deve estar localizada em algum lugar com uma vida útil aproximadamente igual à do seu backbuffer; em algum lugar na pilha do aplicativo geralmente é uma boa escolha. Ao chamar ffxFsr2ContextCreate
a estrutura FfxFsr2Context
será preenchida com os dados necessários. Além disso, várias chamadas serão feitas de ffxFsr2ContextCreate
para o backend que é fornecido ao FfxFsr2Context
como parte da estrutura FfxFsr2ContextDescription
. Essas chamadas executarão tarefas como a criação de recursos intermediários exigidos pelo FSR2 e a configuração de shaders e seu estado de pipeline associado. A API FSR2 não executa nenhuma alocação dinâmica de memória.
Cada quadro do seu aplicativo onde o upscaling é necessário, você deve chamar ffxFsr2ContextDispatch
. Esta função aceita a estrutura FfxFsr2Context
que foi criada anteriormente no tempo de vida do aplicativo, bem como uma descrição de como o upscaling deve ser executado com precisão e em quais dados. Essa descrição é fornecida pelo aplicativo preenchendo uma estrutura FfxFsr2DispatchDescription
.
A destruição do contexto é realizada chamando ffxFsr2ContextDestroy
. Observe que a GPU deve estar ociosa antes de tentar chamar ffxFsr2ContextDestroy
e a função não executa sincronização implícita para garantir que os recursos acessados pelo FSR2 não estejam atualmente em execução. A razão para esta escolha é evitar que o FSR2 introduza liberações de GPU adicionais para aplicativos que já executam sincronização adequada no ponto em que desejam destruir o FfxFsr2Context
, isso permite que um aplicativo execute a criação e desmontagem mais eficiente possível da API FSR2 quando obrigatório.
Existem funções auxiliares adicionais que são fornecidas como parte da API FSR2. Essas funções auxiliares executam tarefas como o cálculo de compensações de jitter de subpixel, bem como o cálculo de resoluções de renderização com base nas resoluções de despacho e nos modos de escala padrão fornecidos pelo FSR2.
Para obter uma documentação mais completa da API FSR2, consulte a documentação de referência da API fornecida.
O design da API FSR2 significa que a implementação principal do algoritmo FSR2 não tem conhecimento de qual API de renderização está baseada. Em vez disso, o FSR2 chama funções fornecidas a ele por meio de uma interface, permitindo que diferentes back-ends sejam usados com o FSR2. Este design também permite que aplicativos que integram o FSR2 forneçam sua própria implementação de back-end, o que significa que plataformas que o FSR2 não suporta atualmente podem ser alvo da implementação de um punhado de funções. Além disso, os aplicativos que possuem suas próprias abstrações de renderização também podem implementar seu próprio back-end, assumindo o controle de todos os aspectos da função subjacente do FSR2, incluindo gerenciamento de memória, criação de recursos, compilação de shader, vinculações de recursos de shader e envio de cargas de trabalho do FSR2 ao dispositivo gráfico. .
Pronto para uso, a API FSR2 será compilada em várias bibliotecas seguindo a separação já delineada entre a API principal e os back-ends. Isso significa que se você deseja usar os back-ends fornecidos com o FSR2, você deve vincular a biblioteca principal da API do FSR2, bem como o back-end que atende aos seus requisitos.
O lançamento público do FSR2 vem com backends DirectX(R)12 e Vulkan(R), mas outros backends estão disponíveis mediante solicitação. Fale com seu representante da AMD Developer Technology para obter mais informações.
Se a API FSR2 for usada com um dos backends fornecidos (por exemplo: DirectX(R)12 ou Vulkan(R)), então todos os recursos exigidos pelo FSR2 serão criados como recursos comprometidos diretamente usando o dispositivo gráfico fornecido pelo aplicativo host. No entanto, ao substituir a família de funções de criação e destruição presente na interface backend, é possível que uma aplicação controle com mais precisão o gerenciamento de memória do FSR2.
Para fazer isso, você pode fornecer um back-end personalizado completo para FSR2 por meio da estrutura FfxFsr2ContextDescription
passada para a função ffxFsr2ContextCreate
ou pode recuperar o back-end da API desejada e substituir as funções de criação e destruição de recursos para lidar com eles você mesmo. Para fazer isso, basta substituir os ponteiros de função fpCreateResource
e fpDestroyResource
.
// Setup DX12 interface.
const size_t scratchBufferSize = ffxFsr2GetScratchMemorySizeDX12();
void * scratchBuffer = malloc(scratchBufferSize);
FfxErrorCode errorCode = ffxFsr2GetInterfaceDX12(&contextDescription.callbacks, m_pDevice-> GetDevice (), scratchBuffer, scratchBufferSize);
FFX_ASSERT (errorCode == FFX_OK);
// Override the resource creation and destruction.
contextDescription.callbacks.createResource = myCreateResource;
contextDescription.callbacks.destroyResource = myDestroyResource;
// Set up the context description.
contextDescription.device = ffxGetDeviceDX12(m_pDevice-> GetDevice ());
contextDescription.maxRenderSize.width = renderWidth;
contextDescription.maxRenderSize.height = renderHeight;
contextDescription.displaySize.width = displayWidth;
contextDescription.displaySize.height = displayHeight;
contextDescription.flags = FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE
| FFX_FSR2_ENABLE_DEPTH_INVERTED
| FFX_FSR2_ENABLE_AUTO_EXPOSURE;
// Create the FSR2 context.
errorCode = ffxFsr2ContextCreate(&context, &contextDescription);
FFX_ASSERT (errorCode == FFX_OK);
Uma vantagem interessante para um aplicativo que assume o controle do gerenciamento de memória necessário para FSR2 é que o alias de recursos pode ser executado, o que pode gerar economia de memória. A tabela presente em Requisitos de memória demonstra as economias disponíveis com o uso desta técnica. Para realizar as economias mostradas nesta tabela, uma área apropriada de memória - cujo conteúdo não é necessário para sobreviver durante uma chamada para os despachos FSR2 - deve ser encontrada para compartilhar com os recursos alias necessários para FSR2. Cada chamada FfxFsr2CreateResourceFunc
feita pela API principal do FSR2 por meio da interface de back-end do FSR2 conterá um conjunto de sinalizadores como parte da estrutura FfxCreateResourceDescription
. Se FFX_RESOURCE_FLAGS_ALIASABLE
estiver definido no campo flags
, isso indica que o recurso pode ter um alias seguro com outros recursos no quadro de renderização.
Antialiasing temporal (TAA) é uma técnica que usa a saída de quadros anteriores para construir uma saída de qualidade superior a partir do quadro atual. Como o FSR2 tem um objetivo semelhante - embora com o objetivo adicional de também aumentar a resolução da imagem renderizada - não há mais necessidade de incluir uma passagem TAA separada em sua aplicação.
FSR2 depende do aplicativo para aplicar tremulação de subpixel durante a renderização - isso normalmente é incluído na matriz de projeção da câmera. Para simplificar a aplicação do jitter da câmera, a API FSR2 fornece um pequeno conjunto de funções utilitárias que calcula o deslocamento do jitter subpixel para um quadro específico dentro de uma sequência de deslocamentos de jitter separados.
int32_t ffxFsr2GetJitterPhaseCount ( int32_t renderWidth, int32_t displayWidth);
FfxErrorCode ffxFsr2GetJitterOffset ( float * outX, float * outY, int32_t jitterPhase, int32_t sequenceLength);
Internamente, essas funções implementam uma sequência Halton[2,3] [Halton]. O objetivo da sequência de Halton é fornecer pontos separados espacialmente, que cubram o espaço disponível.
É importante entender que os valores retornados de ffxFsr2GetJitterOffset
estão no espaço unitário de pixels e, para compor isso corretamente em uma matriz de projeção, devemos convertê-los em deslocamentos de projeção. O diagrama acima mostra um único pixel no espaço de pixels unitários e no espaço de projeção. A listagem de código abaixo mostra como compor corretamente o valor de deslocamento de jitter de subpixel em uma matriz de projeção.
const int32_t jitterPhaseCount = ffxFsr2GetJitterPhaseCount(renderWidth, displayWidth);
float jitterX = 0 ;
float jitterY = 0 ;
ffxFsr2GetJitterOffset (&jitterX, &jitterY, index, jitterPhaseCount);
// Calculate the jittered projection matrix.
const float jitterX = 2 . 0f * jitterX / ( float )renderWidth;
const float jitterY = - 2 . 0f * jitterY / ( float )renderHeight;
const Matrix4 jitterTranslationMatrix = translateMatrix(Matrix3::identity, Vector3(jitterX, jitterY, 0 ));
const Matrix4 jitteredProjectionMatrix = jitterTranslationMatrix * projectionMatrix;
O jitter deve ser aplicado a todas as renderizações. Isso inclui objetos opacos, alfa transparentes e com traçado de raio. Para objetos rasterizados, os valores de tremulação de subpixel calculados pela função ffxFsr2GetJitterOffset
podem ser aplicados à matriz de projeção da câmera que é usada em última análise para realizar transformações durante o sombreamento de vértice. Para renderização com traçado de raio, o jitter subpixel deve ser aplicado à origem do raio - geralmente a posição da câmera.
Se você optar por usar a função ffxFsr2GetJitterOffset
recomendada ou seu próprio gerador de sequência, você deve definir o campo jitterOffset
da estrutura FfxFsr2DispatchDescription
para informar o FSR2 do deslocamento do jitter que foi aplicado para renderizar cada quadro. Além disso, se não estiver usando a função Recomendada ffxFsr2GetJitterOffset
, deve -se tomar cuidado de que sua sequência de jitter nunca gera um vetor nulo; Isso é valor de 0 nas dimensões x e y.
A tabela abaixo mostra o comprimento da sequência do jitter para cada um dos modos de qualidade padrão.
Modo de qualidade | Fator de escala | Comprimento da sequência |
---|---|---|
Qualidade | 1.5x (por dimensão) | 18 |
Equilibrado | 1.7x (por dimensão) | 23 |
Desempenho | 2.0x (por dimensão) | 32 |
Ultra Performance | 3.0x (por dimensão) | 72 |
Personalizado | [1..n] x (por dimensão) | ceil(8 * n^2) |
A maioria das aplicações com renderização em tempo real possui um grande grau de consistência temporal entre dois quadros consecutivos. No entanto, há casos em que uma alteração na transformação de uma câmera pode causar uma mudança abrupta no que é renderizado. Nesses casos, é improvável que o FSR2 seja capaz de reutilizar os dados acumulados a partir de quadros anteriores e deve limpar esses dados como excluí -los da consideração no processo de composição. Para indicar ao FSR2 que ocorreu um corte de salto com a câmera, você deve definir o campo reset
da estrutura FfxFsr2DispatchDescription
como true
para o primeiro quadro da transformação descontínua da câmera.
A renderização do desempenho pode ser um pouco menor que a operação típica de quadro a quadro ao usar o sinalizador de redefinição, pois o FSR2 limpará alguns recursos internos adicionais.
A aplicação de um viés de MIPMap negativo normalmente gera uma imagem upcaled com melhores detalhes de textura. Recomendamos aplicar a seguinte fórmula ao seu viés do MIPMAP:
mipBias = log2(renderResolution/displayResolution) - 1.0 ;
Sugere-se que os aplicativos ajustem o viés do MIP para conteúdo específico de textura de alta frequência, que é suscetível a mostrar problemas de alias temporal.
A tabela a seguir ilustra o fator de polarização do MIPMAP que resulta da avaliação do pseudocódigo acima para as taxas de escala que correspondem aos modos de qualidade sugeridos que os aplicativos devem expor aos usuários finais.
Modo de qualidade | Fator de escala | Viés MipMap |
---|---|---|
Qualidade | 1.5x (por dimensão) | -1,58 |
Equilibrado | 1.7x (por dimensão) | -1,76 |
Desempenho | 2.0x (por dimensão) | -2,0 |
Ultra Performance | 3.0x (por dimensão) | -2,58 |
A API FSR2 exige que frameTimeDelta
seja fornecido pelo aplicativo através da estrutura FfxFsr2DispatchDescription
. Esse valor está em milissegundos : se estiver em execução a 60fps, o valor aprovado deve estar em torno de 16,6f .
O valor é usado dentro do componente temporal do recurso de exposição automática FSR 2. Isso permite o ajuste do acúmulo de história para fins de qualidade.
As imagens de alta faixa dinâmica são suportadas no FSR2. Para ativar isso, você deve definir o bit FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE
no campo flags
da estrutura FfxFsr2ContextDescription
. As imagens devem ser fornecidas ao FSR2 no espaço de cores lineares.
O suporte a espaços de cores adicionais pode ser fornecido em uma revisão futura do FSR2.
O FSR2 foi projetado para aproveitar a aceleração de hardware de meia precisão (FP16) para obter o maior desempenho possível. No entanto, para fornecer o nível máximo de compatibilidade e flexibilidade para aplicações, o FSR2 também inclui a capacidade de compilar os shaders usando operações de precisão total (FP32).
Recomenda -se usar a versão FP16 do FSR2 em todo o hardware que o suporta. Você pode consultar o nível de suporte da sua placa gráfica para FP16, consultando o Capabilidade D3D12_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT
em DirectX (R) 12 - você deve verificar se o D3D[11/12]_SHADER_MIN_PRECISION_16_BIT
, e o FretTen _Slback _Minback _MBATBELT_MBATELT_BPOTEM2 _MABLATEM2. FSR2. Para Vulkan, se VkPhysicalDeviceFloat16Int8FeaturesKHR::shaderFloat16
não estiver definido, você deve fallback para a versão FP32 do FSR2. Da mesma forma, se VkPhysicalDevice16BitStorageFeatures::storageBuffer16BitAccess
não estiver definido, você também deve falar na versão FP32 do FSR2.
Para ativar o caminho FP32 no código -fonte do shader FSR2, você deve definir FFX_HALF
como 1
. Para compartilhar a maioria do código -fonte do algoritmo entre FP16 e FP32 (garantindo um alto nível de compartilhamento de código para suportar a manutenção contínua), você notará que o código -fonte do shader FSR2 usa um conjunto de macros do tipo que facilitará a alternância entre a alternância entre Tipos de base de 16 bits e 32 bits na fonte do shader.
Tipo fidelityfx | Fp32 | FP16 |
---|---|---|
FFX_MIN16_F | float | min16float |
FFX_MIN16_F2 | float2 | min16float2 |
FFX_MIN16_F3 | float3 | min16float3 |
FFX_MIN16_F4 | float4 | min16float4 |
A tabela acima enumera os mapeamentos entre os tipos abstratos de fidelityfx sdk e o tipo intrínseco subjacente que será substituído, dependendo da configuração da fonte do shader durante a compilação.
As GPUs modernas executam coleções de threads - chamados de frente de onda - juntos de maneira simt. O número preciso de encadeamentos que constituem uma única frente de onda é uma quantidade específica de hardware. Alguns hardware, como o GCN da AMD e o GPUs baseados em RDNA, suportam a coleta de 64 threads em uma única frente de onda. Dependendo das características precisas da execução de um algoritmo, pode ser mais ou menos vantajoso preferir uma largura específica da frente de onda. Com a introdução do Shader Model 6.6, a Microsoft adicionou a capacidade de especificar a largura de uma frente de onda via HLSL. Para o hardware, como o rDNA, que suporta larguras de frente para ondas de 32 e 64 largos, essa é uma ferramenta muito útil para fins de otimização, pois fornece uma maneira limpa e portátil de pedir à pilha de software do driver para executar uma frente de onda com uma largura específica.
Para aplicativos baseados em DirectX (R) 12 que estão em execução nas GPUs baseadas em rDNA e rDNA2 e usando o Microsoft Agility SDK, a API do host FSR2 selecionará uma largura de frente para 64 de largura.
A estrutura de descrição do contexto pode ser fornecida com uma função de retorno de chamada para transmitir avisos de texto do tempo de execução do FSR 2 para o aplicativo subjacente. O membro fpMessage
da descrição é do tipo FfxFsr2Message
, que é um ponteiro de função para passar mensagens de string de vários tipos. Atribuir essa variável a uma função adequada e passar o sinalizador FFX_FSR2_ENABLE_DEBUG_CHECKING
dentro do membro Flags do FfxFsr2ContextDescription
ativará o recurso. Recomenda -se que isso seja ativado apenas no Debug Development Builds.
Um exemplo do tipo de saída que pode ocorrer quando o verificador observa possíveis problemas está abaixo:
FSR2_API_DEBUG_WARNING: FFX_FSR2_ENABLE_DEPTH_INFINITE and FFX_FSR2_ENABLE_DEPTH_INVERTED present, cameraFar value is very low which may result in depth separation artefacting
FSR2_API_DEBUG_WARNING: frameTimeDelta is less than 1.0f - this value should be milliseconds (~16.6f for 60fps)
O algoritmo FSR2 é implementado em uma série de estágios, que são os seguintes:
Cada estágio de passagem do algoritmo é apresentado nas seções seguintes, mas o fluxo de dados para o algoritmo FSR2 completo é mostrado no diagrama abaixo.
O estágio da pirâmide de luminância de computação tem duas responsabilidades:
A tabela a seguir contém todos os recursos consumidos pelo estágio de pirâmide de luminância de computação.
A camada temporal indica de qual quadro os dados devem ser adquiridos. 'Quadro atual' significa que os dados devem ser provenientes de recursos criados para o quadro a ser apresentado a seguir. O 'quadro anterior' indica que os dados devem ser provenientes de recursos criados para o quadro que acaba de apresentar. A coluna de resolução indica se os dados devem estar em resolução 'renderizada' ou 'apresentação'. A resolução 'renderizada' indica que o recurso deve corresponder à resolução na qual o aplicativo está executando sua renderização. Por outro lado, a 'apresentação' indica que a resolução do alvo deve corresponder à que deve ser apresentada ao usuário.
Nome | Camada temporal | Resolução | Formatar | Tipo | Notas |
---|---|---|---|---|---|
Buffer de cor | Quadro atual | Renderizar | APPLICATION SPECIFIED | Textura | O buffer de cor de resolução de renderização para o quadro atual fornecido pelo aplicativo. Se o conteúdo do buffer de cores estiver em alta faixa dinâmica (HDR), o sinalizador FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE deverá ser definido no campo flags da estrutura FfxFsr2ContextDescription . |
A tabela a seguir contém todos os recursos produzidos ou modificados pelo estágio da pirâmide de luminância de computação.
A camada temporal indica de qual quadro os dados devem ser adquiridos. 'Quadro atual' significa que os dados devem ser provenientes de recursos criados para o quadro a ser apresentado a seguir. O 'quadro anterior' indica que os dados devem ser provenientes de recursos criados para o quadro que acaba de apresentar. A coluna de resolução indica se os dados devem estar em resolução 'renderizada' ou 'apresentação'. A resolução 'renderizada' indica que o recurso deve corresponder à resolução na qual o aplicativo está executando sua renderização. Por outro lado, a 'apresentação' indica que a resolução do alvo deve corresponder à que deve ser apresentada ao usuário.
Nome | Camada temporal | Resolução | Formatar | Tipo | Notas |
---|---|---|---|---|---|
Exposição | Quadro atual | 1x1 | R32_FLOAT | Textura | Uma textura 1x1 contendo o valor de exposição calculado para o quadro atual. Esse recurso é opcional e pode ser omitido se o sinalizador FFX_FSR2_ENABLE_AUTO_EXPOSURE estiver definido no campo flags da estrutura FfxFsr2ContextDescription ao criar o FfxFsr2Context . |
Luminância atual | Quadro atual | Render * 0.5 + mipchain | R16_FLOAT | Textura | Uma textura a 50% da textura de resolução de renderização que contém a luminância do quadro atual. Uma cadeia MIP completa é alocada. |
O estágio de pirâmide de luminância de computação é implementado usando fidelityfx single passa downs