PFND3DDDI_LOCKCB 콜백 함수(d3dumddi.h)

pfnLockCb 함수는 할당을 잠그고 디스플레이 미니포트 드라이버 또는 비디오 메모리 관리자에서 할당에 대한 포인터를 가져옵니다.

구문

PFND3DDDI_LOCKCB Pfnd3dddiLockcb;

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

매개 변수

hDevice

디스플레이 디바이스(그래픽 컨텍스트)에 대한 핸들입니다.

unnamedParam2

pData [in, out]

잠금 할당을 설명하는 D3DDDICB_LOCK 구조체에 대한 포인터입니다.

반환 값

pfnLockCb 는 다음 값 중 하나를 반환합니다.

반환 코드 설명
S_OK 할당이 성공적으로 잠겼습니다.
D3DERR_NOTAVAILABLE 조리개는 사용할 수 없습니다.
D3DERR_WASSTILLDRAWING 할당은 여전히 렌더링에 사용되고 있습니다.
D3DDDIERR_CANTEVICTPINNEDALLOCATION 소멸 조리개 사용 불가와 고정되었기 때문에 할당을 제거할 수 없기 때문에 할당을 잠글 수 없습니다.
E_OUTOFMEMORY 메모리 부족으로 인해 pfnLockCb 를 완료할 수 없습니다(이 상황은 시스템이 메모리가 매우 부족하고 페이지 배열을 할당할 공간이 충분하지 않은 경우에 발생합니다).
E_INVALIDARG 매개 변수의 유효성이 검사되었고 잘못된 것으로 확인되었습니다.
D3DDDIERR_DEVICEREMOVED pnP(플러그 앤 플레이) 중지 또는 TDR(시간 제한 검색 및 복구) 이벤트가 발생했기 때문에 pfnLockCb에서 비디오 메모리 관리자 및 디스플레이 미니포트 드라이버가 적절한 작업을 수행하도록 할 수 없습니다. pfnLockCb(일반적으로 Lock 또는 ResourceMap 함수)를 호출한 사용자 모드 표시 드라이버 함수는 이 오류 코드를 Direct3D 런타임으로 다시 반환해야 합니다.
Direct3D 버전 9 참고: 오류 코드를 반환하는 방법에 대한 자세한 내용은 런타임 함수에서 받은 오류 코드 반환을 참조하세요.
Direct3D 버전 10 및 11 참고: 드라이버 함수가 반환 매개 변수 형식에 대해 VOID가 있는 값을 반환하지 않는 경우 드라이버 함수는 pfnSetErrorCb 함수를 호출하여 오류 코드를 런타임으로 다시 보냅니다. 오류 코드 처리에 대한 자세한 내용은 오류 처리를 참조하세요.

이 함수는 다른 HRESULT 값을 반환할 수도 있습니다.

설명

사용자 모드 디스플레이 드라이버는 Microsoft Direct3D 런타임의 pfnLockCb 함수를 호출하여 할당을 잠그고 디스플레이 미니포트 드라이버 또는 비디오 메모리 관리자에서 할당에 대한 포인터를 가져올 수 있습니다. 사용자 모드 표시 드라이버는 일반적으로 Lock 또는 ResourceMap 함수(또는 DynamicIABufferMapDiscard와 같은 ResourceMap의 다른 변형)에 대한 호출에 대한 응답으로 pfnLockCb를 호출하여 리소스 또는 리소스 내의 표면을 잠급니다. Lock 또는 ResourceMap 호출에서 반환하기 전에 사용자 모드 표시 드라이버는 먼저 리소스 또는 표면을 적절한 할당에 매핑한 다음 pfnLockCb를 호출하여 할당을 잠가야 합니다. 잠금으로 인해 할당을 읽거나 쓰기 전에 잠가야 합니다.

  • 할당에 대한 가상 주소 범위가 잠금 기간 동안 변경되지 않고 유효하며 읽기 가능하며 쓰기 가능한 상태로 유지되도록 보장합니다. 비디오 메모리 관리자는 이 보증을 제공합니다.
  • 할당의 읽기 및 쓰기 작업을 그래픽 하드웨어 액세스와 동기화하는 방법을 제공합니다. 비디오 메모리 관리자 및 디스플레이 미니포트 드라이버가 동기화를 수행합니다.
