15bd8deadSopenharmony_ciName 25bd8deadSopenharmony_ci 35bd8deadSopenharmony_ci WGL_NV_gpu_affinity 45bd8deadSopenharmony_ci 55bd8deadSopenharmony_ciName Strings 65bd8deadSopenharmony_ci 75bd8deadSopenharmony_ci WGL_NV_gpu_affinity 85bd8deadSopenharmony_ci 95bd8deadSopenharmony_ciContact 105bd8deadSopenharmony_ci 115bd8deadSopenharmony_ci Barthold Lichtenbelt, NVIDIA (blichtenbelt 'at' nvidia.com) 125bd8deadSopenharmony_ci 135bd8deadSopenharmony_ciNotice 145bd8deadSopenharmony_ci 155bd8deadSopenharmony_ci Copyright NVIDIA Corporation, 2005-2006. 165bd8deadSopenharmony_ci 175bd8deadSopenharmony_ciStatus 185bd8deadSopenharmony_ci 195bd8deadSopenharmony_ci Completed. 205bd8deadSopenharmony_ci 215bd8deadSopenharmony_ciVersion 225bd8deadSopenharmony_ci 235bd8deadSopenharmony_ci Last Modified Date: 11/08/2006 245bd8deadSopenharmony_ci Author revision: 11 255bd8deadSopenharmony_ci 265bd8deadSopenharmony_ciNumber 275bd8deadSopenharmony_ci 285bd8deadSopenharmony_ci 355 295bd8deadSopenharmony_ci 305bd8deadSopenharmony_ciDependencies 315bd8deadSopenharmony_ci 325bd8deadSopenharmony_ci WGL_ARB_extensions_string is required. 335bd8deadSopenharmony_ci 345bd8deadSopenharmony_ci This extension interacts with WGL_ARB_make_current_read. 355bd8deadSopenharmony_ci 365bd8deadSopenharmony_ci This extension interacts with WGL_ARB_pbuffer. 375bd8deadSopenharmony_ci 385bd8deadSopenharmony_ci This extension interacts with GL_EXT_framebuffer_object 395bd8deadSopenharmony_ci 405bd8deadSopenharmony_ciOverview 415bd8deadSopenharmony_ci 425bd8deadSopenharmony_ci On systems with more than one GPU it is desirable to be able to 435bd8deadSopenharmony_ci select which GPU(s) in the system become the target for OpenGL 445bd8deadSopenharmony_ci rendering commands. This extension introduces the concept of a GPU 455bd8deadSopenharmony_ci affinity mask. OpenGL rendering commands are directed to the 465bd8deadSopenharmony_ci GPU(s) specified by the affinity mask. GPU affinity is immutable. 475bd8deadSopenharmony_ci Once set, it cannot be changed. 485bd8deadSopenharmony_ci 495bd8deadSopenharmony_ci This extension also introduces the concept called affinity-DC. An 505bd8deadSopenharmony_ci affinity-DC is a device context with a GPU affinity mask embedded 515bd8deadSopenharmony_ci in it. This restricts the device context to only allow OpenGL 525bd8deadSopenharmony_ci commands to be sent to the GPU(s) in the affinity mask. 535bd8deadSopenharmony_ci 545bd8deadSopenharmony_ci Handles for the GPUs present in a system are enumerated with the 555bd8deadSopenharmony_ci command wglEnumGpusNV. An affinity-DC is created by calling 565bd8deadSopenharmony_ci wglCreateAffinityDCNV. This function takes a list of GPU handles, 575bd8deadSopenharmony_ci which make up the affinity mask. An affinity-DC can also 585bd8deadSopenharmony_ci indirectly be created by obtaining a DC from a pBuffer handle, by 595bd8deadSopenharmony_ci calling wglGetPbufferDC, which in turn was created from an 605bd8deadSopenharmony_ci affinity-DC by calling wglCreatePbuffer. 615bd8deadSopenharmony_ci 625bd8deadSopenharmony_ci A context created from an affinity DC will inherit the GPU 635bd8deadSopenharmony_ci affinity mask from the DC. Once inherited, it cannot be changed. 645bd8deadSopenharmony_ci Such a context is called an affinity-context. This restricts the 655bd8deadSopenharmony_ci affinity-context to only allow OpenGL commands to be sent to those 665bd8deadSopenharmony_ci GPU(s) in its affinity mask. Once created, this context can be 675bd8deadSopenharmony_ci used in two ways: 685bd8deadSopenharmony_ci 695bd8deadSopenharmony_ci 1. Make the affinity-context current to an affinity-DC. This 705bd8deadSopenharmony_ci will only succeed if the context's affinity mask is the same 715bd8deadSopenharmony_ci as the affinity mask in the DC. There is no window 725bd8deadSopenharmony_ci associated with an affinity DC, therefore this is a way to 735bd8deadSopenharmony_ci achieve off-screen rendering to an OpenGL context. This can 745bd8deadSopenharmony_ci either be rendering to a pBuffer, or an application created 755bd8deadSopenharmony_ci framebuffer object. In the former case, the affinity-mask of 765bd8deadSopenharmony_ci the pBuffer DC, which is obtained from a pBuffer handle, 775bd8deadSopenharmony_ci will be the same affinity-mask as the DC used to created the 785bd8deadSopenharmony_ci pBuffer handle. In the latter case, the default framebuffer 795bd8deadSopenharmony_ci object will be incomplete because there is no window-system 805bd8deadSopenharmony_ci created framebuffer. Therefore, the application will have to 815bd8deadSopenharmony_ci create and bind a framebuffer object as the target for 825bd8deadSopenharmony_ci rendering. 835bd8deadSopenharmony_ci 2. Make the affinity-context current to a DC obtained from a 845bd8deadSopenharmony_ci window. Rendering only happens to the sub rectangles(s) of 855bd8deadSopenharmony_ci the window that overlap the parts of the desktop that are 865bd8deadSopenharmony_ci displayed by the GPU(s) in the affinity mask of the context. 875bd8deadSopenharmony_ci 885bd8deadSopenharmony_ci Sharing OpenGL objects between affinity-contexts, by calling 895bd8deadSopenharmony_ci wglShareLists, will only succeed if the contexts have identical 905bd8deadSopenharmony_ci affinity masks. 915bd8deadSopenharmony_ci 925bd8deadSopenharmony_ci It is not possible to make a regular context (one without an 935bd8deadSopenharmony_ci affinity mask) current to an affinity-DC. This would mean a way 945bd8deadSopenharmony_ci for a context to inherit affinity information, which makes the 955bd8deadSopenharmony_ci context affinity mutable, which is counter to the premise of this 965bd8deadSopenharmony_ci extension. 975bd8deadSopenharmony_ci 985bd8deadSopenharmony_ciNew Procedures, Functions and Structures: 995bd8deadSopenharmony_ci 1005bd8deadSopenharmony_ci DECLARE_HANDLE(HGPUNV); 1015bd8deadSopenharmony_ci 1025bd8deadSopenharmony_ci typedef struct _GPU_DEVICE { 1035bd8deadSopenharmony_ci DWORD cb; 1045bd8deadSopenharmony_ci CHAR DeviceName[32]; 1055bd8deadSopenharmony_ci CHAR DeviceString[128]; 1065bd8deadSopenharmony_ci DWORD Flags; 1075bd8deadSopenharmony_ci RECT rcVirtualScreen; 1085bd8deadSopenharmony_ci } GPU_DEVICE, *PGPU_DEVICE; 1095bd8deadSopenharmony_ci 1105bd8deadSopenharmony_ci BOOL wglEnumGpusNV(UINT iGpuIndex, 1115bd8deadSopenharmony_ci HGPUNV *phGpu); 1125bd8deadSopenharmony_ci 1135bd8deadSopenharmony_ci BOOL wglEnumGpuDevicesNV(HGPUNV hGpu, 1145bd8deadSopenharmony_ci UINT iDeviceIndex, 1155bd8deadSopenharmony_ci PGPU_DEVICE lpGpuDevice); 1165bd8deadSopenharmony_ci 1175bd8deadSopenharmony_ci HDC wglCreateAffinityDCNV(const HGPUNV *phGpuList); 1185bd8deadSopenharmony_ci 1195bd8deadSopenharmony_ci BOOL wglEnumGpusFromAffinityDCNV(HDC hAffinityDC, 1205bd8deadSopenharmony_ci UINT iGpuIndex, 1215bd8deadSopenharmony_ci HGPUNV *hGpu); 1225bd8deadSopenharmony_ci 1235bd8deadSopenharmony_ci BOOL wglDeleteDCNV(HDC hdc); 1245bd8deadSopenharmony_ci 1255bd8deadSopenharmony_ciNew Tokens 1265bd8deadSopenharmony_ci 1275bd8deadSopenharmony_ci New error codes set by wglShareLists, wglMakeCurrent and 1285bd8deadSopenharmony_ci wglMakeContextCurrentARB: 1295bd8deadSopenharmony_ci 1305bd8deadSopenharmony_ci ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 1315bd8deadSopenharmony_ci 1325bd8deadSopenharmony_ci New error codes set by wglMakeCurrent and 1335bd8deadSopenharmony_ci wglMakeContextCurrentARB: 1345bd8deadSopenharmony_ci 1355bd8deadSopenharmony_ci ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 1365bd8deadSopenharmony_ci 1375bd8deadSopenharmony_ciAdditions to the WGL Specification 1385bd8deadSopenharmony_ci 1395bd8deadSopenharmony_ci GPU Affinity 1405bd8deadSopenharmony_ci 1415bd8deadSopenharmony_ci To query handles for all GPUs in a system call: 1425bd8deadSopenharmony_ci 1435bd8deadSopenharmony_ci BOOL wglEnumGpusNV(UINT iGpuIndex, HGPUNV *phGPU); 1445bd8deadSopenharmony_ci 1455bd8deadSopenharmony_ci <iGpuIndex> is an index value that specifies a GPU. 1465bd8deadSopenharmony_ci 1475bd8deadSopenharmony_ci <phGPU> upon return will contain a handle for GPU number 1485bd8deadSopenharmony_ci <iGpuIndex>. The first GPU will be index 0. 1495bd8deadSopenharmony_ci 1505bd8deadSopenharmony_ci By looping over wglEnumGpusNV and incrementing <iGpuIndex>, 1515bd8deadSopenharmony_ci starting at index 0, all GPU handles can be queried. If the 1525bd8deadSopenharmony_ci function succeeds, the return value is TRUE. If the function 1535bd8deadSopenharmony_ci fails, the return value is FALSE and <phGPU> will be unmodified. 1545bd8deadSopenharmony_ci The function fails if <iGpuIndex> is greater or equal than the 1555bd8deadSopenharmony_ci number of GPUs supported by the system. 1565bd8deadSopenharmony_ci 1575bd8deadSopenharmony_ci To retrieve information about the display devices supported by a 1585bd8deadSopenharmony_ci GPU call: 1595bd8deadSopenharmony_ci 1605bd8deadSopenharmony_ci BOOL wglEnumGpuDevicesNV(HGPUNV hGpu, 1615bd8deadSopenharmony_ci UINT iDeviceIndex, 1625bd8deadSopenharmony_ci PGPU_DEVICE lpGpuDevice); 1635bd8deadSopenharmony_ci 1645bd8deadSopenharmony_ci <hGpu> is a handle to the GPU to query. 1655bd8deadSopenharmony_ci 1665bd8deadSopenharmony_ci <iDeviceIndex> is an index value that specifies a display device, 1675bd8deadSopenharmony_ci supported by <hGpu>, to query. The first display device will be 1685bd8deadSopenharmony_ci index 0. 1695bd8deadSopenharmony_ci 1705bd8deadSopenharmony_ci <lpGpuDevice> pointer to a GPU_DEVICE structure which will receive 1715bd8deadSopenharmony_ci information about the display device at index <iDeviceIndex>. 1725bd8deadSopenharmony_ci 1735bd8deadSopenharmony_ci By looping over the function wglEnumGpuDevicesNV and incrementing 1745bd8deadSopenharmony_ci <iDeviceIndex>, starting at index 0, all display devices can be 1755bd8deadSopenharmony_ci queried. If the function succeeds, the return value is TRUE. If 1765bd8deadSopenharmony_ci the function fails, the return value is FALSE and <lpGpuDevice> 1775bd8deadSopenharmony_ci will be unmodified. The function fails if <iDeviceIndex> is 1785bd8deadSopenharmony_ci greater or equal than the number of display devices supported by 1795bd8deadSopenharmony_ci <hGpu>. 1805bd8deadSopenharmony_ci 1815bd8deadSopenharmony_ci The GPU_DEVICE structure has the following members: 1825bd8deadSopenharmony_ci 1835bd8deadSopenharmony_ci typedef struct _GPU_DEVICE { 1845bd8deadSopenharmony_ci DWORD cb; 1855bd8deadSopenharmony_ci CHAR DeviceName[32]; 1865bd8deadSopenharmony_ci CHAR DeviceString[128]; 1875bd8deadSopenharmony_ci DWORD Flags; 1885bd8deadSopenharmony_ci RECT rcVirtualScreen; 1895bd8deadSopenharmony_ci } GPU_DEVICE, *PGPU_DEVICE; 1905bd8deadSopenharmony_ci 1915bd8deadSopenharmony_ci <cb> is the size of the GPU_DEVICE structure. Before calling 1925bd8deadSopenharmony_ci wglEnumGpuDevicesNV, set <cb> to the size, in bytes, of 1935bd8deadSopenharmony_ci GPU_DEVICE. 1945bd8deadSopenharmony_ci 1955bd8deadSopenharmony_ci <DeviceName> is a string identifying the display device name. This 1965bd8deadSopenharmony_ci will be the same string as stored in the <DeviceName> field of the 1975bd8deadSopenharmony_ci DISPLAY_DEVICE structure, which is filled in by 1985bd8deadSopenharmony_ci EnumDisplayDevices. 1995bd8deadSopenharmony_ci 2005bd8deadSopenharmony_ci <DeviceString> is a string describing the GPU for this display 2015bd8deadSopenharmony_ci device. It is the same string as stored in the <DeviceString> 2025bd8deadSopenharmony_ci field in the DISPLAY_DEVICE structure that is filled in by 2035bd8deadSopenharmony_ci EnumDisplayDevices when it describes a display adapter (and not a 2045bd8deadSopenharmony_ci monitor). 2055bd8deadSopenharmony_ci 2065bd8deadSopenharmony_ci <Flags> Indicates the state of the display device. It can be a 2075bd8deadSopenharmony_ci combination of any of the following: 2085bd8deadSopenharmony_ci 2095bd8deadSopenharmony_ci DISPLAY_DEVICE_ATTACHED_TO_DESKTOP If set, the device is part 2105bd8deadSopenharmony_ci of the desktop. 2115bd8deadSopenharmony_ci 2125bd8deadSopenharmony_ci DISPLAY_DEVICE_PRIMARY_DEVICE If set, the primary 2135bd8deadSopenharmony_ci desktop is on this device. Only one device in the system can have 2145bd8deadSopenharmony_ci this set. 2155bd8deadSopenharmony_ci 2165bd8deadSopenharmony_ci <rcVirtualScreen> specifies the display device rectangle, in 2175bd8deadSopenharmony_ci virtual screen coordinates. The value of <rcVirtualScreen> is 2185bd8deadSopenharmony_ci undefined if the device is not part of the desktop, i.e. 2195bd8deadSopenharmony_ci DISPLAY_DEVICE_ATTACHED_TO_DESKTOP is not set in the <Flags> 2205bd8deadSopenharmony_ci field. 2215bd8deadSopenharmony_ci 2225bd8deadSopenharmony_ci The function wglEnumGpuDevicesNV can fail for a variety of 2235bd8deadSopenharmony_ci reasons. Call GetLastError to get extended error information. 2245bd8deadSopenharmony_ci Possible errors are as follows: 2255bd8deadSopenharmony_ci 2265bd8deadSopenharmony_ci ERROR_INVALID_HANDLE <hGpu> is not a valid GPU handle. 2275bd8deadSopenharmony_ci 2285bd8deadSopenharmony_ci A new type of DC, called an affinity-DC, can be used to direct 2295bd8deadSopenharmony_ci OpenGL commands to a specific GPU or set of GPUs. An affinity-DC 2305bd8deadSopenharmony_ci is a device context with a GPU affinity mask embedded in it. This 2315bd8deadSopenharmony_ci restricts the device context to only allow OpenGL commands to be 2325bd8deadSopenharmony_ci sent to the GPU(s) in the affinity mask. An affinity-DC can be 2335bd8deadSopenharmony_ci created directly, using the new function wglCreateAffinityDCNV and 2345bd8deadSopenharmony_ci also indirectly by calling wglCreatePbufferARB followed by 2355bd8deadSopenharmony_ci wglGetPbufferDCARB. To create an affinity-DC directly call: 2365bd8deadSopenharmony_ci 2375bd8deadSopenharmony_ci HDC wglCreateAffinityDCNV(const HGPUNV *phGpuList); 2385bd8deadSopenharmony_ci 2395bd8deadSopenharmony_ci <phGpuList> is a NULL-terminated array of GPU handles to which the 2405bd8deadSopenharmony_ci affinity-DC will be restricted. If an element in the list is not a 2415bd8deadSopenharmony_ci GPU handle, as returned by wglEnumGpusNV, it is silently ignored. 2425bd8deadSopenharmony_ci 2435bd8deadSopenharmony_ci If successful, the function returns an affinity-DC. If it fails, 2445bd8deadSopenharmony_ci NULL will be returned. 2455bd8deadSopenharmony_ci 2465bd8deadSopenharmony_ci To create an affinity-DC indirectly, first call 2475bd8deadSopenharmony_ci wglCreatePbufferARB passing it an affinity-DC. Next, pass the 2485bd8deadSopenharmony_ci handle returned by the call to wglCreatePbufferARB to 2495bd8deadSopenharmony_ci wglGetPbufferDCARB to create an affinity-DC for the pBuffer. The 2505bd8deadSopenharmony_ci DC returned by wglGetPbufferDCARB will have the same affinity mask 2515bd8deadSopenharmony_ci as the DC used to create the pBuffer handle by calling 2525bd8deadSopenharmony_ci wglCreatePbufferARB. 2535bd8deadSopenharmony_ci 2545bd8deadSopenharmony_ci An affinity-DC has no window associated with it, and therefore it 2555bd8deadSopenharmony_ci has no default window-system-provided framebuffer. (Note: This is 2565bd8deadSopenharmony_ci terminology borrowed from EXT_framebuffer_object). A context made 2575bd8deadSopenharmony_ci current to an affinity-DC will only be able to render into an 2585bd8deadSopenharmony_ci application-created framebuffer object, or a pBuffer. The default 2595bd8deadSopenharmony_ci window-system-framebuffer object, when bound, will be incomplete. 2605bd8deadSopenharmony_ci The EXT_framebuffer_object specification defines what 'incomplete' 2615bd8deadSopenharmony_ci means exactly. 2625bd8deadSopenharmony_ci 2635bd8deadSopenharmony_ci A context created from an affinity-DC, by calling wglCreateContext 2645bd8deadSopenharmony_ci and passing it an affinity-DC, is called an affinity-context. This 2655bd8deadSopenharmony_ci context will inherit the affinity mask from the DC. This affinity- 2665bd8deadSopenharmony_ci mask cannot be changed. The affinity mask restricts the affinity- 2675bd8deadSopenharmony_ci context to only allow OpenGL commands to be sent to those GPU(s) 2685bd8deadSopenharmony_ci in its affinity mask. 2695bd8deadSopenharmony_ci 2705bd8deadSopenharmony_ci The function wglCreateAffinityDCNV can fail for a variety of 2715bd8deadSopenharmony_ci reasons. Call GetLastError to get extended error information. 2725bd8deadSopenharmony_ci Possible errors are as follows: 2735bd8deadSopenharmony_ci 2745bd8deadSopenharmony_ci ERROR_NO_SYSTEM_RESOURCES Insufficient resources exist to 2755bd8deadSopenharmony_ci create the affinity-DC. 2765bd8deadSopenharmony_ci 2775bd8deadSopenharmony_ci ERROR_INVALID_DATA <phGpuList> is empty or contains no 2785bd8deadSopenharmony_ci valid GPU handles 2795bd8deadSopenharmony_ci 2805bd8deadSopenharmony_ci An affinity-context can only be made current to an affinity-DC 2815bd8deadSopenharmony_ci with the same affinity-mask, otherwise wglMakeCurrent and 2825bd8deadSopenharmony_ci wglMakeContextCurrentARB will fail and return FALSE. In the case 2835bd8deadSopenharmony_ci of wglMakeContextCurrentARB, the affinity masks of both the "read" 2845bd8deadSopenharmony_ci and "draw" DCs need to match the affinity-mask of the context. 2855bd8deadSopenharmony_ci 2865bd8deadSopenharmony_ci If a context that has no affinity mask is made current to an 2875bd8deadSopenharmony_ci affinity-DC, wglMakeCurrent and wglMakeContextCurrentARB will fail 2885bd8deadSopenharmony_ci and return FALSE. In the case of wglMakeContextCurrentARB it will 2895bd8deadSopenharmony_ci fail if either the "read" or "draw" DC is an affinity-DC. 2905bd8deadSopenharmony_ci 2915bd8deadSopenharmony_ci If an affinity-context is made current to a DC obtained from a 2925bd8deadSopenharmony_ci window, by calling GetDC, then rendering will only happen to the 2935bd8deadSopenharmony_ci subrectangle(s) of the window that overlap the parts of the 2945bd8deadSopenharmony_ci desktop that are displayed by the GPU(s) in the affinity-mask of 2955bd8deadSopenharmony_ci the context. Note that a DC obtained from a window does not have 2965bd8deadSopenharmony_ci an affinity mask set. 2975bd8deadSopenharmony_ci 2985bd8deadSopenharmony_ci The following error codes are added to the description of 2995bd8deadSopenharmony_ci wglMakeCurrent and wglMakeContextCurrentARB: 3005bd8deadSopenharmony_ci 3015bd8deadSopenharmony_ci ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV The device context(s) and 3025bd8deadSopenharmony_ci rendering context have non-matching affinity masks. 3035bd8deadSopenharmony_ci 3045bd8deadSopenharmony_ci ERROR_MISSING_AFFINITY_MASK_NV The rendering context does 3055bd8deadSopenharmony_ci not have an affinity mask set. 3065bd8deadSopenharmony_ci 3075bd8deadSopenharmony_ci Sharing OpenGL objects between affinity-contexts, by calling 3085bd8deadSopenharmony_ci wglShareLists, will only succeed if the contexts have identical 3095bd8deadSopenharmony_ci affinity masks. The following error codes are added to the 3105bd8deadSopenharmony_ci description of wglShareLists: 3115bd8deadSopenharmony_ci 3125bd8deadSopenharmony_ci ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV The contexts have non- 3135bd8deadSopenharmony_ci matching affinity masks. 3145bd8deadSopenharmony_ci 3155bd8deadSopenharmony_ci To delete an affinity-DC call: 3165bd8deadSopenharmony_ci 3175bd8deadSopenharmony_ci BOOL wglDeleteDCNV(HDC hdc) 3185bd8deadSopenharmony_ci 3195bd8deadSopenharmony_ci <hdc> Is a handle of an affinity-DC to delete. 3205bd8deadSopenharmony_ci 3215bd8deadSopenharmony_ci If the function succeeds, TRUE is returned. If the function fails, 3225bd8deadSopenharmony_ci FALSE is returned. Call GetLastError to get extended error 3235bd8deadSopenharmony_ci information. Possible errors are as follows: 3245bd8deadSopenharmony_ci 3255bd8deadSopenharmony_ci ERROR_INVALID_HANDLE <hdc> is not a handle of an affinity-DC. 3265bd8deadSopenharmony_ci 3275bd8deadSopenharmony_ci To retrieve a list of GPU handles that make up the affinity-mask 3285bd8deadSopenharmony_ci of an affinity-DC, call: 3295bd8deadSopenharmony_ci 3305bd8deadSopenharmony_ci BOOL wglEnumGpusFromAffinityDCNV(HDC hAffinityDC, 3315bd8deadSopenharmony_ci UINT iGpuIndex, 3325bd8deadSopenharmony_ci HGPUNV *phGpu); 3335bd8deadSopenharmony_ci 3345bd8deadSopenharmony_ci <hAffinityDC> is a handle of the affinity-DC to query. 3355bd8deadSopenharmony_ci 3365bd8deadSopenharmony_ci <iGpuIndex> is an index value of the GPU handle in the affinity 3375bd8deadSopenharmony_ci mask of <hAffinityDC> to query. 3385bd8deadSopenharmony_ci 3395bd8deadSopenharmony_ci <phGpu> upon return will contain a handle for GPU number 3405bd8deadSopenharmony_ci <iGpuIndex>. The first GPU will be at index 0. 3415bd8deadSopenharmony_ci 3425bd8deadSopenharmony_ci By looping over wglEnumGpusFromAffinityDCNV and incrementing 3435bd8deadSopenharmony_ci <iGpuIndex>, starting at index 0, all GPU handles associated with 3445bd8deadSopenharmony_ci the DC can be queried. If the function succeeds, the return value 3455bd8deadSopenharmony_ci is TRUE. If the function fails, the return value is FALSE and 3465bd8deadSopenharmony_ci <phGPU> will be unmodified. The function fails if <iGpuIndex> is 3475bd8deadSopenharmony_ci greater or equal than the number of GPUs associated with 3485bd8deadSopenharmony_ci <hAffinityDC>. 3495bd8deadSopenharmony_ci 3505bd8deadSopenharmony_ci Call GetLastError to get extended error information. Possible 3515bd8deadSopenharmony_ci errors are as follows: 3525bd8deadSopenharmony_ci 3535bd8deadSopenharmony_ci ERROR_INVALID_HANDLE <hAffinityDC> is not a handle of an 3545bd8deadSopenharmony_ci affinity-DC. 3555bd8deadSopenharmony_ci 3565bd8deadSopenharmony_ciInteractions with WGL_ARB_make_current_read 3575bd8deadSopenharmony_ci 3585bd8deadSopenharmony_ci If the make current read extension is not supported, all language 3595bd8deadSopenharmony_ci referring to wglMakeContextCurrentARB is deleted. 3605bd8deadSopenharmony_ci 3615bd8deadSopenharmony_ciInteractions with WGL_ARB_pbuffer 3625bd8deadSopenharmony_ci 3635bd8deadSopenharmony_ci If the pbuffer extension is not supported, all language referring 3645bd8deadSopenharmony_ci to puffers, wglGetPbuferDC and wglCreatePbuffer are deleted. 3655bd8deadSopenharmony_ci 3665bd8deadSopenharmony_ciInteractions with GL_EXT_framebuffer_object 3675bd8deadSopenharmony_ci 3685bd8deadSopenharmony_ci If the framebuffer object extension is not supported, all language 3695bd8deadSopenharmony_ci referring to framebuffer objects is deleted. 3705bd8deadSopenharmony_ci 3715bd8deadSopenharmony_ciUsage examples 3725bd8deadSopenharmony_ci 3735bd8deadSopenharmony_ci // Example 1 - Normal window creation, DC setup and 3745bd8deadSopenharmony_ci // context creation. 3755bd8deadSopenharmony_ci 3765bd8deadSopenharmony_ci PIXELFORMATDESCRIPTOR pfd; 3775bd8deadSopenharmony_ci int pf; 3785bd8deadSopenharmony_ci HDC hDC; 3795bd8deadSopenharmony_ci HGLRC hRC; 3805bd8deadSopenharmony_ci HWND hWnd; 3815bd8deadSopenharmony_ci 3825bd8deadSopenharmony_ci hWnd = CreateWindow(...); 3835bd8deadSopenharmony_ci hDC = GetDC(hWnd); 3845bd8deadSopenharmony_ci 3855bd8deadSopenharmony_ci memset(&pfd, 0, sizeof(pfd)); 3865bd8deadSopenharmony_ci pfd.nSize = sizeof(pfd); 3875bd8deadSopenharmony_ci pfd.nVersion = 1; 3885bd8deadSopenharmony_ci pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; 3895bd8deadSopenharmony_ci pfd.iPixelType = PFD_TYPE_RGBA; 3905bd8deadSopenharmony_ci pfd.cColorBits = 32; 3915bd8deadSopenharmony_ci 3925bd8deadSopenharmony_ci // Note, for ease of code reading no error checking is done. 3935bd8deadSopenharmony_ci pf = ChoosePixelFormat(hDC, &pfd); 3945bd8deadSopenharmony_ci SetPixelFormat(hDC, pf, &pfd); 3955bd8deadSopenharmony_ci DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), 3965bd8deadSopenharmony_ci &pfd); 3975bd8deadSopenharmony_ci 3985bd8deadSopenharmony_ci hRC = wglCreateContext(hDC); 3995bd8deadSopenharmony_ci wglMakeCurrent(hDC, hRC); 4005bd8deadSopenharmony_ci 4015bd8deadSopenharmony_ci 4025bd8deadSopenharmony_ci // Example 2 - Offscreen rendering to one GPU using a FBO 4035bd8deadSopenharmony_ci // It is assumed that a context already has been created (and 4045bd8deadSopenharmony_ci // possibly destroyed) and was used to query the proc addresses 4055bd8deadSopenharmony_ci // of the WGL affinity related entrypoints. 4065bd8deadSopenharmony_ci 4075bd8deadSopenharmony_ci #define MAX_GPU 4 4085bd8deadSopenharmony_ci 4095bd8deadSopenharmony_ci PIXELFORMATDESCRIPTOR pfd; 4105bd8deadSopenharmony_ci int pf, gpuIndex = 0; 4115bd8deadSopenharmony_ci HGPUNV hGPU[MAX_GPU]; 4125bd8deadSopenharmony_ci HGPUNV GpuMask[MAX_GPU]; 4135bd8deadSopenharmony_ci HDC affDC; 4145bd8deadSopenharmony_ci HGLRC affRC; 4155bd8deadSopenharmony_ci 4165bd8deadSopenharmony_ci // Get a list of the first MAX_GPU GPUs in the system 4175bd8deadSopenharmony_ci while ((gpuIndex < MAX_GPU) && wglEnumGpusNV(gpuIndex, 4185bd8deadSopenharmony_ci &hGPU[gpuIndex])) { 4195bd8deadSopenharmony_ci gpuIndex++; 4205bd8deadSopenharmony_ci } 4215bd8deadSopenharmony_ci 4225bd8deadSopenharmony_ci // Create an affinity-DC associated with the first GPU 4235bd8deadSopenharmony_ci GpuMask[0] = hGPU[0]; 4245bd8deadSopenharmony_ci GpuMask[1] = NULL; 4255bd8deadSopenharmony_ci 4265bd8deadSopenharmony_ci affDC = wglCreateAffinityDCNV(GpuMask); 4275bd8deadSopenharmony_ci 4285bd8deadSopenharmony_ci // Set a pixelformat on the affinity-DC 4295bd8deadSopenharmony_ci pf = ChoosePixelFormat(affDC, &pfd); 4305bd8deadSopenharmony_ci SetPixelFormat(affDC, pf, &pfd); 4315bd8deadSopenharmony_ci DescribePixelFormat(affDC, pf, sizeof(PIXELFORMATDESCRIPTOR), 4325bd8deadSopenharmony_ci &pfd); 4335bd8deadSopenharmony_ci 4345bd8deadSopenharmony_ci affRC = wglCreateContext(affDC); 4355bd8deadSopenharmony_ci wglMakeCurrent(affDC, affRC); 4365bd8deadSopenharmony_ci 4375bd8deadSopenharmony_ci // Make a previously created FBO current so we have something 4385bd8deadSopenharmony_ci // to render into. Since there's no window, the default system 4395bd8deadSopenharmony_ci // created FBO is incomplete. 4405bd8deadSopenharmony_ci glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb); 4415bd8deadSopenharmony_ci 4425bd8deadSopenharmony_ci <Now draw> 4435bd8deadSopenharmony_ci 4445bd8deadSopenharmony_ci // Example 3 - Offscreen rendering to one GPU using a pBuffer 4455bd8deadSopenharmony_ci // It is assumed that a context already has been created (and 4465bd8deadSopenharmony_ci // possibly destroyed) and was used to query the proc addresses 4475bd8deadSopenharmony_ci // of the WGL affinity and pbuffer related entrypoints. 4485bd8deadSopenharmony_ci 4495bd8deadSopenharmony_ci #define MAX_GPU 4 4505bd8deadSopenharmony_ci 4515bd8deadSopenharmony_ci int gpuIndex = 0; 4525bd8deadSopenharmony_ci HGPUNV hGPU[MAX_GPU]; 4535bd8deadSopenharmony_ci HGPUNV GpuMask[MAX_GPU]; 4545bd8deadSopenharmony_ci HDC affDC, pBufferAffDC; 4555bd8deadSopenharmony_ci HGLRC affRC; 4565bd8deadSopenharmony_ci 4575bd8deadSopenharmony_ci // Get a list of the first MAX_GPU GPUs in the system 4585bd8deadSopenharmony_ci while ((gpuIndex < MAX_GPU) && wglEnumGpusNV(gpuIndex, 4595bd8deadSopenharmony_ci &hGPU[gpuIndex])) { 4605bd8deadSopenharmony_ci gpuIndex++; 4615bd8deadSopenharmony_ci } 4625bd8deadSopenharmony_ci 4635bd8deadSopenharmony_ci // Create an affinity-DC associated with the first GPU 4645bd8deadSopenharmony_ci GpuMask[0] = hGPU[0]; 4655bd8deadSopenharmony_ci GpuMask[1] = NULL; 4665bd8deadSopenharmony_ci 4675bd8deadSopenharmony_ci affDC = wglCreateAffinityDCNV(GpuMask); 4685bd8deadSopenharmony_ci 4695bd8deadSopenharmony_ci // Setup desired pixelformat attributes for the pbuffer 4705bd8deadSopenharmony_ci // including WGL_DRAW_TO_PBUFFER_ARB. 4715bd8deadSopenharmony_ci HPBUFFERARB handle; 4725bd8deadSopenharmony_ci int width = 512, height = 512, format = 0; 4735bd8deadSopenharmony_ci unsigned int nformats; 4745bd8deadSopenharmony_ci 4755bd8deadSopenharmony_ci int attribList[] = 4765bd8deadSopenharmony_ci { 4775bd8deadSopenharmony_ci WGL_RED_BITS_ARB, 8, 4785bd8deadSopenharmony_ci WGL_GREEN_BITS_ARB, 8, 4795bd8deadSopenharmony_ci WGL_BLUE_BITS_ARB, 8, 4805bd8deadSopenharmony_ci WGL_ALPHA_BITS_ARB, 8, 4815bd8deadSopenharmony_ci WGL_STENCIL_BITS_ARB, 0, 4825bd8deadSopenharmony_ci WGL_DEPTH_BITS_ARB, 0, 4835bd8deadSopenharmony_ci WGL_DRAW_TO_PBUFFER_ARB, true, 4845bd8deadSopenharmony_ci 0, 4855bd8deadSopenharmony_ci }; 4865bd8deadSopenharmony_ci 4875bd8deadSopenharmony_ci wglChoosePixelFormatARB(affDC, attribList, NULL, 1, 4885bd8deadSopenharmony_ci &format, &nformats); 4895bd8deadSopenharmony_ci 4905bd8deadSopenharmony_ci handle = wglCreatePbufferARB(affDC, format, width, height, NULL); 4915bd8deadSopenharmony_ci 4925bd8deadSopenharmony_ci // pbufferAffDC will have the same affinity-mask as affDC. 4935bd8deadSopenharmony_ci pBufferAffDC = wglGetPbufferDCARB(handle); 4945bd8deadSopenharmony_ci 4955bd8deadSopenharmony_ci // affRC will inherit the affinity-mask from pBufferAffDC. 4965bd8deadSopenharmony_ci affRC = wglCreateContext(pBufferAffDC); 4975bd8deadSopenharmony_ci wglMakeCurrent(pBufferAffDC, affRC); 4985bd8deadSopenharmony_ci 4995bd8deadSopenharmony_ci <Now draw into the pBuffer> 5005bd8deadSopenharmony_ci 5015bd8deadSopenharmony_ciIssues 5025bd8deadSopenharmony_ci 5035bd8deadSopenharmony_ci 1) Do we really need an affinity-DC, or can we do with just an 5045bd8deadSopenharmony_ci affinity context? 5055bd8deadSopenharmony_ci 5065bd8deadSopenharmony_ci DISCUSSION: If affinity is not part of a DC, a new function will 5075bd8deadSopenharmony_ci need to be defined to create an affinity-context or set an 5085bd8deadSopenharmony_ci affinity-mask for an existing context. Passing NULL as a HDC to 5095bd8deadSopenharmony_ci wglMakeCurrent will then be one way to create an off-screen 5105bd8deadSopenharmony_ci rendering context, where rendering will have to go to a FBO. If 5115bd8deadSopenharmony_ci the HDC passed to wglMakeCurrent is one for a pBuffer, the 5125bd8deadSopenharmony_ci affinity-mask in the affinity-context dictates where rendering is 5135bd8deadSopenharmony_ci direct to. This might mean pBuffer resources will have to move, or 5145bd8deadSopenharmony_ci alternatively, duplicated across all GPUs in a system. That is 5155bd8deadSopenharmony_ci counter to the whole idea of this extension. Thus an affinity-DC 5165bd8deadSopenharmony_ci is definitely needed for a pBuffer. 5175bd8deadSopenharmony_ci 5185bd8deadSopenharmony_ci Thus the question reduces to, do we need an affinity-DC in order 5195bd8deadSopenharmony_ci to facilitate off-screen rendering to a FBO? Having an affinity-DC 5205bd8deadSopenharmony_ci has the following advantages: 5215bd8deadSopenharmony_ci 5225bd8deadSopenharmony_ci a) It is consistent with making current to a pBuffer or window, 5235bd8deadSopenharmony_ci that does need a DC. 5245bd8deadSopenharmony_ci b) passing NULL as a HDC to wglMakeCurrent might be filtered out 5255bd8deadSopenharmony_ci by the MS layer on future OSes. 5265bd8deadSopenharmony_ci c) The driver implementation might benefit from knowing at DC 5275bd8deadSopenharmony_ci creation time what the affinity-mask is, rather than at 5285bd8deadSopenharmony_ci wglMakeCurrent time. 5295bd8deadSopenharmony_ci 5305bd8deadSopenharmony_ci RESOLUTION: Yes. 5315bd8deadSopenharmony_ci 5325bd8deadSopenharmony_ci 2) Should the GPU affinity concept also apply to D3D and/or GDI 5335bd8deadSopenharmony_ci commands? 5345bd8deadSopenharmony_ci 5355bd8deadSopenharmony_ci DISCUSSION: It could be especially desirable to apply the 5365bd8deadSopenharmony_ci affinity concept to D3D. However, D3D is sufficiently different 5375bd8deadSopenharmony_ci that this extension doesn't directly apply. 5385bd8deadSopenharmony_ci 5395bd8deadSopenharmony_ci RESOLUTION: That falls outside this extension. 5405bd8deadSopenharmony_ci 5415bd8deadSopenharmony_ci 3) Should setting a pixelformat on an affinity-DC be required? 5425bd8deadSopenharmony_ci 5435bd8deadSopenharmony_ci DISCUSSION: Setting a pixelformat on an affinity-DC is not 5445bd8deadSopenharmony_ci strictly necessary if the application does off-screen rendering to 5455bd8deadSopenharmony_ci a FBO. However, the Microsoft layer of wglMakeCurrent requires 5465bd8deadSopenharmony_ci that the pixelformats of the DC and RC passed to it match. This 5475bd8deadSopenharmony_ci becomes an issue when making an affinity-context current to a DC 5485bd8deadSopenharmony_ci obtained from a window. The DC has a pixelformat set by the 5495bd8deadSopenharmony_ci application, and therefore the affinity-context needs to have the 5505bd8deadSopenharmony_ci same pixelformat. This means the affinity-DC, that the affinity- 5515bd8deadSopenharmony_ci context is created from, needs to have the same pixelformat set. 5525bd8deadSopenharmony_ci 5535bd8deadSopenharmony_ci RESOLUTION: YES. Setting a pixelformat on an affinity-DC is 5545bd8deadSopenharmony_ci required. 5555bd8deadSopenharmony_ci 5565bd8deadSopenharmony_ci 4) Is it allowed to make an affinity-context current to an 5575bd8deadSopenharmony_ci affinity-DC where the mask of the context spans more GPUs than the 5585bd8deadSopenharmony_ci mask in the DC? 5595bd8deadSopenharmony_ci 5605bd8deadSopenharmony_ci 5) Is it allowed to make an affinity-context current to an 5615bd8deadSopenharmony_ci affinity-DC where the mask of the context spans less GPUs than the 5625bd8deadSopenharmony_ci mask in the DC? 5635bd8deadSopenharmony_ci 5645bd8deadSopenharmony_ci DISCUSSION: Issues 4 and 5 are lumped together in this discussion. 5655bd8deadSopenharmony_ci For example, is this scenario something we want to support: An 5665bd8deadSopenharmony_ci application wants to share objects across two contexts and have 5675bd8deadSopenharmony_ci these two contexts each render to a different GPU. It can do this 5685bd8deadSopenharmony_ci by creating two affinity-DCs. One has an affinity mask for the 5695bd8deadSopenharmony_ci first GPU, the other for the second GPU. It also creates two 5705bd8deadSopenharmony_ci affinity-contexts that both have an affinity-mask that spans both 5715bd8deadSopenharmony_ci GPUs. Making one context current to the first affinity-DC will 5725bd8deadSopenharmony_ci lock the context to the GPU in the mask of that affinity-DC. Make 5735bd8deadSopenharmony_ci another context current to the second affinity-DC will lock that 5745bd8deadSopenharmony_ci context to the second GPU. This is effectively what issue 4) is 5755bd8deadSopenharmony_ci asking. . The simplest solution is to disallow these cases, and 5765bd8deadSopenharmony_ci that is how the spec is currently written. 5775bd8deadSopenharmony_ci 5785bd8deadSopenharmony_ci RESOLUTION: NO, we will not allow this to keep the spec simple. If 5795bd8deadSopenharmony_ci necessary, these restrictions can always be lifted later. 5805bd8deadSopenharmony_ci 5815bd8deadSopenharmony_ci 6) What should an application do if the enum functions that return 5825bd8deadSopenharmony_ci BOOL fail for another reason than they are done? For example, if 5835bd8deadSopenharmony_ci they fail because they run out of memory? 5845bd8deadSopenharmony_ci 5855bd8deadSopenharmony_ci RESOLUTION: An application will have to call GetLastError to find 5865bd8deadSopenharmony_ci out the reason of failure. 5875bd8deadSopenharmony_ci 5885bd8deadSopenharmony_ci 7) The "Enum" API commands in this extension assume that the list 5895bd8deadSopenharmony_ci of things being enumerated does not change dynamically. Is that 5905bd8deadSopenharmony_ci reasonable? 5915bd8deadSopenharmony_ci 5925bd8deadSopenharmony_ci DISCUSSION: Display devices, and possibly GPUs in the future, can 5935bd8deadSopenharmony_ci be changed dynamically and/or hotplugged. Thus yes, this is a 5945bd8deadSopenharmony_ci potential issue. Existing OS functionality like EnumDisplayDevices 5955bd8deadSopenharmony_ci and even wglMakeCurrent will suffer from this too. In the latter 5965bd8deadSopenharmony_ci case, the application could make a context current to a device 5975bd8deadSopenharmony_ci that was removed from the system. A possible solution would be 5985bd8deadSopenharmony_ci some sort of notification mechanism to the application. Possibly 5995bd8deadSopenharmony_ci combined with being able to snapshot state first, then enumerate 6005bd8deadSopenharmony_ci that snapshot. That snapshot of state might immediately become 6015bd8deadSopenharmony_ci invalid, but at least the enumeration will walk a consistent list. 6025bd8deadSopenharmony_ci 6035bd8deadSopenharmony_ci RESOLUTION: This is a wider issue than just this specification, 6045bd8deadSopenharmony_ci and not currently addressed. 6055bd8deadSopenharmony_ci 6065bd8deadSopenharmony_ci 8) How do I transfer data efficiently between two affinity- 6075bd8deadSopenharmony_ci contexts? 6085bd8deadSopenharmony_ci 6095bd8deadSopenharmony_ci DISCUSSION: It is desired for an application to render in one 6105bd8deadSopenharmony_ci context, and transfer the result of that rendering to another 6115bd8deadSopenharmony_ci context. These two contexts can be on different GPUs. If they are, 6125bd8deadSopenharmony_ci how does the application efficiently transfer this data? Currently 6135bd8deadSopenharmony_ci OpenGL provides two mechanisms, neither of which are ideal: 6145bd8deadSopenharmony_ci 6155bd8deadSopenharmony_ci 1) The application can do a ReadPixels followed by a DrawPixels / 6165bd8deadSopenharmony_ci TexImage call. This involves transfer through host memory, which 6175bd8deadSopenharmony_ci can be slow. 6185bd8deadSopenharmony_ci 6195bd8deadSopenharmony_ci 2) The application can share objects among the two contexts using 6205bd8deadSopenharmony_ci wglShareLists(). This will work, but is counter to the premise of 6215bd8deadSopenharmony_ci this extension where each GPU has its own set of resources, not 6225bd8deadSopenharmony_ci shared with another GPU. 6235bd8deadSopenharmony_ci 6245bd8deadSopenharmony_ci RESOLUTION: This is a hole which needs to be addressed separately. 6255bd8deadSopenharmony_ci 6265bd8deadSopenharmony_ciRevision history 6275bd8deadSopenharmony_ci 6285bd8deadSopenharmony_ci None 629