Jump to content

[Blog] Crossfire testing


angerthosenear

Recommended Posts

I've managed to add Crossfire tab to catalyst by making the adapter say it supports every feature. And I've changed the adapter initializtion inside catalyst to return fake make reported speed.

Still doesn't work on 13.12 (Enable button is grayed out).

Found out about AMD ADL SDK, and I modified its SDK sample to enable/disable crossfire chains, it works without catalyst installed on 13.4 driver, but it still doesn't work with 13.12,

ADL_Adapter_Crossfire_Caps reports -1 (ADL_ERR) on all adapters, while on 13.4 the same code gets the crossfire capabilities/configurations.

I can use the older 13.4 atiadlxy.dll (ADL SDK lib) locally with the sample app, but it still doesn't work (same result).

The above means its probably not catalyst or ADL but the driver itself. I've tried to disassemble and decompile (hex rays decompiler) the dll to see how it connects to the driver

and it seems to be with D3DKMTEscape calls. But its gibrish from here.

ADL SDK sample code:


///
/// Copyright (c) 2008 - 2009 Advanced Micro Devices, Inc.

/// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
/// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
/// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.

/// \file main.c
/// \brief C/C++ ADL sample application
///
/// Demonstrates some basic ADL functions - create, destroy, obtaining adapter and display information.
/// If the display capabilities allow, increases, decreases and restores the brightness of each display


#if defined (LINUX)
#include "../include/adl_sdk.h"
#include <dlfcn.h> //dyopen, dlsym, dlclose
#include <stdlib.h>
#include <string.h> //memeset
#include <unistd.h> //sleep

#else
#include <windows.h>
#include <tchar.h>
#include "..\include\adl_sdk.h"
#endif

#include <stdio.h>

// Definitions of the used function pointers. Add more if you use other ADL APIs
typedef int ( *ADL_MAIN_CONTROL_CREATE ) (ADL_MAIN_MALLOC_CALLBACK, int );
typedef int ( *ADL_MAIN_CONTROL_DESTROY ) ( );
typedef int ( *ADL_ADAPTER_NUMBEROFADAPTERS_GET ) (int*);
typedef int ( *ADL_ADAPTER_ADAPTERINFO_GET ) ( LPAdapterInfo, int );
typedef int ( *ADL_ADAPTER_CROSSFIRE_CAPS ) ( int, int*, int*, ADLCrossfireComb** );
typedef int ( *ADL_ADAPTER_ID_GET ) ( int iAdapterIndex, int *lpAdapterID );
typedef int ( *ADL_ADAPTER_CROSSFIRE_SET ) ( int iAdapterIndex, ADLCrossfireComb *lpCrossfireComb);


// Memory allocation function
void* __stdcall ADL_Main_Memory_Alloc ( int iSize )
{
void* lpBuffer = malloc ( iSize );
return lpBuffer;
}

// Optional Memory de-allocation function
void __stdcall ADL_Main_Memory_Free ( void** lpBuffer )
{
if ( NULL != *lpBuffer )
{
free ( *lpBuffer );
*lpBuffer = NULL;
}
}

#if defined (LINUX)
// equivalent functions in linux
void * GetProcAddress( void * pLibrary, const char * name)
{
return dlsym( pLibrary, name);
}

void Sleep( int time)
{
usleep(time*1000);
}

#endif

