Partilhar via


PFND3DDDI_LOCKCB função de retorno de chamada (d3dumddi.h)

A função pfnLockCb bloqueia uma alocação e obtém um ponteiro para a alocação do driver de miniporto de exibição ou do gerenciador de memória de vídeo.

Sintaxe

PFND3DDDI_LOCKCB Pfnd3dddiLockcb;

HRESULT Pfnd3dddiLockcb(
  HANDLE hDevice,
  D3DDDICB_LOCK *unnamedParam2
)
{...}

Parâmetros

hDevice

Um identificador para o dispositivo de exibição (contexto gráfico).

unnamedParam2

pData [in, out]

Um ponteiro para uma estrutura D3DDDICB_LOCK que descreve a alocação a ser bloqueada.

Retornar valor

pfnLockCb retorna um dos seguintes valores:

Código de retorno Descrição
S_OK A alocação foi bloqueada com êxito.
D3DERR_NOTAVAILABLE Uma abertura não estava disponível.
D3DERR_WASSTILLDRAWING A alocação ainda estava sendo usada para renderização.
D3DDDIERR_CANTEVICTPINNEDALLOCATION A alocação não pôde ser bloqueada devido à indisponibilidade de uma abertura deswizzling e à incapacidade de remover a alocação porque ela foi fixada.
E_OUTOFMEMORY O pfnLockCb não pôde ser concluído devido à memória insuficiente (essa situação ocorre quando o sistema está em uma situação de memória extremamente baixa e não há espaço suficiente para alocar a matriz de páginas).
E_INVALIDARG Os parâmetros foram validados e determinados como incorretos.
D3DDDIERR_DEVICEREMOVED O pfnLockCb não pôde fazer com que o gerenciador de memória de vídeo e o driver de miniporto de vídeo executassem as ações apropriadas porque ocorreu uma parada de Plug and Play (PnP) ou um evento TDR (Detecção e Recuperação de Tempo limite). A função de driver de exibição do modo de usuário que chamou pfnLockCb(normalmente, a função Lock ou ResourceMap ) deve retornar esse código de erro de volta ao runtime do Direct3D.
Direct3D Versão 9 Observação: para obter mais informações sobre como retornar códigos de erro, consulte Retornando códigos de erro recebidos de funções de runtime.
Versões 10 e 11 do Direct3D Observação: se a função driver não retornar um valor (ou seja, tem VOID para um tipo de parâmetro de retorno), a função de driver chamará a função pfnSetErrorCb para enviar um código de erro de volta ao runtime. Para obter mais informações sobre como lidar com códigos de erro, consulte Tratamento de erros.

Essa função também pode retornar outros valores HRESULT.

Comentários

O driver de exibição no modo de usuário pode chamar a função pfnLockCb do runtime do Microsoft Direct3D para bloquear uma alocação e obter um ponteiro para a alocação do driver de miniporto de exibição ou do gerenciador de memória de vídeo. O driver de exibição do modo de usuário normalmente chama pfnLockCb em resposta a uma chamada para sua função Lock ou ResourceMap (ou outras variações de ResourceMap , como DynamicIABufferMapDiscard) para bloquear um recurso ou uma superfície dentro do recurso. Antes de retornar da chamada Lock ou ResourceMap , o driver de exibição do modo de usuário deve primeiro mapear o recurso ou a superfície para a alocação apropriada e, em seguida, chamar pfnLockCb para bloquear a alocação. A alocação deve ser bloqueada antes de ser lida ou gravada porque está bloqueando:

  • Garante que o intervalo de endereços virtuais para a alocação permaneça inalterado, válido, legível e gravável durante o bloqueio. O gerenciador de memória de vídeo fornece essa garantia.
  • Fornece uma maneira de sincronizar as operações de leitura e gravação da alocação com acessos de hardware gráficos da alocação. O gerenciador de memória de vídeo e o driver de miniporto de vídeo executam a sincronização.
