Limitações de acesso de bloco com mapeamentos duplicados
Há limitações em acesso de bloco com mapeamentos duplicados, como ao copiar recursos de streaming com origem e destino sobrepostos, ou ao renderizar para blocos compartilhados dentro da área de renderização.
Copiando recursos de streaming com origem e destino sobrepostos
Se os blocos na área de origem e destino de uma operação Copy* tiverem mapeamentos duplicados na área de cópia que teriam se sobreposto mesmo se ambos os recursos não fossem recursos de streaming e a operação Copy* der suporte a cópias sobrepostas, a operação Copy* se comportará bem (como se a origem fosse copiada para um local temporário antes de ir para o destino). Mas se a sobreposição não for óbvia (como os recursos de origem e destino são diferentes, mas os mapeamentos de compartilhamento ou mapeamentos são duplicados em uma determinada superfície), os resultados da operação de cópia nos blocos compartilhados serão indefinidos.
Copiando para o recurso de streaming com blocos duplicados na área de destino
Copiar para um recurso de streaming com blocos duplicados na área de destino produz resultados indefinidos nesses blocos, a menos que os dados em si sejam idênticos; blocos diferentes podem escrever os blocos em ordens diferentes.
Acessos UAV a mapeamentos de blocos duplicados
Suponha que uma UAV (exibição de acesso não ordenado) em um recurso de streaming tenha mapeamentos de bloco duplicados em sua área ou com outros recursos associados ao pipeline. A ordenação de acessos a esses blocos duplicados é indefinida se executada por threads diferentes, assim como qualquer ordenação de acesso à memória para UAVs em geral não é ordenada.
Renderização após alterações de mapeamento de bloco ou atualizações de conteúdo de mapeamentos externos
Se os mapeamentos de bloco de um recurso de streaming tiverem sido alterados ou o conteúdo em blocos de pool de blocos mapeados tiver sido alterado por meio dos mapeamentos de outro recurso de streaming, e o recurso de streaming for renderizado por meio da exibição de destino de renderização ou da exibição de estêncil de profundidade, o aplicativo deverá limpar (usando a função fixa Limpar APIs) ou copiar totalmente usando APIs Copy*/Update* os blocos que foram alterados dentro da área que está sendo renderizada (mapeada ou não).
A falha de um aplicativo para limpar ou copiar nesses casos resulta em estruturas de otimização de hardware para a exibição de destino de renderização ou exibição de estêncil de profundidade fornecidas e resultará em resultados de renderização de lixo em alguns hardwares e inconsistência em diferentes hardwares. Essas estruturas de dados de otimização ocultas usadas pelo hardware podem ser locais para mapeamentos individuais e não visíveis para outros mapeamentos para a mesma memória.
Ao limpar uma exibição de recurso (definindo todos os elementos em uma exibição de recurso como um valor), você pode limpar exibições de destino de renderização com retângulos. Para hardware que dá suporte a recursos de streaming, a limpeza de uma exibição de recurso também deve dar suporte à limpeza de exibições de estêncil de profundidade com retângulos, para superfícies somente de profundidade (sem estêncil). Essa operação permite que os aplicativos limpem apenas a área necessária de uma superfície.
Se um aplicativo precisar preservar o conteúdo de memória existente de áreas em um recurso de streaming em que os mapeamentos foram alterados, esse aplicativo deverá contornar o requisito claro. O aplicativo pode realizar essa solução alternativa salvando primeiro o conteúdo em que os mapeamentos de bloco foram alterados (copiando-os para uma superfície temporária), emitindo o comando clear necessário e, em seguida, copiando o conteúdo de volta. Embora isso cumpra a tarefa de preservar o conteúdo da superfície para renderização incremental, a desvantagem é que o desempenho de renderização subsequente na superfície pode ser prejudicado porque as otimizações de renderização podem ser perdidas.
Se um bloco for mapeado em vários recursos de streaming ao mesmo tempo e o conteúdo do bloco for manipulado por qualquer meio (renderizar, copiar e assim por diante) por meio de um dos recursos de streaming, se o mesmo bloco for renderizado por meio de qualquer outro recurso de streaming, o bloco deverá ser limpo primeiro, conforme descrito anteriormente.
Renderização em blocos compartilhados fora da área de renderização
Suponha que uma área em um recurso de streaming esteja sendo renderizada e os blocos do pool de blocos referenciados pela área de renderização também sejam mapeados de fora da área de renderização (inclusive por meio de outros recursos de streaming, ao mesmo tempo ou não). Não há garantia de que os dados renderizados nesses blocos apareçam corretamente quando exibidos por meio de outros mapeamentos, mesmo que o layout de memória subjacente seja compatível. Esse fato se deve a estruturas de dados de otimização que alguns hardwares usam que podem ser locais para mapeamentos individuais para superfícies renderizáveis e não visíveis para outros mapeamentos para o mesmo local de memória.
Você pode contornar essa restrição copiando do mapeamento renderizado para todos os outros mapeamentos para a mesma memória que pode ser acessada (ou limpando essa memória ou copiando outros dados para ela se o conteúdo antigo não for mais necessário). Embora essa solução alternativa pareça redundante, ela faz com que todos os outros mapeamentos para a mesma memória entendam corretamente como acessar seu conteúdo e, pelo menos, a economia de memória de ter apenas um único suporte de memória física permanece intacta.
Além disso, ao alternar entre o uso de diferentes recursos de streaming que compartilham mapeamentos (a menos que apenas leitura), você deve especificar uma restrição de ordenação de acesso a dados (uma barreira) entre vários recursos em blocos, entre as opções.
Renderização para blocos compartilhados na área de renderização
Se uma área em um recurso de streaming estiver sendo renderizada e, dentro da área de renderização, vários blocos forem mapeados para o mesmo local do pool de blocos, os resultados da renderização serão indefinidos nesses blocos.
Compatibilidade de dados entre blocos de compartilhamento de recursos de streaming
Suponha que vários recursos de streaming tenham mapeamentos para os mesmos locais de pool de blocos e cada recurso seja usado para acessar os mesmos dados. Esse cenário só será válido se as outras regras sobre como evitar problemas com estruturas de otimização de hardware forem evitadas, as barreiras apropriadas forem especificadas (especificando uma restrição de ordenação de acesso a dados entre vários recursos em blocos) e os recursos de streaming forem compatíveis entre si.
O último é descrito aqui em termos do que significa que os blocos de compartilhamento de recursos de streaming são incompatíveis. As condições de incompatibilidade de acesso aos mesmos dados em mapeamentos de bloco duplicados são o uso de diferentes dimensões ou formatos de superfície ou diferenças na presença de destino de renderização ou sinalizadores de associação de estêncil de profundidade nos recursos. Gravar na memória com um tipo de mapeamento produz resultados indefinidos se você ler ou renderizar posteriormente por meio de um mapeamento de um recurso incompatível.
Se os outros mapeamentos de compartilhamento de recursos forem inicializados pela primeira vez com novos dados (reciclando a memória para uma finalidade diferente), a operação de leitura ou renderização subsequente será boa, pois os dados não estão sangrando em interpretações incompatíveis. Mas, ao alternar entre o acesso a mapeamentos incompatíveis como esse, você deve especificar barreiras (especificando uma restrição de ordenação de acesso a dados entre vários recursos em blocos).
Se o destino de renderização ou o sinalizador de associação de estêncil de profundidade não estiver definido em nenhum dos recursos que compartilham mapeamentos entre si, haverá muito menos restrições. Desde que o formato e os tipos de superfície (por exemplo, Texture2D) sejam os mesmos, os blocos podem ser compartilhados. Diferentes formatos compatíveis são casos como superfícies BC* e o formato de 32 bits ou 16 bits por componente não compactado de tamanho equivalente, como BC6H e R32G32B32A32. Muitos formatos de 32 bits por elemento também podem ser alias com R32_* (R10G10B10A2_*, R8G8B8A8_*, B8G8R8A8_*,B8G8R8X8_*,R16G16_*); Essa operação sempre foi permitida para recursos que não são de streaming.
O compartilhamento entre blocos compactados e não compactados é bom se os formatos forem compatíveis e os blocos forem preenchidos com cores sólidas.
Por fim, se nada for comum sobre os recursos que compartilham mapeamentos de bloco, exceto que nenhum tem sinalizadores de associação de estêncil de destino de renderização ou profundidade, somente a memória preenchida com 0 pode ser compartilhada com segurança; O mapeamento aparecerá como o que 0 decodificar para a definição do formato de recurso fornecido (normalmente apenas 0).
Tópicos relacionados
Acesso pipeline aos recursos de streaming