Direct3D 버전 9 참고:

사용자 모드 표시 드라이버는 일반적으로 드라이버가 리소스를 만들 때 D3DDDIARG_CREATERESOURCE 구조의Flags 멤버에서 동적 비트 필드 플래그가 설정된 리소스를 처리하는 경우를 제외하고 각각 LockUnlock 함수에 대한 모든 호출에 해당하는 pfnLockCbpfnUnlockCb 함수를 호출합니다. 런타임은 종종 드라이버가 이러한 유형의 리소스를 잠그라고 요청하며, 종종 D3DDDIARG_LOCK 구조의 Flags 멤버에 NoOverwrite 비트 필드 플래그가 설정됩니다. 이러한 리소스의 데이터는 수정해서는 안 되므로( NoOverwrite에 표시된 대로) 각 잠금 요청에 대해 pfnLockCb 를 호출하면 과도한 처리 시간이 소요됩니다. 각 잠금 요청에 대해 pfnLockCb를 호출하지 않도록 하려면 드라이버가 NoOverwrite 비트 필드 플래그 집합을 사용하여 Lock 함수를 호출할 때 D3DDDIARG_LOCK pSurfData 멤버에서 반환하는 가상 메모리 포인터를 캐시할 수 있습니다. 그러나 드라이버는 Lock 함수가 삭제 비트 필드 플래그 집합 또는 플래그가 설정되지 않은 상태에서 호출할 때마다 pfnLockCb를 계속 호출할 수 있습니다.

Direct3D 버전 10 및 11 참고:

사용자 모드 표시 드라이버는 일반적으로 ResourceMap 및 ResourceUnmap 함수(또는 이러한 함수의 다른 변형)에 대한 모든 호출에 해당하는 pfnLockCb 및pfnUnlockCb 함수를 호출합니다. 이는 드라이버가 리소스를 만들 때 D3D10DDIARG_CREATERESOURCE 또는 D3D11DDIARG_CREATERESOURCE 구조체의 Usage 멤버에서 D3D10_DDI_USAGE_DYNAMIC 값이 설정된 리소스를 처리하는 경우 발생하지 않습니다. 런타임은 종종 ResourceMap 호출에서 D3D10_DDI_MAP_WRITE_NOOVERWRITE 값을 DDIMap 매개 변수에 전달하여 드라이버가 이러한 유형의 리소스를 잠그도록 요청합니다. 이러한 리소스의 데이터는 수정해서는 안 되므로(D3D10_DDI_MAP_WRITE_NOOVERWRITE 표시된 대로) 각 잠금 요청에 대해 pfnLockCb 를 호출하면 과도한 처리 시간이 소요됩니다. 각 잠금 요청에 대해 pfnLockCb 호출을 방지하기 위해 드라이버는 resourceMap 함수가 D3D10_DDI_MAP_WRITE_NOOVERWRITE 호출된 경우 pMappedSubResource 매개 변수에서 반환하는 가상 메모리 포인터를 캐시할 수 있습니다. 그러나 드라이버는 resourceMap 함수가 D3D10_DDI_MAP_WRITE_DISCARD 값 또는 DDIMap 매개 변수에 전달된 0으로 호출될 때마다 pfnLockCb를 계속 호출할 수 있습니다.

애플리케이션은 가상 메모리 포인터와 연결된 리소스에 대한 미해결 잠금을 보유하지 않지만 드라이버는 일반적으로 드라이버가 pfnRenderCb 함수를 호출하기 전에 pfnUnlockCb 함수를 호출하여 가상 메모리 포인터를 캐시하지 않습니다. 잠금이 캐시되지 않았거나 애플리케이션에 여전히 리소스가 잠겨 있기 때문에 잠금을 캐시할 수 없는 경우 하드웨어가 잠긴 할당에서 렌더링될 수 있습니다. 할당이 로컬 비디오 메모리에 있는 경우 비디오 메모리 관리자는 이 작업 모드를 지원할 수 없습니다. 따라서 메모리 관리자는 메모리 관리자가 이 상황을 감지할 때 시스템 또는 AGP 메모리에 대한 할당을 제거합니다. 시스템 또는 AGP 메모리 세그먼트에서 할당이 지원되지 않는 경우 메모리 관리자는 D3DDDIERR_CANTRENDERLOCKEDALLOCATION 사용하여 pfnRenderCb 호출에 실패합니다. 따라서 동적 비트 필드 플래그가 D3DDDIARG_CREATERESOURCE Flags 멤버(또는 D3D10DDIARG_CREATERESOURCE 또는 D3D11DDIARG_CREATERESOURCE Usage 멤버에 설정된 D3D10_DDI_USAGE_DYNAMIC 값)에서 설정된 리소스를 만드는 데 대한 응답으로 할당된 꼭짓점 및 인덱스 버퍼 할당은 시스템 또는 AGP 세그먼트에서 지원되어야 합니다.