char *RetToString(int ret) {
switch (ret) {
case 0:
return "( 0 = ADK_OK: ADL function completed successfully.)";
break;
case 1:
return "( 1 = ADL_OK_WARNING : All OK, but with warning. )";
break;
case 2:
return "( 2 = ADL_OK_MODE_CHANGE : All OK but need mode change. )";
break;
case 3:
return "( 3 = ADL_OK_RESTART : All OK, but need restart. )";
break;
case 4:
return "( 4 = ADL_OK_WAIT : All OK, but need to wait. )";
break;



case -1:
return "( -1 = ADL_ERR : Generic Error. Most likely one or more of the Escape calls to the driver failed! )";
break;
case -2:
return "( -2 = ADL_ERR_NOT_INIT : ADL not initialized. )";
break;
case -3:
return "( -3 = ADL_ERR_INVALID_PARAM : One of the parameter passed is invalid. )";
break;
case -4:
return "( -4 = ADL_ERR_INVALID_PARAM_SIZE : One of the parameter size is invalid. )";
break;
case -5:
return "( -5 = ADL_ERR_INVALID_ADL_IDX : Invalid ADL index passed. )";
break;
case -6:
return "( -6 = ADL_ERR_INVALID_CONTROLLER_IDX : Invalid controller index passed. )";
break;
case -7:
return "( -7 = ADL_ERR_INVALID_DIPLAY_IDX : Invalid display index passed. )";
break;
case -8:
return "( -8 = ADL_ERR_NOT_SUPPORTED : Function not supported by the driver. )";
break;
case -9:
return "( -9 = ADL_ERR_NULL_POINTER : Null Pointer error. )";
break;
case -10:
return "( -10 = ADL_ERR_DISABLED_ADAPTER : Call can't be made due to disabled adapter. )";
break;
case -11:
return "( -11 = ADL_ERR_INVALID_CALLBACK : Invalid Callback. )";
break;
case -12:
return "( -12 = ADL_ERR_RESOURCE_CONFLICT : Display Resource conflict. )";
break;
case -20:
return "( -20 = ADL_ERR_SET_INCOMPLETE)";
break;
case -21:
return "( -21 = ADL_ERR_NO_XDISPLAY : There's no Linux XDisplay in Linux Console environment. )";
break;
default:
break;
}
return "Unknown error code";
}

