Pular para o conteúdo principal

Introdução

O sistema de memória virtual gráfica foi reconstruído para o Microsoft Game Development Kit (GDK). Embora os componentes internos sejam todos novos, o conjunto amplo de recursos não é muito diferente daquele do sistema operacional ERA do XBOX One. O conjunto de recursos inclui:
  • Um espaço de endereço virtual unificado de CPU e GPU para memória gráfica, ocupando os 1.024 GB inferiores do espaço de endereço virtual, com os 4 GB inferiores reservados para alocações gráficas específicas que exigem endereços de 32 bits.
  • Um tamanho de página nativo de 64 KB para gráficos, além de um tamanho de página maior de 2 MB.
  • Os atributos gráficos especificados no momento da alocação de memória incluem leitura/gravação, execução e coerência de cache da GPU.
  • XMemAlloc, que é um heap de modo de usuário flexível e rápido para memória gráfica, incluindo a capacidade de interceptar alocações de várias bibliotecas de títulos do XBOX.
  • APIs de alocação e mapeamento de páginas físicas acessíveis ao título.
  • Acesso direto da GPU aos mapeamentos de páginas da GPU por meio das APIs de extensão de recursos lado a lado e mapeamento de páginas do Direct3D 12.
  • Tamanho de alocação de memória da tabela de páginas da GPU controlável pelo título, alocado no momento da inicialização (sem alocações em tempo de execução).

Inicializando o sistema de memória gráfica

Antes de alocar memória gráfica, o título deve inicializar o sistema de memória gráfica no kernel. Esse é um novo requisito do Microsoft Game Development Kit (GDK). A maneira mais fácil de inicializar o sistema de memória gráfica é criando um dispositivo Direct3D 12 por meio da API D3D12CreateDevice. Se o título precisar alocar ou reservar memória gráfica antes de o dispositivo Direct3D 12 ser criado, a API D3D12ConfigureVirtualMemoryX (XBOX Series X|S)/D3DConfigureVirtualMemory (XBOX One) também pode ser usada para inicializar o sistema de memória gráfica. Criar um dispositivo Direct3D 12 equivale a chamar D3D12ConfigureVirtualMemoryX com parâmetros padrão.

Novos sinalizadores para alocar memória gráfica

Uma nova API de título, XMemVirtualAlloc, foi introduzida como substituta da VirtualAlloc estendida presente no ERA do XBOX One. A VirtualAlloc no Microsoft Game Development Kit (GDK) agora está restrita ao comportamento “padrão” da plataforma, idêntico ao do Windows para desktop. A API padrão VirtualFree é usada para liberar e/ou descomprometer a memória alocada com XMemVirtualAlloc. Uma nova API XMemVirtualQuery foi adicionada para recuperar o conjunto completo de sinalizadores de proteção de CPU e GPU para um determinado endereço virtual. XMemVirtualAlloc recebe uma nova combinação de sinalizadores XMem que indicam solicitações de memória gráfica e/ou de ferramentas. Um sinalizador de alocação MEM_GRAPHICS para VirtualAlloc no ERA do XBOX One equivale a um sinalizador XMem XMEM_GRAPHICS para XMemVirtualAlloc. Um novo sinalizador, XMEM_GRAPHICS_32BIT_ADDRESS, combinado com XMEM_GRAPHICS, aloca memória gráfica, mas restringe o endereço virtual atribuído automaticamente ao intervalo de 2 GB a 4 GB. Sem o sinalizador XMEM_GRAPHICS_32BIT_ADDRESS, os endereços virtuais atribuídos automaticamente ficam acima de 4 GB e abaixo do final do intervalo coberto pela tabela de páginas gráficas (159 GB por padrão). O endereço virtual final das tabelas de páginas gráficas é definido pela quantidade de memória dedicada às tabelas de páginas gráficas e pode ser ajustado antes da primeira alocação gráfica usando a API D3D12ConfigureVirtualMemoryX.  Os sinalizadores de tamanho de página também mudaram de semântica. O ERA do XBOX One usava MEM_LARGE_PAGES para páginas de 64 KB e MEM_4MB_PAGES para páginas de 4 MB. O Microsoft Game Development Kit (GDK) agora usa MEM_64K_PAGES para páginas de 64 KB e MEM_2MB_PAGES para páginas de 2 MB. Observe que o código de título existente que usa MEM_LARGE_PAGES precisa ser atualizado de forma cuidadosa e completa para usar MEM_64K_PAGES. Páginas de 4 MB não são compatíveis com o Microsoft Game Development Kit (GDK). Por fim, os sinalizadores de proteção de página para gráficos também mudaram. Os sinalizadores PAGE_GPU_* do ERA do XBOX One foram substituídos por uma enumeração PAGE_GRAPHICS_* e um sinalizador PAGE_GRAPHICS_COHERENT para corresponder melhor aos padrões existentes de proteção de páginas da CPU. Todas as alocações gráficas via XMemGraphics devem incluir apenas um dos seguintes sinalizadores de proteção:
  • PAGE_GRAPHICS_NOACCESS
  • PAGE_GRAPHICS_READONLY
  • PAGE_GRAPHICS_READWRITE
  • PAGE_GRAPHICS_EXECUTE
  • PAGE_GRAPHICS_EXECUTE_READ
  • PAGE_GRAPHICS_EXECUTE_READWRITE