pfnLockCb 호출에서 D3DDDICB_LOCKFlags 멤버에서 삭제 비트 필드 플래그를 설정하면 비디오 메모리 관리자가 잠겨 있는 할당의 새 instance 만듭니다. 비디오 메모리 관리자는 D3DDDICB_LOCK hAllocation 멤버의 사용자 모드 표시 드라이버에 새 핸들을 반환하여 새 instance 나타냅니다.

참고 할당의 새 instance 만들 때 디스플레이 미니포트 드라이버의 DxgkDdiCreateAllocation 함수가 호출되지 않습니다. 인스턴스는 여러 다른 위치에 동시에 페이징되는 할당으로 표시 미니포트 드라이버에 표시됩니다.
 
비디오 메모리 관리자는 새 instance 만들거나 할당의 기존 instance 다시 사용할 수 없으므로 비트 필드 삭제 플래그가 설정된 잠금에 실패할 수 있습니다. 이 오류가 발생하면 사용자 모드 표시 드라이버는 pfnRenderCb 함수를 호출하여 현재 명령 버퍼를 커널로 플러시해야 합니다. 명령 버퍼의 이 플러시 에서는 삭제 비트 필드 플래그를 사용하여 잠글 수 없는 할당의 일부 인스턴스를 사용 중지할 수 있습니다.

명령 버퍼를 플러시한 후 사용자 모드 표시 드라이버는 DiscardNoExistingReference 비트 필드 플래그를 모두 사용하여 표면을 다시 잠그려고 시도해야 합니다. NoExistingReference 비트 필드 플래그는 비디오 메모리 관리자에게 드라이버에 현재 명령 버퍼에서 대기 중인 할당의 instance 대한 참조가 없음을 나타냅니다. 그런 다음 비디오 메모리 관리자는 할당의 모든 instance 다시 사용하여 현재 instance 포함하여 잠금을 처리할 수 있습니다.

비트 필드 삭제 플래그가 설정된 pfnLockCb를 호출한 후 사용자 모드 표시 드라이버는 항상 D3DDDICB_LOCK hAllocation 멤버의 업데이트된 핸들 값에 대해 검사 합니다. 새 할당 핸들이 제공된 경우 사용자 모드 표시 드라이버는 새 할당 핸들을 참조하도록 내부 데이터 구조를 업데이트해야 합니다. 또한 사용자 모드 표시 드라이버는 현재 명령 버퍼에 잠긴 할당 기본 주소의 다시 프로그래밍된 버전을 추가해야 합니다(할당 인스턴스에 다른 기본 주소가 포함되어 있기 때문). 비디오 메모리 관리자는 드라이버에서 사용하는 할당 인스턴스의 사용의 유효성을 검사하고 할당 인스턴스를 잘못 사용하는 DMA 버퍼를 거부합니다(즉, 할당 인스턴스를 잘못 사용하는 경우 pfnPresentCbpfnRenderCb 호출 실패). 드라이버가 할당의 특정 instance 참조한 후 드라이버는 더 이상 동일한 할당의 이전 instance 참조할 수 없습니다. 예를 들어 명령 버퍼가 할당 A를 사용하고 현재 A0 및 A1 인스턴스를 사용하는 경우 A1이 사용되는 즉시(즉, 패치 위치 목록에 표시됨) A0이 잘못됩니다. 디스플레이 미니포트 드라이버는 A0 및 A1을 모두 참조하는 패치 위치 목록을 생성할 수 있습니다. 그러나 참조는 순서를 지정해야 합니다(즉, A0을 먼저 사용할 수 있음) A0은 A2를 사용하면 유효하지 않습니다. A1은 A2를 사용할 때 유효하지 않습니다.)

