Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
As pilhas de descritores contêm muitos tipos de objeto que não fazem parte de um Objeto de Estado de Pipeline (PSO), como Shader Resource Views (SRVs - Visões de Recursos de Sombras), Unordered Access Views (UAVs - Visões de Acesso Não Ordenado), Constant Buffer Views (CBVs - Visões de Buffer Constante), e Amostradores (Samplers).
- O Propósito do Descritor Heaps
- Sincronização
- Vinculação
- Comutação de pilhas
- Pacotes
- Gestão
- Tópicos relacionados
O Propósito das Pilhas Descritoras
O objetivo principal de um heap de descritor é abranger a maior parte da alocação de memória necessária para armazenar as especificações do descritor de tipos de objeto aos quais os sombreadores fazem referência, de forma a cobrir o maior período de renderização possível (idealmente, um frame inteiro de renderização ou mais). Se uma aplicação estiver mudando rapidamente quais texturas o pipeline vê a partir da API, deve haver espaço no heap de descritores (descriptor heap) para definir tabelas de descritores dinamicamente para cada conjunto de estado necessário. A aplicação pode optar por reutilizar definições se os recursos forem usados novamente em outro objeto, por exemplo, ou apenas atribuir o espaço em heap sequencialmente à medida que alterna entre vários tipos de objeto.
As pilhas de descritores também permitem que componentes de software individuais gerenciem o armazenamento do descritor separadamente uns dos outros.
Todas as pilhas são visíveis para a CPU. O aplicativo também pode solicitar quais propriedades de acesso à CPU um heap descritor deve ter (se houver) – gravação combinada, gravação de volta e assim por diante. Os aplicativos podem criar quantas pilhas de descritores desejarem com quaisquer propriedades desejadas. As aplicações têm sempre a opção de criar heaps de descritores que são puramente para fins intermediários e que não têm restrição de tamanho, podendo copiar para heaps de descritores usados para renderização conforme necessário.
Existem algumas restrições quanto ao que pode ser incluído no mesmo heap de descritores. As entradas CBV, UAV e SRV podem estar no mesmo agrupamento de descritores. No entanto, as entradas de Samplers não podem compartilhar uma pilha com as entradas CBV, UAV ou SRV. Normalmente, há dois conjuntos de heaps de descritores, um para os recursos comuns e o segundo para os amostradores.
O uso de pilhas de descritores pelo Direct3D 12 espelha o que a maioria do hardware de GPU faz, que é exigir que os descritores existam apenas em pilhas de descritores, ou simplesmente que são necessários menos bits de endereçamento se essas pilhas forem usadas. O Direct3D 12 requer o uso de pilhas de descritores, não há opção para colocar descritores em qualquer lugar na memória.
Pilhas de descritor só podem ser editadas imediatamente pela CPU, não há opção para editar uma pilha de descritor pela GPU.
Sincronização
O conteúdo da pilha do descritor pode ser alterado antes, durante e após a gravação das listas de comandos que fazem referência a ele. No entanto, os descritores não podem ser alterados enquanto uma lista de comandos enviada para execução possa referir-se a esse local, pois isso pode invocar uma condição de corrida.
Vinculação
No máximo, uma pilha combinada CBV/SRV/UAV e uma pilha Sampler podem ser ligadas a qualquer momento. Essas pilhas são compartilhadas entre os pipelines gráficos e de computação (descritos em suas OSP).
Pilhas de comutação
É aceitável que uma aplicação alterne heaps dentro da mesma lista de comandos ou em listas diferentes usando as APIs SetDescriptorHeaps e Reset. Em algum hardware, esta pode ser uma operação cara, exigindo uma interrupção da GPU para esvaziar todo o trabalho que depende do heap de descritores atualmente associado. Como resultado, se as pilhas de descritores precisarem ser alteradas, as aplicações devem tentar fazê-lo quando a carga de trabalho da GPU for relativamente leve, talvez limitando as alterações ao início de uma lista de comandos.
Pacotes
Com bundles, só pode haver uma chamada para o métodoSetDescriptorHeaps, e o conjunto de heaps do descritor deve corresponder exatamente aos da lista de comandos que chama o bundle. Se o pacote não alterar as tabelas de descritores, não será necessário definir as pilhas de descritores.
Para obter uma lista de chamadas de API que não podem ser usadas com pacotes, consulte Criando e gravando listas de comandos e pacotes.
Gestão
Para renderizar todos os objetos em uma cena, muitos descritores serão necessários, e existem algumas estratégias de gerenciamento diferentes que podem ser seguidas.
A estratégia mais básica seria preencher uma nova área da pilha do descritor com todos os requisitos para a próxima chamada de sorteio. Assim, imediatamente antes de emitir a chamada de renderização na lista de comandos, um ponteiro para a tabela de descritores seria definido para o início da tabela recém-preenchida. A vantagem é que não há necessidade de registar onde qualquer descritor em particular está na pilha.
A desvantagem desta estratégia é que pode haver muita repetição de descritores na pilha de descritores, especialmente quando uma cena muito semelhante está a ser renderizada, e esse espaço da pilha de descritores vai ser rapidamente esgotado. Pilhas de descritor separadas para aqueles que estão sendo renderizados na GPU e para aqueles que estão sendo gravados pela CPU, provavelmente seriam necessários para evitar conflitos. Em alternativa, poderia ser utilizado um sistema de subatribuição.
Além disso, o sistema básico poderia ser otimizado ainda mais pelo uso cuidadoso de tabelas de descritores sobrepostas de uma chamada de desenho para a próxima, de modo que apenas os novos descritores necessários sejam adicionados.
Uma estratégia mais eficiente do que a básica seria preencher previamente pilhas de descritores com os descritores necessários para os objetos (ou materiais) que são conhecidos como parte da cena. A ideia aqui é que só é necessário definir a tabela do descritor no momento do desenho, pois o heap do descritor é preenchido com antecedência.
Uma variação da estratégia de pré-preenchimento é tratar a pilha de descritores como uma enorme matriz, contendo todos os descritores necessários em locais fixos e conhecidos. Em seguida, a chamada de sorteio precisa apenas receber um conjunto de constantes que são os índices na matriz de onde estão os descritores que precisam ser usados.
Uma otimização adicional é garantir que as constantes de raiz e os descritores de raiz contenham aqueles que se alteram com mais frequência, em vez de colocar constantes no heap do descritor. Para a maioria do hardware, esta é uma maneira eficiente de lidar com constantes.
Na prática, um motor gráfico pode utilizar uma estratégia diferente em diferentes situações e combinar elementos de cada estratégia para se adequar aos requisitos de desenho específicos.
Tópicos relacionados