PAGE_GRAPHICS_COHERENT pode ser combinado com qualquer um dos sinalizadores de proteção mencionados anteriormente para indicar memória coerente com a GPU, também conhecida como memória “onion”. PAGE_GRAPHICS_NOCACHE só pode ser usado em hardware XBOX Series X|S e indica que a memória não deve ser armazenada em cache pela GPU (ignorar o cache). Esse sinalizador de memória é usado para memória de buffer de comandos, bem como para memória de writeback de fence no XBOX Series X|S. No caso da memória de buffer de comandos, é fundamental que o hardware de pré-busca do buffer de comandos não armazene em cache conteúdos de memória que ainda não foram gravados pela CPU. No caso da memória de writeback de fence, em que se deseja visibilidade oportuna dos dados de writeback pela CPU, definir a memória como não armazenada em cache pela GPU garante que os writebacks de fim de pipe fiquem imediatamente visíveis na memória para a CPU, em vez de permanecerem em uma linha de cache dentro dos caches da GPU. A tabela a seguir mostra o guia de conversão entre os sinalizadores do ERA do XBOX One e do Microsoft Game Development Kit (GDK) usados para alocar tipos comuns de memória gráfica, bem como os tipos de memória XMemAlloc correspondentes. | Descrição | Tipo de XMemAlloc | Sinalizadores de proteção do ERA do XBOX One | Sinalizadores de proteção do Microsoft Game Development Kit (GDK) | Sinalizadores de proteção do XBOX Series X|S | | --- | --- | --- | --- | --- | | Memória “Garlic”: write-combined na CPU e não coerente na GPU | XALLOC_MEMTYPE_GRAPHICS_WRITECOMBINE | PAGE_READWRITE | PAGE_WRITECOMBINE | PAGE_READWRITE | PAGE_WRITECOMBINE | PAGE_GRAPHICS_READWRITE | PAGE_READWRITE | PAGE_WRITECOMBINE | PAGE_GRAPHICS_READWRITE | | Memória “Onion”: armazenada em cache na CPU e coerente na GPU | XALLOC_MEMTYPE_GRAPHICS_CACHEABLE | PAGE_READWRITE | PAGE_GPU_COHERENT | PAGE_READWRITE | PAGE_GRAPHICS_COHERENT | PAGE_GRAPHICS_READWRITE | PAGE_READWRITE | PAGE_GRAPHICS_COHERENT | PAGE_GRAPHICS_READWRITE | | Buffer de comandos “Garlic” | XALLOC_MEMTYPE_GRAPHICS_COMMAND_BUFFER_WRITECOMBINE | PAGE_READWRITE | PAGE_WRITECOMBINE | PAGE_GPU_EXECUTE | PAGE_READWRITE | PAGE_WRITECOMBINE | PAGE_GRAPHICS_EXECUTE_READWRITE | PAGE_READWRITE | PAGE_WRITECOMBINE | PAGE_GRAPHICS_EXECUTE_READWRITE | PAGE_GRAPHICS_NOCACHE | | Buffer de comandos “Onion” | XALLOC_MEMTYPE_GRAPHICS_COMMAND_BUFFER_CACHEABLE | PAGE_READWRITE | PAGE_GPU_EXECUTE | PAGE_GPU_COHERENT | PAGE_READWRITE | PAGE_GRAPHICS_EXECUTE_READWRITE | PAGE_GRAPHICS_COHERENT | PAGE_READWRITE | PAGE_GRAPHICS_EXECUTE_READWRITE | PAGE_GRAPHICS_NOCACHE | PAGE_GRAPHICS_COHERENT | | Memória “Cached garlic”: armazenada em cache na CPU, não coerente na GPU e somente leitura | XALLOC_MEMTYPE_GRAPHICS_CACHEABLE_NONCOHERENT_GPU_READONLY | PAGE_READWRITE | PAGE_GPU_READONLY | PAGE_READWRITE | PAGE_GRAPHICS_READONLY | PAGE_READWRITE | PAGE_GRAPHICS_READONLY | | Memória de writeback de fence: armazenada em cache na CPU e coerente na GPU | XALLOC_MEMTYPE_GRAPHICS_GPU_UNCACHED | n/d (usava XALLOC_MEMTYPE_GRAPHICS_CACHEABLE) | PAGE_READWRITE | PAGE_GRAPHICS_COHERENT | PAGE_GRAPHICS_READWRITE | PAGE_READWRITE | PAGE_GRAPHICS_COHERENT | PAGE_GRAPHICS_NOCACHE | PAGE_GRAPHICS_READWRITE |

XMemAlloc para o Microsoft Game Development Kit (GDK)