Observação do Direct3D versão 9:

O driver de exibição do modo de usuário geralmente chama as funções pfnLockCb e pfnUnlockCb que correspondem a cada chamada para suas funções de Bloqueio e Desbloqueio , respectivamente, exceto quando o driver manipula recursos nos quais o sinalizador de campo de bit dinâmico foi definido no membro Flags da estrutura D3DDDIARG_CREATERESOURCE quando os recursos foram criados. O runtime solicita frequentemente que o driver bloqueie esses tipos de recursos, geralmente com o sinalizador de campo de bits NoOverwrite definido no membro Flags da estrutura D3DDDIARG_LOCK . Como os dados nesses recursos não devem ser modificados (conforme indicado por NoOverwrite), chamar pfnLockCb para cada solicitação de bloqueio consome tempo excessivo de processamento. Para impedir a chamada de pfnLockCb para cada solicitação de bloqueio, o driver pode armazenar em cache o ponteiro de memória virtual que retorna no membro pSurfData de D3DDDIARG_LOCK quando sua função Lock é chamada com o sinalizador de campo de bits NoOverwrite definido. No entanto, o driver pode continuar a chamar pfnLockCb sempre que sua função Lock for chamada com o sinalizador Descartar campo de bits definido ou nenhum sinalizador definido.

Observação das versões 10 e 11 do Direct3D:

O driver de exibição do modo de usuário geralmente chama as funções pfnLockCb e pfnUnlockCb que correspondem a cada chamada às funções ResourceMap e ResourceUnmap (ou outras variações dessas funções). Isso não acontece quando o driver manipula recursos nos quais o valor de D3D10_DDI_USAGE_DYNAMIC foi definido no membro Uso da estrutura D3D10DDIARG_CREATERESOURCE ou D3D11DDIARG_CREATERESOURCE quando os recursos foram criados. O runtime solicita frequentemente que o driver bloqueie esses tipos de recursos, geralmente passando o valor D3D10_DDI_MAP_WRITE_NOOVERWRITE para o parâmetro DDIMap na chamada para ResourceMap. Como os dados nesses recursos não devem ser modificados (conforme indicado por D3D10_DDI_MAP_WRITE_NOOVERWRITE), chamar pfnLockCb para cada solicitação de bloqueio consome tempo excessivo de processamento. Para evitar chamar pfnLockCb para cada solicitação de bloqueio, o driver pode armazenar em cache o ponteiro de memória virtual que retorna no parâmetro pMappedSubResource quando sua função ResourceMap é chamada com D3D10_DDI_MAP_WRITE_NOOVERWRITE. No entanto, o driver pode continuar a chamar pfnLockCb sempre que sua função ResourceMap for chamada com o valor D3D10_DDI_MAP_WRITE_DISCARD ou 0 passado para o parâmetro DDIMap .

Embora o aplicativo não mantenha um bloqueio pendente para o recurso associado ao ponteiro de memória virtual, o driver normalmente desafixa o ponteiro de memória virtual chamando a função pfnUnlockCb antes que o driver chame a função pfnRenderCb . Se o bloqueio não for não armazenado em cache ou se o bloqueio não puder ser armazenado em cache porque o aplicativo ainda tem o recurso bloqueado, o hardware poderá ser renderizado de uma alocação bloqueada. O gerenciador de memória de vídeo não poderá dar suporte a esse modo de operação se a alocação estiver na memória de vídeo local; portanto, o gerenciador de memória remove a alocação para a memória do sistema ou do AGP quando o gerenciador de memória detecta essa situação. Se não houver suporte para a alocação no sistema ou no segmento de memória AGP, o gerenciador de memória falhará na chamada para pfnRenderCb com D3DDDIERR_CANTRENDERLOCKEDALLOCATION. Portanto, as alocações de buffer de vértice e de índice alocadas em resposta à criação de recursos nos quais o sinalizador de campo de bit dinâmico é definido no membro Flags de D3DDDIARG_CREATERESOURCE (ou o valor D3D10_DDI_USAGE_DYNAMIC é definido no Membro de uso de D3D10DDIARG_CREATERESOURCE ou D3D11DDIARG_CREATERESOURCE) devem ter suporte em segmentos de sistema ou AGP.

