Aufrufen von FSR „ffxQuery“ aus C#-Code, um die DLL-Unterstützung zu identifizierenC#

Ein Treffpunkt für C#-Programmierer
Guest
 Aufrufen von FSR „ffxQuery“ aus C#-Code, um die DLL-Unterstützung zu identifizieren

Post by Guest »

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

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);
Die erste Hälfte der angegebenen C++-Codebeispiele sieht folgendermaßen aus:

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);
Ich habe es geschafft, dass das in C# so funktioniert

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}");
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.

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);
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)

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);
}
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:

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
Wenn ich die Zeile versionIds.Add(0); in versionIds.Add(7); ändere, sieht meine Ausgabe so aus:

Code: Select all

ID: 7, Name: 3.1.3
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.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post