O heap de memória de modo de usuário XMemAlloc foi trazido para o Microsoft Game Development Kit (GDK) com mudanças mínimas. Agora ele fica em sua própria DLL (xmem.dll) e biblioteca de vinculação (xmem.lib). As APIs XMemAlloc existentes, incluindo XMemAlloc, XMemFree e XMemSetAllocationHooks, ainda estão presentes e funcionam da mesma forma que no ERA do XBOX One. Um novo sinalizador Address32BitMapping foi adicionado à struct XALLOC_ATTRIBUTES, que é passada para XMemAlloc e XMemFree. O novo sinalizador indica que o chamador deseja alocar memória e que essa alocação deve ter um endereço de 32 bits. O driver gráfico de modo de usuário do Direct3D 12 do Microsoft Game Development Kit (GDK) usa esse sinalizador ao criar alocações de memória específicas, incluindo heaps de descritores e memória de objetos de estado de pipeline. Essas alocações têm longa duração e estão sempre alinhadas a páginas de 64 KB, portanto não precisam ser gerenciadas em heap. Em vez disso, as solicitações de alocação podem ser repassadas para XMemVirtualAlloc com o sinalizador XMEM_GRAPHICS_32BIT_ADDRESS. O driver gráfico do Direct3D 12 no ERA do XBOX One usava, nos bastidores, um mecanismo complicado e caro para remapear alocações arbitrárias do título no espaço de endereço de 32 bits, deixando a implementação do XMemAlloc e o título sem conhecimento da necessidade de endereços de 32 bits. O driver gráfico do Microsoft Game Development Kit (GDK) abandonou esse sistema complexo em favor de uma abordagem muito mais simples e rápida, que comunica claramente ao título e à implementação do XMemAlloc o desejo de uma alocação de 32 bits.

Alterações na memória de heap de descritores do Direct3D 12.X

O driver gráfico do Direct3D 12.X no ERA do XBOX One criava um segundo alias de memória, armazenado em cache na CPU e somente leitura, para todos os heaps de descritores visíveis para a GPU. O código que lia descritores na CPU usava esse alias somente leitura em cache para melhorar o desempenho de leitura da CPU. Esse segundo alias de memória não está mais presente no Microsoft Game Development Kit (GDK), portanto quaisquer leituras da CPU de heaps de descritores visíveis para a GPU são leituras da CPU sem cache de memória write-combined. Observe que os heaps de descritores de destino de renderização e de profundidade/estêncil (D3D12_DESCRIPTOR_HEAP_TYPE_RTV e D3D12_DESCRIPTOR_HEAP_TYPE_DSV) são sempre criados como memória armazenada em cache na CPU, independentemente de serem criados como visíveis para a GPU.

Suporte à memória “Cached Garlic” no XBOX One e no XBOX Series X|S

No XBOX One, o Microsoft Game Development Kit (GDK) não oferece mais suporte à criação de mapeamentos de memória armazenados em cache e somente leitura na CPU, e não coerentes e de leitura/gravação na GPU. Os sinalizadores de proteção de página do Microsoft Game Development Kit (GDK) usados para essa combinação não permitida são PAGE_READONLY | PAGE_GRAPHICS_READWRITE. No XBOX Series X|S, o Microsoft Game Development Kit (GDK) oferece suporte à criação de todos os 3 tipos de mapeamentos de memória em cache e não coerentes. Esses 3 tipos são leitura/gravação na CPU e somente leitura na GPU, somente leitura na CPU e leitura/gravação na GPU, e leitura/gravação na CPU e leitura/gravação na GPU. Ao usar esses tipos de memória gráfica, é preciso ter cuidado especial para evitar corrupção de memória devido ao cache não coerente pela CPU e pela GPU. Lembre-se das seguintes regras ao usar memória cached garlic:
  1. Antes de ler ou gravar memória cached garlic, na CPU ou na GPU, libere os caches.
  2. Após a conclusão das gravações na memória cached garlic, na CPU ou na GPU, libere os caches.
  3. Use primitivos de sincronização para controlar o acesso exclusivo de gravação à memória cached garlic. Evite gravações simultâneas de mais de um cliente.
  4. Ao considerar os padrões de acesso de leitura/gravação, observe linhas de cache inteiras de 64 bytes por vez, pois esse tamanho será a unidade de memória carregada nos caches da CPU e da GPU e gravada de volta. Nem sempre é possível garantir que gravações parciais de linhas de cache sejam geradas pela CPU ou pela GPU, especialmente para memória em cache.
A memória cached garlic, e todas as outras memórias gráficas armazenadas em cache na CPU, é criada no gerenciador de memória do Microsoft Game Development Kit (GDK) como memória criptografada. A GPU do XBOX Series X|S é capaz de gravar nesse tipo de memória, mas, devido a ineficiências de gravação parcial com criptografia de memória, a largura de banda não coerente máxima nem sempre pode ser alcançada. Se você decidir usar memória cached garlic no seu título, certifique-se de ter uma maneira eficaz de desabilitar completamente o cached garlic para testes, substituindo-o por memória gráfica coerente em cache. Esse recurso permitirá determinar rapidamente se o uso indevido de cached garlic é responsável por corrupção de dados ou travamentos da GPU.

Consulte também

Gráficos
Última modificação em 6 de outubro de 2026