Definir o sinalizador Descartar campo de bits no membro Flags do D3DDDICB_LOCK em uma chamada para pfnLockCb faz com que o gerenciador de memória de vídeo crie uma nova instância da alocação que está sendo bloqueada. O gerenciador de memória de vídeo representa a nova instância retornando um novo identificador para o driver de exibição do modo de usuário no membro hAllocation do D3DDDICB_LOCK.

Nota A função DxgkDdiCreateAllocation do driver de miniport de exibição não é chamada quando uma nova instância de uma alocação é criada. As instâncias aparecem para o driver de miniporto de exibição como alocações que são paginada simultaneamente em vários locais diferentes.
 
O gerenciador de memória de vídeo pode falhar em um bloqueio no qual o sinalizador Descartar campo de bit é definido porque o gerenciador de memória de vídeo não pode criar uma nova instância ou reutilizar uma instância existente de uma alocação. Quando essa falha ocorre, o driver de exibição do modo de usuário deve chamar a função pfnRenderCb para liberar seu buffer de comando atual para o kernel. Essa liberação do buffer de comando pode desativar algumas instâncias da alocação que não puderam ser bloqueadas usando o sinalizador Descartar campo de bits.

Depois de liberar o buffer de comando, o driver de exibição do modo de usuário deve tentar bloquear a superfície novamente usando os sinalizadores de campo de bits Discard e NoExistingReference . O sinalizador de campo de bits NoExistingReference indica ao gerenciador de memória de vídeo que o driver não tem atualmente uma referência a nenhuma instância da alocação que está sendo bloqueada na fila em seu buffer de comando. O gerenciador de memória de vídeo pode reutilizar qualquer instância da alocação para lidar com o bloqueio, incluindo a instância atual.

Após uma chamada para pfnLockCb na qual o sinalizador descartar campo de bits é definido, o driver de exibição do modo de usuário deve sempre marcar para um valor de identificador atualizado no membro hAllocation de D3DDDICB_LOCK. Se um novo identificador de alocação for fornecido, o driver de exibição do modo de usuário deverá atualizar sua estrutura de dados interna para fazer referência ao novo identificador de alocação. O driver de exibição do modo de usuário também deve adicionar uma versão re-programada do endereço base de alocação bloqueado ao buffer de comando atual (porque as instâncias de alocação contêm endereços base diferentes). O gerenciador de memória de vídeo valida o uso de instâncias de alocação usadas pelo driver e rejeita buffers DMA que usam as instâncias de alocação incorretamente (ou seja, as chamadas para pfnPresentCb e pfnRenderCb falham se usarem incorretamente instâncias de alocação). Depois que o driver faz referência a uma instância específica de uma alocação, o driver não pode mais referenciar uma instância anterior da mesma alocação. Por exemplo, se um buffer de comando usa alocação A e usa atualmente as instâncias A0 e A1, assim que a A1 é usada (ou seja, aparece na lista de locais de patch) o A0 se torna inválido. O driver de miniporto de exibição pode gerar uma lista de localização de patch que faz referência ao A0 e ao A1. No entanto, as referências devem ser ordenadas (ou seja, A0 pode ser usado primeiro; O A0 torna-se inválido quando o A2 é usado; A1 torna-se inválido quando A2 é usado e assim por diante).

O driver de exibição do modo de usuário pode chamar pfnLockCb para alocações de memória do sistema, mesmo que a memória não tenha sido pré-alocada, pois o driver de miniporto de exibição pode realmente estar em processo de envio, por meio de DMA ou transferência assíncrona dessas alocações para hardware gráfico. Portanto, antes que um aplicativo tenha permissão para gravar na superfície, o driver de miniporto de exibição e o gerenciador de memória de vídeo devem ser notificados para que possam bloquear o bloqueio, se necessário.

