Aufrufen von FSR „ffxQuery“ aus C#-Code, um die DLL-Unterstützung zu identifizieren
Posted: 13 Jan 2025, 11:16
Für einige Projekte, an denen ich arbeite, versuche ich, FSR 3.1-DLLs zu laden und herauszufinden, um welche Version es sich handelt. Bei einigen DLLs befindet sich die Version in den Dateieigenschaften. Die DLL von DLSS 3.7 hat beispielsweise die Dateiversion 3.7.0.0. Mit FSR 3.1 haben sie ihre DLLs so kompiliert, dass die Dateiversion 1.0.1.39157 und die Produktversion 1.0.1.0 ist, aber die FSR-Version, von der ich weiß, dass sie darin enthalten ist, ist 3.1.3.
I Ich habe hier ein Repository, in dem daran gearbeitet wird.
Das Problem
Bei einem zufälligen FSR (z. B. amd_fidelityfx_dx12.dll), laden Sie es in eine C#-Anwendung und rufen Sie die ffxQuery-Methode auf.
Die DLLs können entweder beim Ausführen von Code aus dem oben genannten Repository abgerufen werden, oder Sie sind auch im AMD FidelityFX SDK enthalten.
Die oben erwähnte ffqQuery stammt aus den von AMD hier und hier bereitgestellten Beispielen. Obwohl dieser Code C++ ist, muss ich die gleichen Dinge von C# aus tun.
Mein aktueller Versuch
Mein aktueller Der Versuch befindet sich in meinem ReadFSRVersionFromCSharp-Repository. Anfangs konnte ich nichts laden. Nach etwas Schlaf und mit Hilfe von GitHub Copilot/GPT-4o spuckte es Code aus, der halb funktioniert.
Ich bin kein C++-Entwickler, ich habe keine Kenntnisse im korrekten Laden von C++-DLLs in C#. Wenn mir die KI schrecklichen Code gegeben hat, zeigen Sie mir bitte, wie ich ihn verbessern kann.
In der Datei AMDFidelityFXAPI.cs habe ich es geschafft, dass die DLL dynamisch geladen wird Verwenden von Methoden aus kernel32.dll
Die erste Hälfte der angegebenen C++-Codebeispiele sieht folgendermaßen aus:
Ich habe es geschafft, dass das in C# so funktioniert
Dies hat jetzt versionCount, der den Wert 2 enthält. Soweit mir bekannt ist, ist dies zu erwarten, da FSR 3.1.x auch FSR 2.3.y als Fallback enthält.
Das verbleibende ProblemDie zweite Hälfte des von AMD bereitgestellten Codes sollte die FSR-Version und -IDs laden.
Daraus wurde dann C#-Code erstellt, der wie folgt aussieht (auch hier: Wenn dies falsch ist oder verbessert werden kann, lassen Sie es mich bitte wissen)
Das Problem besteht darin, dass die Ausgabe von Console.WriteLine($"ID: {versionIds}, Name: {versionNames}"); so aussieht wird nicht korrekt gemeldet.
Wenn ich dies sowohl auf der DX12- als auch auf der Vulkan-DLL ausführe, erhalte ich die folgende Ausgabe:
Wenn ich die Zeile versionIds.Add(0); in versionIds.Add(7); ändere, sieht meine Ausgabe so aus:
Ich glaube, dass bei der Einrichtung des obigen Codes etwas nicht stimmt, bevor er ffxQuery aufruft, aber ich kann nicht 100 % sicher sein. In den oben verlinkten AMD-Dokumenten heißt es:
Nur von ffxQuery zurückgegebene Versions-IDs in ffxQueryDescGetVersions mit dem entsprechenden Erstellungsstrukturtyp verwenden
Daher gehe ich davon aus, dass die für die Zeilen 3.1.3 und 2.3.2 zurückgegebenen IDs unterschiedlich sein sollten, da diese beim Erstellen des FSR-Kontexts für die zu verwendende Version verwendet werden.
I Ich habe hier ein Repository, in dem daran gearbeitet wird.
Das Problem
Bei einem zufälligen FSR (z. B. amd_fidelityfx_dx12.dll), laden Sie es in eine C#-Anwendung und rufen Sie die ffxQuery-Methode auf.
Die DLLs können entweder beim Ausführen von Code aus dem oben genannten Repository abgerufen werden, oder Sie sind auch im AMD FidelityFX SDK enthalten.
Die oben erwähnte ffqQuery stammt aus den von AMD hier und hier bereitgestellten Beispielen. Obwohl dieser Code C++ ist, muss ich die gleichen Dinge von C# aus tun.
Mein aktueller Versuch
Mein aktueller Der Versuch befindet sich in meinem ReadFSRVersionFromCSharp-Repository. Anfangs konnte ich nichts laden. Nach etwas Schlaf und mit Hilfe von GitHub Copilot/GPT-4o spuckte es Code aus, der halb funktioniert.
Ich bin kein C++-Entwickler, ich habe keine Kenntnisse im korrekten Laden von C++-DLLs in C#. Wenn mir die KI schrecklichen Code gegeben hat, zeigen Sie mir bitte, wie ich ihn verbessern kann.
In der Datei AMDFidelityFXAPI.cs habe ich es geschafft, dass die DLL dynamisch geladen wird Verwenden von Methoden aus kernel32.dll
Code: Select all
// Define the LoadLibrary and GetProcAddress functions
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FreeLibrary(IntPtr hModule);
Code: Select all
ffx::QueryDescGetVersions versionQuery{};
versionQuery.createDescType = FFX_API_CREATE_CONTEXT_DESC_TYPE_UPSCALE;
versionQuery.device = GetDX12Device(); // only for DirectX 12 applications
uint64_t versionCount = 0;
versionQuery.outputCount = &versionCount;
// get number of versions for allocation
ffxQuery(nullptr, &versionQuery.header);
Code: Select all
var versionQuery = new QueryDescGetVersions();
//versionQuery.createDescType = FFX_API_CREATE_CONTEXT_DESC_TYPE_UPSCALE;
versionQuery.createDescType = FxxConsts.FFX_API_CREATE_CONTEXT_DESC_TYPE_UPSCALE;
// versionQuery.device = GetDX12Device(); // only for DirectX 12 applications
versionQuery.device = IntPtr.Zero;
// uint64_t versionCount = 0;
UInt64 versionCount = 0;
versionQuery.outputCount = Marshal.AllocHGlobal(sizeof(UInt64));
Marshal.WriteInt64(versionQuery.outputCount, (UInt32)versionCount);
Debug.WriteLine("AMDFidelityFXAPI - Reading version count");
// get number of versions for allocation
// ffxQuery(IntPtr.Zero, &versionQuery.header);
var returnCode = ffxQuery(IntPtr.Zero, ref versionQuery);
Debug.WriteLine($"AMDFidelityFXAPI - returnCode: {returnCode}");
versionCount = (UInt64)Marshal.ReadInt64(versionQuery.outputCount);
Debug.WriteLine($"AMDFidelityFXAPI - versionCount: {versionCount}");
Das verbleibende ProblemDie zweite Hälfte des von AMD bereitgestellten Codes sollte die FSR-Version und -IDs laden.
Code: Select all
std::vector versionNames;
std::vector versionIds;
m_FsrVersionIds.resize(versionCount);
versionNames.resize(versionCount);
versionQuery.versionIds = versionIds.data();
versionQuery.versionNames = versionNames.data();
// fill version ids and names arrays.
ffxQuery(nullptr, &versionQuery.header);
Code: Select all
var versionCountInt = (int)versionCount;
//std::vector versionNames;
//std::vector versionIds;
//m_FsrVersionIds.resize(versionCount);
//versionNames.resize(versionCount);
var versionNames = new List(versionCountInt);
var versionIds = new List(versionCountInt);
var versionNamesPtrs = new IntPtr[versionCountInt];
var versionIdsPtrs = new IntPtr[versionCountInt];
try
{
for (var i = 0; i < versionCountInt; i++)
{
versionNames.Add(null);
versionIds.Add(0);
}
//versionQuery.versionIds = versionIds.data();
//versionQuery.versionNames = versionNames.data();
versionQuery.versionIds = Marshal.AllocHGlobal(sizeof(UInt64) * versionCountInt);
versionQuery.versionNames = Marshal.AllocHGlobal(IntPtr.Size * versionCountInt);
for (var i = 0; i < versionCountInt; i++)
{
versionIdsPtrs[i] = Marshal.AllocHGlobal(sizeof(UInt64));
Marshal.WriteInt64(versionIdsPtrs[i], (long)versionIds[i]);
Marshal.WriteIntPtr(versionQuery.versionIds, i * IntPtr.Size, versionIdsPtrs[i]);
versionNamesPtrs[i] = Marshal.StringToHGlobalAnsi(versionNames[i]);
Marshal.WriteIntPtr(versionQuery.versionNames, i * IntPtr.Size, versionNamesPtrs[i]);
}
// fill version ids and names arrays.
//ffxQuery(nullptr, &versionQuery.header);
returnCode = ffxQuery(IntPtr.Zero, ref versionQuery);
Debug.WriteLine($"AMDFidelityFXAPI - returnCode: {returnCode}");
if (returnCode != FfxApiReturnCodes.FFX_API_RETURN_OK)
{
throw new Exception($"Failed to get version count. Return code: {returnCode}");
}
for (var i = 0; i < versionCountInt; i++)
{
versionIds[i] = (UInt64)Marshal.ReadInt64(versionIdsPtrs[i]);
versionNames[i] = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(versionQuery.versionNames, i * IntPtr.Size));
}
Console.WriteLine("AMDFidelityFXAPI - Version Names and IDs:");
for (var i = 0; i < versionCountInt; i++)
{
Console.WriteLine($"ID: {versionIds[i]}, Name: {versionNames[i]}");
}
return versionNames;
}
finally
{
foreach (var ptr in versionIdsPtrs)
{
Marshal.FreeHGlobal(ptr);
}
foreach (var ptr in versionNamesPtrs)
{
Marshal.FreeHGlobal(ptr);
}
Marshal.FreeHGlobal(versionQuery.versionIds);
Marshal.FreeHGlobal(versionQuery.versionNames);
}
Wenn ich dies sowohl auf der DX12- als auch auf der Vulkan-DLL ausführe, erhalte ich die folgende Ausgabe:
Code: Select all
AMDFidelityFXAPI - Loading amd_fidelityfx_vk.dll
AMDFidelityFXAPI - Reading version count
AMDFidelityFXAPI - returnCode: FFX_API_RETURN_OK
AMDFidelityFXAPI - versionCount: 2
AMDFidelityFXAPI - returnCode: FFX_API_RETURN_OK
AMDFidelityFXAPI - Version Names and IDs:
ID: 0, Name: 3.1.3
ID: 0, Name: 2.3.2
AMDFidelityFXAPI - Loading amd_fidelityfx_dx12.dll
AMDFidelityFXAPI - Reading version count
AMDFidelityFXAPI - returnCode: FFX_API_RETURN_OK
AMDFidelityFXAPI - versionCount: 2
AMDFidelityFXAPI - returnCode: FFX_API_RETURN_OK
AMDFidelityFXAPI - Version Names and IDs:
ID: 0, Name: 3.1.3
ID: 0, Name: 2.3.2
Code: Select all
ID: 7, Name: 3.1.3
Nur von ffxQuery zurückgegebene Versions-IDs in ffxQueryDescGetVersions mit dem entsprechenden Erstellungsstrukturtyp verwenden
Daher gehe ich davon aus, dass die für die Zeilen 3.1.3 und 2.3.2 zurückgegebenen IDs unterschiedlich sein sollten, da diese beim Erstellen des FSR-Kontexts für die zu verwendende Version verwendet werden.