Visão geral dos heaps de descritores
Os heaps de descritor contêm muitos tipos de objeto que não fazem parte de um Objeto de Estado de Pipeline (PSO), como SRVs (Exibições de Recurso de Sombreador), UAVs (Exibições de Acesso Não Ordenado), CBVs (Exibições de Buffer Constante) e Samplers.
- A finalidade dos heaps de descritor
- Sincronização
- Associação
- Alternar heaps
- Pacotes
- Gerenciamento
- Tópicos relacionados
A finalidade dos heaps de descritor
A principal finalidade 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 que os sombreadores referenciam para o maior número possível de uma janela de renderização (idealmente um quadro inteiro de renderização ou mais). Se um aplicativo estiver alternando quais texturas o pipeline vê rapidamente da API, deve haver espaço no heap do descritor para definir tabelas de descritor em tempo real para cada conjunto de estado necessário. O aplicativo poderá optar por reutilizar definições se os recursos forem usados novamente em outro objeto, por exemplo, ou apenas atribuir o espaço de heap sequencialmente à medida que alternar vários tipos de objeto.
Os heaps de descritor também permitem que componentes de software individuais gerenciem o armazenamento do descritor separadamente entre si.
Todos os heaps são visíveis para a CPU. O aplicativo também pode solicitar quais propriedades de acesso à CPU um heap de descritor deve ter (se houver) – gravação combinada, write-back e assim por diante. Os aplicativos podem criar quantos heaps de descritor desejarem com as propriedades desejadas. Os aplicativos sempre têm a opção de criar heaps de descritor que são puramente para fins de preparo que não são treinados em tamanho e copiar para heaps de descritor que são usados para renderização conforme necessário.
Há algumas restrições no que pode ir no mesmo heap de descritor. As entradas CBV, UAV e SRV podem estar no mesmo heap de descritor. No entanto, as entradas samplers não podem compartilhar um heap com entradas CBV, UAV ou SRV. Normalmente, há dois conjuntos de heaps de descritor, um para os recursos comuns e o segundo para Samplers.
O uso de heaps de descritor pelo Direct3D 12 espelha o que a maioria dos hardwares de GPU faz, que é exigir descritores que vivem apenas em heaps de descritor ou simplesmente que menos bits de endereçamento são necessários se esses heaps forem usados. O Direct3D 12 requer o uso de heaps de descritor, não há nenhuma opção para colocar descritores em qualquer lugar na memória.
Heaps de descritor só podem ser editados imediatamente pela CPU, não há nenhuma opção para editar um heap de descritor pela GPU.
Sincronização
O conteúdo do heap do descritor pode ser alterado antes, durante e após a gravação de 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 pode referenciar esse local, pois isso pode invocar uma condição de corrida.
Associação
No máximo um heap combinado CBV/SRV/UAV e um heap de Sampler podem ser associados a qualquer momento. Esses heaps são compartilhados entre os pipelines gráficos e de computação (descritos em seus PSOs).
Alternar heaps
É aceitável que um aplicativo alterne heaps na mesma lista de comandos ou em diferentes usando as APIs SetDescriptorHeaps e Reset . Em algum hardware, essa pode ser uma operação cara, exigindo uma parada de GPU para liberar todo o trabalho que depende do heap de descritor associado no momento. Como resultado, se os heaps de descritor precisarem ser alterados, os aplicativos devem tentar fazê-lo quando a carga de trabalho de GPU for relativamente leve, talvez limitando as alterações ao início de uma lista de comandos.
Pacotes
Com os pacotes, só pode haver uma chamada para o método SetDescriptorHeaps , e o conjunto de heaps do descritor deve corresponder exatamente aos da lista de comandos que chama o pacote. Se o pacote não alterar tabelas de descritor, ele não precisará definir os heaps do descritor.
Para obter uma lista de chamadas à API que não podem ser usadas com pacotes, consulte Criando e gravando listas de comandos e pacotes.
Gerenciamento
Para renderizar todos os objetos em uma cena, muitos descritores serão necessários e há algumas estratégias de gerenciamento diferentes que podem ser seguidas.
A estratégia mais básica seria preencher uma nova área do heap de descritor com todos os requisitos para a próxima chamada de desenho. Portanto, pouco antes de emitir a chamada de desenho na lista de comandos, um ponteiro de tabela de descritor seria definido como o início da tabela recém-preenchida. O lado positivo é que não é necessário registrar onde qualquer descritor específico está no heap.
A desvantagem dessa estratégia é que pode haver muita repetição de descritores no heap do descritor, especialmente quando uma cena muito semelhante está sendo renderizada, e esse espaço de heap do descritor será usado rapidamente. Heaps de descritor separados para aqueles que estão sendo renderizados na GPU e para aqueles que estão sendo registrados pela CPU, provavelmente seriam necessários para evitar conflitos. Como alternativa, um sistema de sublocação pode ser usado.
Além disso, o sistema básico pode ser otimizado com o 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 pré-preencher heaps de descritor com descritores necessários para os objetos (ou materiais) que são conhecidos por fazer parte da cena. A ideia aqui é que só é necessário definir a tabela de descritor em tempo de desenho, pois o heap do descritor é preenchido antecipadamente.
Uma variação da estratégia de pré-preenchimento é tratar o heap do descritor como uma matriz enorme, contendo todos os descritores necessários em locais conhecidos fixos. Em seguida, a chamada de desenho só precisa receber um conjunto de constantes que são os índices na matriz de onde os descritores são que precisam ser usados.
Uma otimização adicional é garantir que constantes raiz e descritores raiz contenham aqueles que mudam com mais frequência, em vez de colocar constantes no heap do descritor. Para a maioria dos hardwares, essa é uma maneira eficiente de lidar com constantes.
Na prática, um mecanismo gráfico pode usar uma estratégia diferente em situações diferentes e combinar elementos de cada estratégia para atender aos requisitos específicos de desenho.
Tópicos relacionados