O driver de exibição do modo de usuário também pode bloquear sub-regiões de uma alocação. Normalmente, esse tipo de bloqueio não é necessário quando uma abertura de hardware deswizzling ou linearização está disponível porque, nessa situação, o driver de exibição do modo de usuário pode converter um bloqueio em toda a alocação para a sub-região, compensando o ponteiro. No entanto, quando o pfnLockCb falha usando D3DERR_NOTAVAILABLE para indicar que uma abertura não está disponível, o gerenciador de memória solicita que o driver de exibição do modo de usuário copie o conteúdo da memória de vídeo. O driver de exibição do modo de usuário deswizzles ou lineariza o conteúdo da memória de vídeo enquanto os copia para outra área de memória. Nessa situação, o driver de exibição do modo de usuário pode fornecer uma lista de páginas a serem copiadas para economizar grandes quantidades de cópia ao bloquear pequenas sub-regiões em uma alocação grande. Observe que o gerenciador de memória falha em uma chamada para pfnLockCb com D3DERR_NOTAVAILABLE se o driver de exibição do modo de usuário não definiu o sinalizador de campo de bits LockEntire no membro Flags da estrutura D3DDDICB_LOCK e não especificou uma lista de páginas no membro pPages do D3DDDICB_LOCK. Se o driver de exibição do modo de usuário definir o sinalizador de campo de bit LockEntire , ele também deverá definir os membros NumPages e pPages de D3DDDICB_LOCK como 0 e NULL, respectivamente. O driver de exibição do modo de usuário sempre deve fornecer uma lista de páginas em pPages ao bloquear uma alocação que foi criada com um repositório de backup permanente. Nessa situação, o gerenciador de memória usa a lista de páginas para marcar como sujo apenas páginas específicas e não é necessário copiar toda a alocação do repositório de backup quando ela é usada para renderização.

O driver de exibição do modo de usuário pode chamar pfnLockCb para adquirir vários intervalos de swizzling para uma única alocação (por exemplo, um intervalo de giro para cada nível de MIP). Se o driver não puder adquirir nenhum dos intervalos, o runtime do Direct3D removerá toda a alocação para lidar com o bloqueio (todos os níveis de MIP) e recuperará todos os intervalos de swizzling.

Quando o driver de exibição do modo de usuário solicita que um intervalo de swizzling seja atribuído à alocação, o driver solicita efetivamente acesso aos bits deswizzled da alocação. Para essas solicitações, o gerenciador de memória de vídeo ou páginas na alocação em um segmento de memória e configura um intervalo de swizzling para acessar a alocação ou páginas na alocação em um segmento de memória e, em seguida, remove a alocação para a memória do sistema enquanto solicita que o driver deswizzle a alocação no caminho para a memória do sistema. Uma alocação que foi deswizzled para a memória do sistema é reswizzled (por ser paginada na memória de vídeo) antes que a GPU use a alocação novamente. Como resultado, o driver não pode solicitar um bloqueio sem tipo de substituição (definindo o sinalizador de campo de bits DonotWait ) quando ele adquire um intervalo de swizzling. Da mesma forma, o driver não pode referenciar um bloqueio de alocação dessa forma em um buffer de DMA enviado à GPU (porque o buffer de DMA será rejeitado).

O driver de exibição do modo de usuário pode bloquear uma alocação deswizzled sem adquirir um intervalo de swizzling se o driver precisar acessar os bits da alocação em um formato girado. Nessa situação, o gerenciador de memória de vídeo fornece ao driver um ponteiro para os bits girados da alocação. No entanto, o driver não pode solicitar um ponteiro para os bits girados da alocação enquanto uma solicitação para os bits deswizzled estiver pendente e vice-versa (ou seja, um bloqueio está atualmente pendente na alocação com um intervalo de swizzling adquirido).