int main (int argc, char *argv[])
{
#if defined (LINUX)
void *hDLL = 0; // Handle to .so library
#else
HINSTANCE hDLL = 0; // Handle to DLL
#endif


ADL_MAIN_CONTROL_CREATE ADL_Main_Control_Create;
ADL_MAIN_CONTROL_DESTROY ADL_Main_Control_Destroy;
ADL_ADAPTER_NUMBEROFADAPTERS_GET ADL_Adapter_NumberOfAdapters_Get;
ADL_ADAPTER_ADAPTERINFO_GET ADL_Adapter_AdapterInfo_Get;
ADL_ADAPTER_CROSSFIRE_CAPS ADL_Adapter_Crossfire_Caps;
ADL_ADAPTER_ID_GET ADL_Adapter_ID_Get;
ADL_ADAPTER_CROSSFIRE_SET ADL_Adapter_Crossfire_Set;

ADL_CONTEXT_HANDLE lpAdlContextHandle = NULL;

LPAdapterInfo lpAdapterInfo = NULL;
LPADLDisplayInfo lpAdlDisplayInfo = NULL;
int i, j, z, k;
int iNumberAdapters;
int iAdapterIndex;

int seenids[100];
int seenids_num = 0;
int isnew = 0;

int lpPreferred = -1;
int lpNumComb = -1;
int ret = 0;
ADLCrossfireComb *lpADLCrossfireComb = NULL;

int lpAdapterId;


#if defined (LINUX)
hDLL = dlopen( "libatiadlxx.so", RTLD_LAZY|RTLD_GLOBAL);
#else
hDLL = LoadLibrary("atiadlxx.dll");
if (hDLL == NULL)
// A 32 bit calling application on 64 bit OS will fail to LoadLIbrary.
// Try to load the 32 bit library (atiadlxy.dll) instead
hDLL = LoadLibrary("atiadlxy.dll");
#endif

if (NULL == hDLL)
{
printf("ADL library not found!\n");
return 0;
}

ADL_Adapter_AdapterInfo_Get = (ADL_ADAPTER_ADAPTERINFO_GET) GetProcAddress(hDLL,"ADL_Adapter_AdapterInfo_Get");
ADL_Main_Control_Create = (ADL_MAIN_CONTROL_CREATE) GetProcAddress(hDLL,"ADL_Main_Control_Create");
ADL_Main_Control_Destroy = (ADL_MAIN_CONTROL_DESTROY) GetProcAddress(hDLL,"ADL_Main_Control_Destroy");
ADL_Adapter_NumberOfAdapters_Get = (ADL_ADAPTER_NUMBEROFADAPTERS_GET) GetProcAddress(hDLL,"ADL_Adapter_NumberOfAdapters_Get");
ADL_Adapter_Crossfire_Caps = (ADL_ADAPTER_CROSSFIRE_CAPS) GetProcAddress(hDLL,"ADL_Adapter_Crossfire_Caps");
ADL_Adapter_ID_Get = (ADL_ADAPTER_ID_GET) GetProcAddress(hDLL,"ADL_Adapter_ID_Get");
ADL_Adapter_Crossfire_Set = (ADL_ADAPTER_CROSSFIRE_SET) GetProcAddress(hDLL,"ADL_Adapter_Crossfire_Set");
if (
NULL == ADL_Main_Control_Destroy ||
NULL == ADL_Adapter_NumberOfAdapters_Get ||
NULL == ADL_Adapter_AdapterInfo_Get ||
NULL == ADL_Main_Control_Create ||
NULL == ADL_Adapter_Crossfire_Caps ||
NULL == ADL_Adapter_Crossfire_Set ||
NULL
)
{
printf("ADL's API is missing!\n");
return 0;
}

// Initialize ADL. The second parameter is 1, which means:
// retrieve adapter information only for adapters that are physically present and enabled in the system
if ( ADL_OK != ADL_Main_Control_Create (ADL_Main_Memory_Alloc, 1) )
{
printf("ADL Initialization Error!\n");
return 0;
}

// Obtain the number of adapters for the system
if ( ADL_OK != ADL_Adapter_NumberOfAdapters_Get ( &iNumberAdapters ) )
{
printf("Cannot get the number of adapters!\n");
return 0;
}

if ( 0 < iNumberAdapters )
{
printf("Mum adapters! %d\n", iNumberAdapters);

lpAdapterInfo = malloc ( sizeof (AdapterInfo) * iNumberAdapters );
memset ( lpAdapterInfo,'\0', sizeof (AdapterInfo) * iNumberAdapters );

// Get the AdapterInfo structure for all adapters in the system
ADL_Adapter_AdapterInfo_Get (lpAdapterInfo, sizeof (AdapterInfo) * iNumberAdapters);
}


i = j = z = k = 0 ;

// Repeat for all available adapters in the system
for ( i = 0; i < iNumberAdapters; i++ )
{
iAdapterIndex = lpAdapterInfo[ i ].iAdapterIndex;
ret = ADL_Adapter_ID_Get(iAdapterIndex, &lpAdapterId);


isnew = 1;
for ( j = 0; j < seenids_num; j++) {
if (seenids[j] == lpAdapterId) isnew = 0;
}
if (isnew) {

printf("%d/%d: Adapter name: %s\n", i, iAdapterIndex, lpAdapterInfo[ i ].strAdapterName);
printf("%d, Adapter name id: %d\n", ret, lpAdapterId);

seenids[j] = lpAdapterId;
seenids_num++;

lpPreferred = 0;
lpNumComb = 0;
lpADLCrossfireComb = NULL;
ret = ADL_Adapter_Crossfire_Caps(iAdapterIndex, &lpPreferred, &lpNumComb, &lpADLCrossfireComb);
printf("ADL_Adapter_Crossfire_Caps: %s\n", RetToString(ret));
if (ret != 0) continue;


printf("Number of available configurations: %d\n", lpNumComb);
if (lpPreferred > -1 && lpPreferred < lpNumComb) printf("Preferred configuration: %d\n", lpPreferred);
for (k = 0; k < lpNumComb; k++) {
printf("\tCombination number: %d, IsPreferedConfiguration: %s\n", k, k==lpPreferred? "yes" : "no");
printf("\tnumber of links (beside this adapter) [%d].iNumLinkAdapter: %d\n", k, lpADLCrossfireComb[lpPreferred].iNumLinkAdapter);
for (z = 0; z < lpADLCrossfireComb[lpPreferred].iNumLinkAdapter && z < 3; z++) {
printf("\tCan be linked with [%d].iAdaptLink[%d]: %d\n", k, z, lpADLCrossfireComb[z].iAdaptLink[0]);
}
}

ADL_Main_Memory_Free ( &lpADLCrossfireComb );
}

printf("\n");

}

if (argc == 3 && (argv[1][0] == 'd' || argv[1][0] == 'D')) { //xxx.exe disable 0
printf("Disable: %d\n", atoi(argv[2]));
lpADLCrossfireComb = (ADLCrossfireComb *) malloc(sizeof(ADLCrossfireComb));
if (lpADLCrossfireComb != NULL) {
lpADLCrossfireComb->iNumLinkAdapter = 1;
lpADLCrossfireComb->iAdaptLink[0] = 6;
}
ret = ADL_Adapter_Crossfire_Set(atoi(argv[2]), NULL);
printf("ADL_Adapter_Crossfire_Set: %s\n", RetToString(ret));

}
else if (argc == 4 && (argv[1][0] == 'e' || argv[1][0] == 'E')) { //xxx.exe enable 0 6
printf("Enable: %d with %d\n", atoi(argv[2]), atoi(argv[3]));
lpADLCrossfireComb = (ADLCrossfireComb *) malloc(sizeof(ADLCrossfireComb));
if (lpADLCrossfireComb != NULL) {
lpADLCrossfireComb->iNumLinkAdapter = 1;
lpADLCrossfireComb->iAdaptLink[0] = atoi(argv[3]);
}
ret = ADL_Adapter_Crossfire_Set(atoi(argv[2]), lpADLCrossfireComb);
printf("ADL_Adapter_Crossfire_Set: %s\n", RetToString(ret));
}




ADL_Main_Memory_Free ( &lpAdapterInfo );
ADL_Main_Memory_Free ( &lpAdlDisplayInfo );
ADL_Main_Control_Destroy ();

#if defined (LINUX)
dlclose(hDLL);
#else
FreeLibrary(hDLL);
#endif

return 0;
}<dlfcn.h><stdlib.h><string.h><unistd.h><windows.h><tchar.h><stdio.h>