사용자 모드 디스플레이 드라이버는 메모리가 미리 할당되지 않은 경우에도 시스템 메모리 할당을 위해 pfnLockCb 를 호출할 수 있습니다. 디스플레이 미니포트 드라이버가 실제로 DMA를 통해 또는 그래픽 하드웨어로 해당 할당을 비동기적으로 전송하는 프로세스에 있을 수 있기 때문입니다. 따라서 애플리케이션이 표면에 쓰도록 허용하기 전에 디스플레이 미니포트 드라이버 및 비디오 메모리 관리자에 알림을 보내 필요한 경우 잠금을 차단할 수 있도록 해야 합니다.

사용자 모드 표시 드라이버는 할당의 하위 리소스를 잠글 수도 있습니다. 이 경우 사용자 모드 표시 드라이버가 포인터를 오프셋하여 전체 할당에 대한 잠금을 하위 리전으로 변환할 수 있기 때문에 이러한 유형의 잠금은 일반적으로 언스위즐링 또는 선형화 하드웨어 조리개에서 사용할 수 있는 경우에 필요하지 않습니다. 그러나 D3DERR_NOTAVAILABLE 사용하여 조리개 사용이 불가능함을 나타내면서 pfnLockCb 이 실패하면 메모리 관리자는 사용자 모드 표시 드라이버에 비디오 메모리 콘텐츠를 복사하도록 요청합니다. 사용자 모드 표시 드라이버는 비디오 메모리 콘텐츠를 다른 메모리 영역으로 복사하는 동안 스와이즈 해제하거나 선형화합니다. 이 경우 사용자 모드 표시 드라이버는 큰 할당에서 작은 하위 리소스를 잠글 때 대량의 복사를 저장하기 위해 복사할 페이지 목록을 제공할 수 있습니다. 사용자 모드 표시 드라이버가 D3DDDICB_LOCK 구조의 Flags 멤버에서 LockEntire 비트 필드 플래그를 설정하지 않고 D3DDDICB_LOCK pPages 멤버에 페이지 목록을 지정하지 않은 경우 메모리 관리자가 D3DERR_NOTAVAILABLEpfnLockCb 호출에 실패합니다. 사용자 모드 표시 드라이버가 LockEntire 비트 필드 플래그를 설정하는 경우 D3DDDICB_LOCK NumPagespPages 멤버도 각각 0 및 NULL로 설정해야 합니다. 영구 백업 저장소를 사용하여 만든 할당을 잠글 때 사용자 모드 표시 드라이버는 항상 pPages 에 페이지 목록을 제공해야 합니다. 이 경우 메모리 관리자는 페이지 목록을 사용하여 특정 페이지만 더티 표시하며 렌더링에 사용될 때 백업 저장소에서 전체 할당을 복사할 필요가 없습니다.

사용자 모드 표시 드라이버는 pfnLockCb 를 호출하여 단일 할당에 대해 여러 스위즐링 범위를 획득할 수 있습니다(예: 각 MIP 수준에 대해 하나의 스위즐링 범위). 드라이버가 범위 중 하나를 획득할 수 없는 경우 Direct3D 런타임은 전체 할당을 제거하여 잠금(모든 MIP 수준)을 처리하고 모든 스위즐링 범위를 회수합니다.

사용자 모드 표시 드라이버가 스위즐링 범위를 할당에 할당하도록 요청하면 드라이버는 할당의 얽매이지 않은 비트에 대한 액세스를 효과적으로 요청합니다. 이러한 요청의 경우 비디오 메모리 관리자는 할당의 페이지를 메모리 세그먼트로 페이지로 설정하고 메모리 세그먼트로 할당 또는 할당의 페이지에 액세스하도록 스위즐링 범위를 설정한 다음, 드라이버가 시스템 메모리로 가는 길에 할당을 해제하도록 요청하면서 시스템 메모리에 대한 할당을 제거합니다. GPU가 할당을 다시 사용하기 전에 시스템 메모리에 대한 할당이 다시 표시됩니다(비디오 메모리로 페이징됨). 따라서 드라이버는 스위즐링 범위를 획득할 때 DonotWait 비트 필드 플래그를 설정하여 덮어쓰지 않는 형식 잠금을 요청할 수 없습니다. 마찬가지로 드라이버는 GPU에 제출되는 DMA 버퍼에서 이러한 방식으로 할당 잠금을 참조할 수 없습니다(DMA 버퍼가 거부되기 때문).