O driver de exibição do modo de usuário deve passar o sinalizador Descartar campo de bits no membro Flags do D3DDDICB_LOCK na chamada pfnLockCb nas seguintes situações:

  • Quando o runtime do Direct3D passa o sinalizador Descartar campo de bits no membro Flags da estrutura D3DDDIARG_LOCK na chamada para a função Lock do driver de exibição no modo de usuário
  • Quando o runtime passa o valor D3D10_DDI_MAP_WRITE_DISCARD para o parâmetro DDIMap na chamada para a função ResourceMap do driver
Definir o sinalizador Descartar campo de bits faz com que o gerenciador de memória determine se ele deve renomear a alocação ou deve fazer com que o thread do aplicativo seja interrompido até que a alocação esteja ociosa. Para obter mais informações sobre como renomear uma alocação, consulte Solicitando renomeação de uma alocação. O driver pode usar seu próprio suporte de renomeação ou o suporte de renomeação do gerenciador de memória. Para usar seu próprio suporte de renomeação, o driver define o sinalizador de campo de bits DonotWait , em resposta a uma chamada lock com o sinalizador Descartar campo de bits definido ou em resposta a uma chamada ResourceMap com o valor D3D10_DDI_MAP_WRITE_DISCARD definido. Definir o sinalizador de campo de bits DonotWait faz com que o gerenciador de memória falhe na chamada para pfnLockCb com D3DERR_WASSTILLDRAWING se o hardware gráfico ainda estiver usando a alocação. Essa falha indica ao driver de exibição do modo de usuário para renomear ou para vários buffers a alocação.
Nota O sinalizador de campo de bits DonotWait não terá efeito no gerenciador de memória se o sinalizador Descartar campo de bits também estiver definido.
 
O driver de exibição do modo de usuário deve definir o sinalizador de campo de bits IgnoreSync no membro Flags do D3DDDICB_LOCK quando não exigir que o gerenciador de memória marcar se o hardware gráfico está usando a alocação. O driver de exibição do modo de usuário deve sincronizar corretamente o acesso à alocação. Se o sinalizador de campo de bits DonotWait não for especificado com o sinalizador de campo de bits IgnoreSync , o gerenciador de memória ignorará o sinalizador de campo de bits IgnoreSync .
Nota O sinalizador de campo de bits IgnoreSync não terá efeito no gerenciador de memória se o sinalizador Descartar campo de bits também estiver definido.
 
Exemplo

O exemplo de código a seguir mostra como o sinalizador Descartar campo de bits é usado em uma chamada para pfnLockCb.

HRESULT hr;
D3DDDICB_LOCK LockData;
LockData.hAllocation = AllocationToLock;
LockData.Flags.Discard = TRUE;
hr = pfnLockCb(&LockData)
if (FAILED(hr)) {
    FlushAccumulatedCommandBufferToKernel();
    LockData.Flags.Discard = TRUE;
    LockData.Flags.NoExistingReference = TRUE;
    hr = pfnLockCb(&LockData);
    if (FAILED(hr)) {
        // Fails the lock to the application
    }
}
UpdateAllocationHandleInUMDDataStructure(LockData.hAllocation);
ProgramSurfaceBaseAddressInCurrentCommandBuffer(LockData.hAllocation);

Requisitos

Requisito Valor
Cliente mínimo com suporte Disponível no Windows Vista e versões posteriores dos sistemas operacionais Windows.
Plataforma de Destino Área de Trabalho
Cabeçalho d3dumddi.h (inclua D3dumddi.h)

Confira também

D3D10DDIARG_CREATERESOURCE

D3D11DDIARG_CREATERESOURCE

D3DDDIARG_LOCK

D3DDDICB_LOCK

D3DDDI_DEVICECALLBACKS

Bloquear

ResourceMap

ResourceUnmap