usage:

ADL_Sample.exe info - shows the prefered crossfire configurations.

ADL_Sample.exe enable - links the first adapter as master with the second adapter as slave

ADL_Sample.exe disable - disables crossfire at the id specified.

for example, info on my computer shows:


Mum adapters! 12
0/0: Adapter name: AMD Radeon HD 6900 Series
0, Adapter name id: 44524032
ADL_Adapter_Crossfire_Caps: 0
lpPreferred: 0
lpNumComb: 1
[0].iNumLinkAdapter: 1
[0].iAdaptLink[0]: 6

6/6: Adapter name: AMD Radeon HD 6900 Series
0, Adapter name id: 34014592
ADL_Adapter_Crossfire_Caps: 0
lpPreferred: 0
lpNumComb: 1
[0].iNumLinkAdapter: 1
[0].iAdaptLink[0]: 6

it says adapter id 0 can be linked with adapter id 6 (iAdaptLink[0]), so I use enable 0 6, and it enables crossfire. disable 0 to disable it.

binary:

ADL_Sample.zip

Anyone sure just the link bandwidth? or might it be the motherboard without crossfire support?

Anyway, I've given up here so I've dumped what I found out if anyone wants to continue.

I suggest from here:

1) Ask amd to allow ADL/Catalyst to enable crossfire on all configurations even if its in some debug mode.

2) Hook deeper (PCI.sys, emulation, w/e), I have no idea about those.</stdio.h></tchar.h></windows.h></unistd.h></string.h></stdlib.h></dlfcn.h>

ADL_Sample.zip

  • Thumbs Up 2
Link to comment
Share on other sites

13.4 without crossfire bridge, trying to enable 0 and 6 even if it isn't in configurations options gives:


D:\Downloads\IDM\Compressed\ADL_SDK_6.0\Sample\Debug>ADL_Sample.exe e 0 6
Mum adapters! 12
0/0: Adapter name: AMD Radeon HD 6900 Series
0, Adapter name id: 38428160
ADL_Adapter_Crossfire_Caps: ( 0 = ADK_OK: ADL function completed successfully.)
Number of available configurations: 0

6/6: Adapter name: AMD Radeon HD 6900 Series
0, Adapter name id: 29151424
ADL_Adapter_Crossfire_Caps: ( 0 = ADK_OK: ADL function completed successfully.)
Number of available configurations: 0

Enable: 0 with 6
ADL_Adapter_Crossfire_Set: ( -8 = ADL_ERR_NOT_SUPPORTED : Function not supported by the driver. )

same with 13.12 (no catalyst):


Mum adapters! 12
0/0: Adapter name: AMD Radeon HD 6900 Series
0, Adapter name id: 255925184
ADL_Adapter_Crossfire_Caps: ( -1 = ADL_ERR : Generic Error. Most likely one or more of the Escape calls to the driver failed! )