드라이버가 스위즐 형식으로 할당의 비트에 액세스해야 하는 경우 사용자 모드 표시 드라이버는 스위즐링 범위를 획득하지 않고 스위즐된 할당을 잠글 수 있습니다. 이 경우 비디오 메모리 관리자는 드라이버에 할당의 살짝 밀린 비트에 대한 포인터를 제공합니다. 그러나 드라이버가 스와이징되지 않은 비트에 대한 요청이 미해결 상태인 동안에는 할당의 스위즐된 비트에 대한 포인터를 요청할 수 없으며, 그 반대의 경우도 마찬가지입니다(즉, 스위즐링 범위가 획득한 할당에 대한 잠금이 현재 보류 중임).

사용자 모드 표시 드라이버는 다음과 같은 상황에서 pfnLockCb 호출에서 D3DDDICB_LOCK Flags 멤버의 삭제 비트 필드 플래그를 전달해야 합니다.

  • Direct3D 런타임이 사용자 모드 표시 드라이버의 Lock 함수 호출에서 D3DDDIARG_LOCK 구조체의 Flags 멤버에 있는 삭제 비트 필드 플래그를 전달하는 경우
  • 런타임이 드라이버의 ResourceMap 함수 호출에서 DDIMap 매개 변수에 D3D10_DDI_MAP_WRITE_DISCARD 값을 전달하는 경우
삭제 비트 필드 플래그를 설정하면 메모리 관리자가 할당 이름을 바꿔야 하는지 또는 할당이 유휴 상태가 될 때까지 애플리케이션 스레드가 중단되어야 하는지를 결정합니다. 할당 이름을 바꾸는 방법에 대한 자세한 내용은 할당 이름 바꾸기 요청을 참조하세요. 드라이버는 고유한 이름 바꾸기 지원 또는 메모리 관리자의 이름 바꾸기 지원을 사용할 수 있습니다. 고유한 이름 바꾸기 지원을 사용하기 위해 드라이버는 비트 필드 삭제 플래그가 설정된 Lock 호출에 대한 응답으로 또는 D3D10_DDI_MAP_WRITE_DISCARD 값이 설정된 ResourceMap 호출에 대한 응답으로 DonotWait비트 필드 플래그를 설정합니다. DonotWait 비트 필드 플래그를 설정하면 그래픽 하드웨어가 여전히 할당을 사용하는 경우 메모리 관리자가 D3DERR_WASSTILLDRAWING 사용하여 pfnLockCb 호출에 실패합니다. 이러한 오류는 사용자 모드 표시 드라이버에 할당 이름을 바꾸거나 여러 버퍼링하는 것을 나타냅니다.
참고 비트 필드 삭제 플래그도 설정된 경우 DonotWait비트 필드 플래그는 메모리 관리자에 영향을 주지 않습니다.
 
메모리 관리자가 그래픽 하드웨어에서 할당을 사용하고 있는지 여부를 검사 필요가 없는 경우 사용자 모드 표시 드라이버는 D3DDDICB_LOCK Flags 멤버에서 IgnoreSync 비트 필드 플래그를 설정해야 합니다. 그러면 사용자 모드 표시 드라이버가 할당에 대한 액세스를 제대로 동기화해야 합니다. DonotWait 비트 필드 플래그가 IgnoreSync 비트 필드 플래그로 지정되지 않은 경우 메모리 관리자는 IgnoreSync 비트 필드 플래그를 무시합니다.
참고 무시 비트 필드 플래그도 설정된 경우 IgnoreSync비트 필드 플래그는 메모리 관리자에 영향을 주지 않습니다.
 
예제

다음 코드 예제에서는 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);

요구 사항

요구 사항
지원되는 최소 클라이언트 Windows Vista 이상 버전의 Windows 운영 체제에서 사용할 수 있습니다.
대상 플랫폼 데스크톱
머리글 d3dumddi.h(D3dumddi.h 포함)

추가 정보

D3D10DDIARG_CREATERESOURCE

D3D11DDIARG_CREATERESOURCE

D3DDDIARG_LOCK

D3DDDICB_LOCK

D3DDDI_DEVICECALLBACKS

잠금

ResourceMap

ResourceUnmap