Partilhar via


Limitações de acesso de bloco com mapeamentos duplicados

Esta seção descreve as limitações de acesso a blocos com mapeamentos duplicados.

Copiar recursos lado a lado 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 lado a lado 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 (por exemplo, os recursos de origem e destino são diferentes, mas compartilham mapeamentos, ou os mapeamentos são duplicados sobre uma determinada superfície), os resultados da operação de cópia nos blocos que são compartilhados serão indefinidos.

Copiar para o recurso lado a lado com blocos duplicados na área de destino

Copiar para um recurso lado a lado com blocos duplicados na área de destino produz resultados indefinidos nesses blocos, a menos que os próprios dados sejam idênticos; blocos diferentes podem gravar os blocos em ordens diferentes.

Acessos UAV a mapeamentos de blocos duplicados

Suponha que uma UAV (exibição de acesso não ordenada) em um recurso lado a lado tenha mapeamentos de bloco duplicados em sua área ou com outros recursos associados ao pipeline. A ordenação dos acessos a estes blocos duplicados é indefinida se realizada por threads diferentes, assim como qualquer ordenação de acesso da memória a UAVs em geral é não ordenada.

Renderizando após alterações no mapeamento de blocos ou atualizações de conteúdo de mapeamentos externos

Se os mapeamentos de blocos de um recurso lado a lado tiverem sido alterados ou o conteúdo nos blocos do pool de blocos mapeados tiver sido alterado por meio de mapeamentos de outro recurso lado a lado e o recurso lado a lado 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 de limpar ou copiar nesses casos resulta em estruturas de otimização de hardware para a exibição de destino de renderização especificada ou a exibição de estêncil de profundidade está obsoleta e resultará em resultados de renderização de lixo em algum hardware e inconsistência em diferentes hardwares. Essas estruturas de dados de otimização ocultas usadas pelo hardware podem ser mapeamentos locais a individuais e não visíveis para outros mapeamentos na mesma memória.

A operação ID3D11DeviceContext1::ClearView dá suporte à limpeza de exibições de destino de renderização com retângulos. Para hardware que dá suporte a recursos lado a lado, o ClearView também deve dar suporte à limpeza de exibições de estêncil de profundidade com retângulos, somente para superfícies 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 das áreas em um recurso lado a lado 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, por exemplo, usando ID3D11DeviceContext2::CopyTiles), emitindo o comando clear necessário e copiando o conteúdo de volta. Embora isso conclua a tarefa de preservar o conteúdo da superfície para renderização incremental, a desvantagem é que o desempenho da renderização subsequente na superfície poderá ser prejudicado porque as otimizações de renderização poderão ser perdidas.

Se um bloco for mapeado em vários recursos lado a lado ao mesmo tempo e o conteúdo do bloco for manipulado por qualquer meio (renderização, cópia e assim por diante) por meio de um dos recursos lado a lado, se o mesmo bloco for renderizado por meio de qualquer outro recurso lado a lado, o bloco deverá ser limpo primeiro, conforme descrito anteriormente.

Renderizando blocos compartilhados fora da área de renderização

Suponha que uma área em um recurso lado a lado esteja sendo renderizada para 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 lado a lado, ao mesmo tempo ou não). Não há garantira de que os dados renderizados nesses blocos aparecerão corretamente quando visualizados por meio de outros mapeamentos, mesmo que o layout de memória subjacente seja compatível. Isso se deve às estruturas de dados de otimização que alguns hardwares usam que podem ser mapeamentos locais a individuais para superfícies renderizáveis e não visíveis para outros mapeamentos no mesmo local de memória. Você pode usar uma solução alternativa para essa restrição copiando do mapeamento renderizado para todos os outros mapeamentos na 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, isso 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 se ter apenas uma única memória física de backup permanece intacta. Além disso, ao alternar entre o uso de diferentes recursos lado a lado que compartilham mapeamentos (a menos que somente leitura), você deve chamar a API ID3D11DeviceContext2::TiledResourceBarrier entre as opções.

Renderizando blocos compartilhados dentro da área de renderização

Se uma área em um recurso lado a lado estiver sendo renderizada para e dentro da área de renderização vários blocos forem mapeados para o mesmo local do pool de blocos, os resultados de renderização serão indefinidos nesses blocos.

Compatibilidade de dados entre blocos de compartilhamento de recursos lado a lado

Suponha que vários recursos lado a lado tenham mapeamentos para os mesmos locais do 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 chamadas apropriadas para ID3D11DeviceContext2::TiledResourceBarrier forem feitas e os recursos lado a lado forem compatíveis entre si. Este último é descrito aqui em termos do que significa que os blocos de compartilhamento de recursos lado a lado sejam incompatíveis. As condições de incompatibilidade de acesso aos mesmos dados em mapeamentos de blocos duplicados são o uso de diferentes dimensões ou formatos de superfície, ou diferenças na presença de sinalizadores de associação do destino de renderização ou do estêncil de profundidade nos recursos. A gravação na memória com um tipo de mapeamento gera resultados indefinidos quando, subsequentemente, você lê ou renderiza usando um mapeamento de um recurso incompatível. Se os outros mapeamentos de compartilhamento de recursos forem inicializados primeiro com novos dados (reciclando a memória para um objetivo diferente), a operação de leitura ou renderização subsequente funcionará bem, pois não haverá sangria dos dados entre interpretações incompatíveis. Porém, você deve chamar a API TiledResourceBarrier ao alternar entre acessar mapeamentos incompatíveis como este.

Se o sinalizador de associação do destino de renderização ou do estêncil de profundidade não estiver definido em qualquer um dos recursos que compartilham mapeamentos entre si, haverá bem menos restrições. Contanto que os tipos de formato e superfície (por exemplo, Texture2D) sejam os mesmos, os blocos poderão ser compartilhados. Formatos diferentes compatíveis são casos como superfícies BC* e tamanho equivalente de 32 bits ou 16 bits por formato de componente, 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 não lado a lado.

Não há problema no compartilhamento entre blocos compactados e não compactados quando os formatos são compatíveis e os blocos são preenchidos com cor sólida.

Por fim, se não houver nada em comum nos mapeamentos de blocos de compartilham recursos, exceto que nenhum apresente sinalizadores de associação do destino de renderização ou do estêncil de profundidade, somente a memória preenchida com 0 poderá ser compartilhada com segurança; o mapeamento aparecerá como o valor que o 0 decodificar para a definição do formato de recurso específico (normalmente 0).

Acesso de pipeline a recursos lado a lado