6/6: Adapter name: AMD Radeon HD 6900 Series
0, Adapter name id: 255396928
ADL_Adapter_Crossfire_Caps: ( -1 = ADL_ERR : Generic Error. Most likely one or more of the Escape calls to the driver failed! )


Enable: 0 with 6
ADL_Adapter_Crossfire_Set: ( -1 = ADL_ERR : Generic Error. Most likely one or more of the Escape calls to the driver failed! )

AMD_Catalyst_14.1_BetaV1.6:


Mum adapters! 12
0/0: Adapter name: AMD Radeon HD 6900 Series
0, Adapter name id: 97894464
ADL_Adapter_Crossfire_Caps: ( -1 = ADL_ERR : Generic Error. Most likely one or more of the Escape calls to the driver failed! )

6/6: Adapter name: AMD Radeon HD 6900 Series
0, Adapter name id: 269955840
ADL_Adapter_Crossfire_Caps: ( -1 = ADL_ERR : Generic Error. Most likely one or more of the Escape calls to the driver failed! )

Enable: 0 with 6
ADL_Adapter_Crossfire_Set: ( -1 = ADL_ERR : Generic Error. Most likely one or more of the Escape calls to the driver failed! )

Just one HD6950 on normal 16x link, catalyst 14.1 beta


D:\Downloads\IDM\Compressed\ADL_SDK_6.0\Sample\Debug>ADL_Sample.exe info
Mum adapters! 6
0/0: Adapter name: AMD Radeon HD 6900 Series
0, Adapter name id: 33798080
ADL_Adapter_Crossfire_Caps: ( -1 = ADL_ERR : Generic Error. Most likely one or m
ore of the Escape calls to the driver failed! )

Seems to be unrelated with the 1x link. This function may be generally broken, you can try it on your PC (single/multi card doesn't matter).

Link to comment
Share on other sites

  • 1 month later...

Hello!

In first, sorry for my english.

I pay attention to this thread because on my mobo, i've only one pcie 16x & 3 Pcie 1x but i've 2 R7 250.

On this type of graphic card, there's no crossfire connector.

After reading this thread, i try the catalyst 13.4 but i modify them( .ini et .msi), the R7 or HD8670 came 6 months later. The 13.4 finally wok fine. I try ADL_sample. I pass 2 days to find the DLL to make it work but no chance in my case, the 2 cards are in crossfire= -1. So, i'm searching for a trick to make functional the crossfire with this 2 cards, perhaps it's not possible with my mobo.

Oh... Sorry, i'm under 7 x64 sp1.

I've tested under ubuntu 13.10 but 2 problems: I'm not expert in Linux and the glrx drivers doesn't recognize the R7.

I've got another fool project: I've an operational motherboard of HP 9212ea, mobo functional but the gpu has been removed, so, i've the 16x lane to make something interesting if the mobo wants.

i've a 4870x2 but after testing in 1x, this type of card is very bandwith dependant.

Thanks to read (and help me if you want)

Link to comment
Share on other sites

  • 2 weeks later...

hello!

So, ADL Info give:

Mum adapters! 4

0/0: Adapter name: AMD Radeon R7 200 Series

0, Adapter name id: 1271040

ADL_Adapter_Crossfire_Caps: -1

2/2: Adapter name: AMD Radeon R7 200 Series

0, Adapter name id: 153019008

ADL_Adapter_Crossfire_Caps: -1

And with ADL e 0 2, same listing with at the end:

Enable: 0 with 2

ADL_Adapter_Crossfire_Set: -1

I precise, this is not the legacy drivers 13.4, but the catalyst with modif to recognize the r7 series. I searched for the legacys but the amds servers don't contain any legacy driver. If you have a link, i take it.

So, the mobo is P45TS with a C2Q Q9300, 2*2GO DDR3 Crucial Win7 x64 Sp1 and Samsung HD103UJ 1TB.

I lose, This type of graphics is software crossfire only. There's no crossfire connetor on them.

Thanks.

Link to comment
Share on other sites

  • 6 months later...

whoah this is such an awesome thread but what happened? Action lost?

perhaps the newest catalyst 14.9.1 beta will work since many complained of crossfire difficulties in the newly released WHQL AMD Catalyst 14.9

such a nerdy but rewarding crossfire attempts here guys!

Link to comment
Share on other sites

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.