diff --git a/dlls/amdxc64/amdxc_interfaces.idl b/dlls/amdxc64/amdxc_interfaces.idl index 0c88ec17540..8a6c8e0011e 100644 --- a/dlls/amdxc64/amdxc_interfaces.idl +++ b/dlls/amdxc64/amdxc_interfaces.idl @@ -1,5 +1,6 @@ /* * Copyright 2025 Etaash Mathamsetty + * Copyright (c) 2016-2025 Advanced Micro Devices, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,6 +20,14 @@ import "wtypes.idl"; import "unknwn.idl"; +import "d3d12.idl"; + +typedef struct VkInstance_T *VkInstance; +typedef struct VkDevice_T *VkDevice; +typedef struct VkPhysicalDevice_T *VkPhysicalDevice; +typedef struct VkQueue_T *VkQueue; + +/* the following are publicly available */ [ object, @@ -40,14 +49,62 @@ interface IAmdExtAntiLagApi : IUnknown HRESULT UpdateAntiLagState([in, out] void* pData); } +/* The following were reverse engineered, but updated with interface, function names & structures from AMD headers */ + +typedef struct +{ + unsigned int waveSize; + unsigned int minWaveSize; + unsigned int maxWaveSize; + unsigned int reserved[5]; +} AmdExtD3DShaderIntrinsicsInfo; + +typedef enum +{ + AmdExtD3DShaderIntrinsicsSupport_Readfirstlane = 0x1, + AmdExtD3DShaderIntrinsicsSupport_Readlane = 0x2, + AmdExtD3DShaderIntrinsicsSupport_LaneId = 0x3, + AmdExtD3DShaderIntrinsicsSupport_Swizzle = 0x4, + AmdExtD3DShaderIntrinsicsSupport_Ballot = 0x5, + AmdExtD3DShaderIntrinsicsSupport_MBCnt = 0x6, + AmdExtD3DShaderIntrinsicsSupport_Compare3 = 0x7, + AmdExtD3DShaderIntrinsicsSupport_Barycentrics = 0x8, + AmdExtD3DShaderIntrinsicsSupport_WaveReduce = 0x9, + AmdExtD3DShaderIntrinsicsSupport_WaveScan = 0xA, + AmdExtD3DShaderIntrinsicsSupport_LoadDwordAtAddr = 0xB, + AmdExtD3DShaderIntrinsicsSupport_Reserved1 = 0xC, + AmdExtD3DShaderIntrinsicsSupport_IntersectInternal = 0xD, + AmdExtD3DShaderIntrinsicsSupport_DrawIndex = 0xE, + AmdExtD3DShaderIntrinsicsSupport_AtomicU64 = 0xF, + AmdExtD3DShaderIntrinsicsSupport_BaseInstance = 0x10, + AmdExtD3DShaderIntrinsicsSupport_BaseVertex = 0x11, + AmdExtD3DShaderIntrinsicsSupport_FloatConversion = 0x12, + AmdExtD3DShaderIntrinsicsSupport_GetWaveSize = 0x13, + AmdExtD3DShaderIntrinsicsSupport_ReadlaneAt = 0x14, + AmdExtD3DShaderIntrinsicsSupport_RayTraceHitToken = 0x15, + AmdExtD3DShaderIntrinsicsSupport_ShaderClock = 0x16, + AmdExtD3DShaderIntrinsicsSupport_ShaderRealtimeClock = 0x17, + AmdExtD3DShaderIntrinsicsSupport_Halt = 0x18, + AmdExtD3DShaderIntrinsicsSupport_IntersectBvhNode = 0x19, + AmdExtD3DShaderIntrinsicsSupport_BufferStoreByte = 0x1A, + AmdExtD3DShaderIntrinsicsSupport_BufferStoreShort = 0x1B, + AmdExtD3DShaderIntrinsicsSupport_ShaderMarker = 0x1C, + AmdExtD3DShaderIntrinsicsSupport_FloatOpWithRoundMode = 0x1D, + AmdExtD3DShaderIntrinsicsSupport_Reserved2 = 0x1E, + AmdExtD3DShaderIntrinsicsSupport_WaveMatrix = 0x1F, + AmdExtD3DShaderIntrinsicsSupport_Float8Conversion = 0x20, + AmdExtD3DShaderIntrinsicsSupport_Builtins = 0x21, + AmdExtD3DShaderIntrinsicsSupport_LoadByteAtAddr = 0x22, +} AmdExtD3DShaderIntrinsicsSupport; + [ object, uuid(014937ec-9288-446f-a9ac-d75a8e3a984f), local ] -interface IAmdExtStub1 : IUnknown +interface IAmdExtD3DFactory : IUnknown { - HRESULT QueryInterface2([in, out] void* unk, [in] REFIID iid, [in, out] void** out); + HRESULT CreateInterface([in] IUnknown* outer, [in] REFIID iid, [in, out] void** out); } [ @@ -55,9 +112,240 @@ interface IAmdExtStub1 : IUnknown uuid(ba019d53-ccab-4cbd-b56a-7230ed4330ad), local ] -interface IAmdExtStub2 : IUnknown +interface IAmdExtD3DShaderIntrinsics : IUnknown +{ + HRESULT GetInfo([in, out] AmdExtD3DShaderIntrinsicsInfo *pInfo); + HRESULT CheckSupport([in] AmdExtD3DShaderIntrinsicsSupport opcodeSupport); + HRESULT Enable(); +} + +/* The following were taken from AMD headers */ + +typedef enum +{ + AmdExtD3DStructUnknown, + AmdExtD3DStructPipelineState, + AmdExtD3DStructPipelineElf, + AmdExtD3DStructPipelineCrossCompile +} AmdExtD3DStructType; + +typedef struct +{ + AmdExtD3DStructType type; + void *pNext; +} AmdExtD3DCreateInfo; + +cpp_quote("#define AMD_EXT_DEPTH_BOUNDS_TEST_ENABLE (1 << 0)") +cpp_quote("#define AMD_EXT_ABORT_IF_NOT_PIPELINE_CACHED (1 << 1)") +cpp_quote("#define AMD_EXT_TOPOLOGY_TYPE_RECTANGLE (1 << 2)") + +typedef struct +{ + ULONG flags; +} AmdExtD3DPipelineFlags; + +typedef struct +{ + AmdExtD3DCreateInfo info; + AmdExtD3DPipelineFlags flags; +} AmdExtD3DPipelineCreateInfo; + +typedef enum +{ + Flags, +} AmdExtD3DCheckFeatureSupportType; + +typedef enum +{ + AmdExtD3DPrimitiveTopologyUndefined = 0, + AmdExtD3DPrimitiveTopologyRectangleList = 1, +} AmdExtD3DPrimitiveTopology; + +typedef struct +{ + USHORT major; + USHORT minor; +} AmdExtD3DGpuRtVersion; + +cpp_quote("#define AMD_EXT_WMMA_TYPE_FP16 0") +cpp_quote("#define AMD_EXT_WMMA_TYPE_FP32 1") +cpp_quote("#define AMD_EXT_WMMA_TYPE_FP8 11") + +typedef struct +{ + SIZE_T mSize; + SIZE_T nSize; + SIZE_T kSize; + ULONG aType; + ULONG bType; + ULONG cType; + ULONG resultType; + BOOL saturatingAccumulation; +} AmdExtWaveMatrixProperties; + +typedef struct +{ + AmdExtD3DCreateInfo info; + const void *elfBinary; + SIZE_T elfSize; + struct + { + ULONG width; + ULONG height; + ULONG depth; + } threadsPerGroup; +} AmdExtD3DPipelineElfInfo; + +typedef struct +{ + AmdExtD3DCreateInfo info; + const void *blob; + SIZE_T blobSize; + struct + { + UINT dimx; + UINT dimy; + UINT dimz; + } threadsPerGroup; + ULONG shaderType; + const void *options; + SIZE_T optionSize; + const char *kernelName; +} AmdExtD3DPipelineCrossCompileInfo; + +[ + object, + uuid(E6144584-03DE-439C-9C0B-43AE6D009BC6), + local +] +interface IAmdExtD3DShaderIntrinsics1 : IAmdExtD3DShaderIntrinsics +{ + HRESULT SetExtensionUavBinding([in] UINT registerIndex, [in] UINT registerSpace); +} + +[ + object, + uuid(8104C0FC-7413-410F-8E83-AA617E908648), + local +] +interface IAmdExtD3DDevice : IUnknown +{ + HRESULT CreateGraphicsPipelineState([in] const AmdExtD3DCreateInfo* pAmdExtCreateInfo, + [in] const D3D12_GRAPHICS_PIPELINE_STATE_DESC *pDesc, + [in] REFIID iid, [in, out] void **ppPipelineState); +} + +[ + object, + uuid(4BBCAF68-EAF7-4FA4-B653-CB458C334A4E), + local +] +interface IAmdExtD3DDevice1 : IAmdExtD3DDevice +{ + void PushMarker([in] ID3D12GraphicsCommandList *pGfxCmdList, [in] const char *pMarkerData); + void PopMarker([in] ID3D12GraphicsCommandList *pGfxCmdList); + void SetMarker([in] ID3D12GraphicsCommandList *pGfxCmdList, [in] const char *pMarkerData); +} + +[ + object, + uuid(A7BECF5D-2930-4FDA-8EEE-C797D8A52B7E), + local +] +interface IAmdExtD3DDevice2 : IAmdExtD3DDevice1 +{ + HRESULT CheckExtFeatureSupport([in] AmdExtD3DCheckFeatureSupportType featureType, + [in, out] void *pFeatureData, [in] SIZE_T featureDataSize); + HRESULT CreateComputePipelineState([in] const AmdExtD3DCreateInfo* pAmdExtCreateInfo, + [in] const D3D12_COMPUTE_PIPELINE_STATE_DESC* pDesc, + [in] REFIID iid, [in, out] void **ppPipelineState); +} + +[ + object, + uuid(397E3533-111E-4A9D-A171-2BAE8EF6CB24), + local +] +interface IAmdExtD3DDevice3 : IAmdExtD3DDevice2 +{ + HRESULT CreatePipelineState([in] const AmdExtD3DCreateInfo *pAmdExtCreateInfo, + [in] const D3D12_PIPELINE_STATE_STREAM_DESC* pDesc, + [in] REFIID iid, [in, out] void **ppPipelineState); +} + +[ + object, + uuid(BE9A8C6A-868E-490D-8FBF-29DAC2650F3B), + local +] +interface IAmdExtD3DDevice4 : IAmdExtD3DDevice3 +{ + void SetPrimitiveTopology([in] ID3D12GraphicsCommandList *pGfxCmdList, [in] AmdExtD3DPrimitiveTopology topology); +} + +[ + object, + uuid(BDC14598-B7D2-4A8D-9CA5-67848E2AF745), + local +] +interface IAmdExtD3DDevice5 : IAmdExtD3DDevice4 +{ + HRESULT CreateComputePipelineFromElf([in] AmdExtD3DPipelineElfInfo *pAmdExtCreateInfo, + REFIID iid, void **ppPipelineState); + void SetKernelArguments([in] ID3D12GraphicsCommandList *pCmdList, [in] ULONG first, + [in] ULONG count, [in] const void *ppValues); +} + +[ + object, + uuid(F764A768-48B4-46A5-9779-928ED6896D2A), + local +] +interface IAmdExtD3DDevice6 : IAmdExtD3DDevice5 +{ + void GetGpuRtInterfaceVersion([in, out] AmdExtD3DGpuRtVersion* pInterfaceVersion); + void GetGpuRtBinaryVersion([in, out] AmdExtD3DGpuRtVersion* pBinaryVersion); +} + +[ + object, + uuid(FEE37AFC-3C50-4ABF-86CC-1622349B29C0), + local +] +interface IAmdExtD3DDevice7 : IAmdExtD3DDevice6 +{ + HRESULT CreateComputePipelineCrossCompile([in] const AmdExtD3DPipelineCrossCompileInfo* pAmdExtCreateInfo, + [in] REFIID iid, [in, out] void** ppPipelineState); +} + +[ + object, + uuid(F714E11A-B54E-4E0F-ABC5-DF58B18133D1), + local +] +interface IAmdExtD3DDevice8 : IAmdExtD3DDevice7 +{ + HRESULT GetWaveMatrixProperties([in, out] SIZE_T *pCount, [in, out] AmdExtWaveMatrixProperties *pProperties); +} + +/* taken from vkd3d-proton */ + +[ + uuid(39da4e09-bd1c-4198-9fae-86bbe3be41fd), + object, + local, + pointer_default(unique) +] +interface ID3D12DXVKInteropDevice : IUnknown { - void stub(); - void stub2([in] unsigned int unk); - void stub3(); + HRESULT GetDXGIAdapter(REFIID iid, void **object); + HRESULT GetInstanceExtensions(UINT *extension_count, const char **extensions); + HRESULT GetDeviceExtensions(UINT *extension_count, const char **extensions); + HRESULT GetDeviceFeatures(const void **features); + HRESULT GetVulkanHandles(VkInstance *vk_instance, VkPhysicalDevice *vk_physical_device, VkDevice *vk_device); + HRESULT GetVulkanQueueInfo(ID3D12CommandQueue *queue, VkQueue *vk_queue, UINT32 *vk_queue_family); + void GetVulkanImageLayout(ID3D12Resource *resource, D3D12_RESOURCE_STATES state, void *vk_layout); + HRESULT GetVulkanResourceInfo(ID3D12Resource *resource, UINT64 *vk_handle, UINT64 *buffer_offset); + HRESULT LockCommandQueue(ID3D12CommandQueue *queue); + HRESULT UnlockCommandQueue(ID3D12CommandQueue *queue); } diff --git a/dlls/amdxc64/main.c b/dlls/amdxc64/main.c index b4eb97f34a9..d96406b6212 100644 --- a/dlls/amdxc64/main.c +++ b/dlls/amdxc64/main.c @@ -28,6 +28,7 @@ #include "winternl.h" #include "wine/debug.h" #include "wine/heap.h" +#include "wine/vulkan.h" #define COBJMACROS #include "initguid.h" @@ -37,10 +38,84 @@ WINE_DEFAULT_DEBUG_CHANNEL(amdxc); +static BOOL check_fsr4_supported(ID3D12Device *device) +{ + ID3D12DXVKInteropDevice *interop; + VkInstance instance; + VkDevice vk_device; + VkPhysicalDevice phys_device; + VkPhysicalDeviceProperties2 prop = {0}; + VkPhysicalDeviceDriverProperties driver_prop = {0}; + const char **extensions = NULL; + UINT extension_count = 0; + UINT major, minor; + BOOL has_float8 = FALSE, has_coopmat2 = FALSE, has_coopmat = FALSE; + BOOL rdna3_workaround = FALSE, ret = FALSE; + const char *env = getenv("DXIL_SPIRV_CONFIG"); + + if (FAILED(ID3D12Device_QueryInterface(device, &IID_ID3D12DXVKInteropDevice, (void **)&interop))) + return FALSE; + + if (FAILED(ID3D12DXVKInteropDevice_GetVulkanHandles(interop, &instance, &phys_device, &vk_device))) + goto fail; + + prop.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + prop.pNext = &driver_prop; + driver_prop.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; + + vkGetPhysicalDeviceProperties2(phys_device, &prop); + + if (prop.properties.vendorID != 0x1002) goto fail; + /* only RADV supports FSR4 */ + if (driver_prop.driverID != VK_DRIVER_ID_MESA_RADV) goto fail; + + major = VK_API_VERSION_MAJOR(prop.properties.driverVersion); + minor = VK_API_VERSION_MINOR(prop.properties.driverVersion); + + if (FAILED(ID3D12DXVKInteropDevice_GetDeviceExtensions(interop, &extension_count, NULL))) + goto fail; + + extensions = malloc(sizeof(*extensions) * extension_count); + + if (FAILED(ID3D12DXVKInteropDevice_GetDeviceExtensions(interop, &extension_count, extensions))) + goto fail; + + for (UINT i = 0; i < extension_count; i++) + { + if (!strcmp("VK_NV_cooperative_matrix2", extensions[i])) + has_coopmat2 = TRUE; + if (!strcmp("VK_KHR_cooperative_matrix", extensions[i])) + has_coopmat = TRUE; + if (!strcmp("VK_EXT_shader_float8", extensions[i])) + has_float8 = TRUE; + } + + if (env && strstr(env, "wmma_rdna3_workaround")) + rdna3_workaround = TRUE; + + if (major > 25 || (major == 25 && minor >= 2)) + { + /* RDNA 4+ */ + if (has_coopmat2 && has_float8) ret = TRUE; + /* + * RDNA3 (or RDNA 2/1 with layer), + * ensure the user is doing stuff correctly + */ + if (has_coopmat && rdna3_workaround) ret = TRUE; + } + +fail: + if (extensions) free(extensions); + ID3D12DXVKInteropDevice_Release(interop); + + return ret; +} + struct AMDFSR4FFX { IAmdExtFfxApi IAmdExtFfxApi_iface; LONG ref; + BOOL fsr4_supported; }; static struct AMDFSR4FFX* impl_from_IAmdExtFfxApi(IAmdExtFfxApi* iface) @@ -77,6 +152,7 @@ HRESULT STDMETHODCALLTYPE AMDFSR4FFX_UpdateFfxApiProvider(IAmdExtFfxApi *iface, const char *env; updateffxapi_pfn pfn; HMODULE amdffx; + struct AMDFSR4FFX *this = impl_from_IAmdExtFfxApi(iface); TRACE("%p %p %u\n", iface, data, size); @@ -87,7 +163,13 @@ HRESULT STDMETHODCALLTYPE AMDFSR4FFX_UpdateFfxApiProvider(IAmdExtFfxApi *iface, amdffx = LoadLibraryA("amdxcffx64"); if (!amdffx) { - ERR("Failed to load FSR4 dll (amdxcffx)!\n"); + ERR("Failed to load FSR4 dll (amdxcffx64)!\n"); + return E_NOINTERFACE; + } + + if (!this->fsr4_supported) + { + ERR("FSR4 not supported on this system!\n"); return E_NOINTERFACE; } @@ -110,97 +192,286 @@ static const struct IAmdExtFfxApiVtbl AMDFSR4FFX_vtable = { AMDFSR4FFX_UpdateFfxApiProvider }; -struct AMDExtStub2 +struct AmdExtD3DShaderIntrinsics { - IAmdExtStub2 IAmdExtStub2_iface; + IAmdExtD3DShaderIntrinsics IAmdExtD3DShaderIntrinsics_iface; LONG ref; }; -struct AMDExtStub2* impl_from_IAMDExtStub2(IAmdExtStub2 *iface) +struct AmdExtD3DShaderIntrinsics* impl_from_IAmdExtD3DShaderIntrinsics(IAmdExtD3DShaderIntrinsics *iface) { - return CONTAINING_RECORD(iface, struct AMDExtStub2, IAmdExtStub2_iface); + return CONTAINING_RECORD(iface, struct AmdExtD3DShaderIntrinsics, IAmdExtD3DShaderIntrinsics_iface); } -ULONG STDMETHODCALLTYPE AMDExtStub2_AddRef(IAmdExtStub2 *iface) +ULONG STDMETHODCALLTYPE AmdExtD3DShaderIntrinsics_AddRef(IAmdExtD3DShaderIntrinsics *iface) { - struct AMDExtStub2 *this = impl_from_IAMDExtStub2(iface); + struct AmdExtD3DShaderIntrinsics *this = impl_from_IAmdExtD3DShaderIntrinsics(iface); return InterlockedIncrement(&this->ref); } -ULONG STDMETHODCALLTYPE AMDExtStub2_Release(IAmdExtStub2 *iface) +ULONG STDMETHODCALLTYPE AmdExtD3DShaderIntrinsics_Release(IAmdExtD3DShaderIntrinsics *iface) { - struct AMDExtStub2 *this = impl_from_IAMDExtStub2(iface); + struct AmdExtD3DShaderIntrinsics *this = impl_from_IAmdExtD3DShaderIntrinsics(iface); ULONG ret = InterlockedDecrement(&this->ref); if (!ret) free(this); return ret; } -HRESULT STDMETHODCALLTYPE AMDExtStub2_QueryInterface(IAmdExtStub2 *iface, REFIID iid, void **out) +HRESULT STDMETHODCALLTYPE AmdExtD3DShaderIntrinsics_QueryInterface(IAmdExtD3DShaderIntrinsics *iface, REFIID iid, void **out) { FIXME("%p %s %p stub!\n", iface, debugstr_guid(iid), out); return E_NOINTERFACE; } -void STDMETHODCALLTYPE AMDExtStub2_stub1(IAmdExtStub2 *iface) +HRESULT STDMETHODCALLTYPE AmdExtD3DShaderIntrinsics_GetInfo(IAmdExtD3DShaderIntrinsics *iface, + AmdExtD3DShaderIntrinsicsInfo *info) { - FIXME("%p stub!\n", iface); + FIXME("%p %p stub!\n", iface, info); + return S_OK; } -void STDMETHODCALLTYPE AMDExtStub2_stub2(IAmdExtStub2 *iface, unsigned int unk) +HRESULT STDMETHODCALLTYPE AmdExtD3DShaderIntrinsics_CheckSupport(IAmdExtD3DShaderIntrinsics *iface, + AmdExtD3DShaderIntrinsicsSupport opcode) { - FIXME("%p %u stub!\n", iface, unk); + if (opcode == AmdExtD3DShaderIntrinsicsSupport_Float8Conversion) return S_OK; + if (opcode == AmdExtD3DShaderIntrinsicsSupport_WaveMatrix) return S_OK; + + FIXME("%p %u stub!\n", iface, opcode); + return S_OK; } -void STDMETHODCALLTYPE AMDExtStub2_stub3(IAmdExtStub2 *iface) +HRESULT STDMETHODCALLTYPE AmdExtD3DShaderIntrinsics_Enable(IAmdExtD3DShaderIntrinsics *iface) { - FIXME("%p stub!\n", iface); + TRACE("%p\n", iface); + /* shader intrinsics are always handled by vkd3d-proton */ + return S_OK; } -const static struct IAmdExtStub2Vtbl AMDSTUB2_vtable = { - AMDExtStub2_QueryInterface, - AMDExtStub2_AddRef, - AMDExtStub2_Release, - AMDExtStub2_stub1, - AMDExtStub2_stub2, - AMDExtStub2_stub3 +const static struct IAmdExtD3DShaderIntrinsicsVtbl AmdExtD3DShaderIntrinsics_vtable = { + AmdExtD3DShaderIntrinsics_QueryInterface, + AmdExtD3DShaderIntrinsics_AddRef, + AmdExtD3DShaderIntrinsics_Release, + AmdExtD3DShaderIntrinsics_GetInfo, + AmdExtD3DShaderIntrinsics_CheckSupport, + AmdExtD3DShaderIntrinsics_Enable }; -struct AMDExtStub1 +struct AmdExtD3DDevice8 { - IAmdExtStub1 IAmdExtStub1_iface; + IAmdExtD3DDevice8 IAmdExtD3DDevice8_iface; LONG ref; + BOOL fsr4_supported; }; -struct AMDExtStub1* impl_from_IAMDExtStub1(IAmdExtStub1 *iface) +struct AmdExtD3DDevice8 *impl_from_IAmdExtD3DDevice8(IAmdExtD3DDevice8 *iface) +{ + return CONTAINING_RECORD(iface, struct AmdExtD3DDevice8, IAmdExtD3DDevice8_iface); +} + +HRESULT STDMETHODCALLTYPE AmdExtD3DDevice8_QueryInterface(IAmdExtD3DDevice8 *iface, REFIID iid, void **out) { - return CONTAINING_RECORD(iface, struct AMDExtStub1, IAmdExtStub1_iface); + TRACE("%p %s %p\n", iface, debugstr_guid(iid), out); + return E_NOINTERFACE; } -ULONG STDMETHODCALLTYPE AMDExtStub1_AddRef(IAmdExtStub1 *iface) +ULONG STDMETHODCALLTYPE AmdExtD3DDevice8_AddRef(IAmdExtD3DDevice8 *iface) { - struct AMDExtStub1 *this = impl_from_IAMDExtStub1(iface); + struct AmdExtD3DDevice8* this = impl_from_IAmdExtD3DDevice8(iface); return InterlockedIncrement(&this->ref); } -ULONG STDMETHODCALLTYPE AMDExtStub1_Release(IAmdExtStub1 *iface) +ULONG STDMETHODCALLTYPE AmdExtD3DDevice8_Release(IAmdExtD3DDevice8 *iface) { - struct AMDExtStub1 *this = impl_from_IAMDExtStub1(iface); + struct AmdExtD3DDevice8* this = impl_from_IAmdExtD3DDevice8(iface); ULONG ret = InterlockedDecrement(&this->ref); if (!ret) free(this); return ret; } -HRESULT STDMETHODCALLTYPE AmdExtStub1_QueryInterface2(IAmdExtStub1 *iface, void* unk, REFIID iid, void **out) +HRESULT STDMETHODCALLTYPE AmdExtD3DDevice8_CreateGraphicsPipelineState(IAmdExtD3DDevice8 *iface, + const AmdExtD3DCreateInfo *pCreateInfo, + const D3D12_GRAPHICS_PIPELINE_STATE_DESC *pDesc, + REFIID iid, void **ppPipelineState) +{ + FIXME("%p %p %p %s %p stub!\n", iface, pCreateInfo, pDesc, debugstr_guid(iid), ppPipelineState); + return E_NOTIMPL; +} + +void STDMETHODCALLTYPE AmdExtD3DDevice8_PushMarker(IAmdExtD3DDevice8 *iface, ID3D12GraphicsCommandList *pGfxCmdList, + const char *pMarkerData) +{ + FIXME("%p %p %s stub!\n", iface, pGfxCmdList, pMarkerData); +} + +void STDMETHODCALLTYPE AmdExtD3DDevice8_PopMarker(IAmdExtD3DDevice8 *iface, ID3D12GraphicsCommandList *pGfxCmdList) +{ + FIXME("%p %p stub!\n", iface, pGfxCmdList); +} + +void STDMETHODCALLTYPE AmdExtD3DDevice8_SetMarker(IAmdExtD3DDevice8 *iface, ID3D12GraphicsCommandList *pGfxCmdList, + const char *pMarkerData) +{ + FIXME("%p %p %s stub!\n", iface, pGfxCmdList, pMarkerData); +} + +HRESULT STDMETHODCALLTYPE AmdExtD3DDevice8_CheckExtFeatureSupport(IAmdExtD3DDevice8 *iface, AmdExtD3DCheckFeatureSupportType type, + void *data, SIZE_T size) +{ + FIXME("%p %u %p %lu stub!\n", iface, type, data, (ULONG)size); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE AmdExtD3DDevice8_CreateComputePipelineState(IAmdExtD3DDevice8 *iface, + const AmdExtD3DCreateInfo* pAmdExtCreateInfo, + const D3D12_COMPUTE_PIPELINE_STATE_DESC* pDesc, + REFIID iid, void **ppPipelineState) +{ + FIXME("%p %p %p %s %p stub!\n", iface, pAmdExtCreateInfo, pDesc, debugstr_guid(iid), ppPipelineState); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE AmdExtD3DDevice8_CreatePipelineState(IAmdExtD3DDevice8 *iface, + const AmdExtD3DCreateInfo *pAmdExtCreateInfo, + const D3D12_PIPELINE_STATE_STREAM_DESC* pDesc, + REFIID iid, void **ppPipelineState) { - TRACE("%p %p %s %p\n", iface, unk, debugstr_guid(iid), out); + FIXME("%p %p %p %s %p stub!\n", iface, pAmdExtCreateInfo, pDesc, debugstr_guid(iid), ppPipelineState); + return E_NOTIMPL; +} + +void STDMETHODCALLTYPE AmdExtD3DDevice8_SetPrimitiveTopology(IAmdExtD3DDevice8 *iface, + ID3D12GraphicsCommandList *pGfxCmdList, + AmdExtD3DPrimitiveTopology topology) +{ + FIXME("%p %p %u stub!\n", iface, pGfxCmdList, topology); +} + +HRESULT STDMETHODCALLTYPE AmdExtD3DDevice8_CreateComputePipelineFromElf(IAmdExtD3DDevice8 *iface, + AmdExtD3DPipelineElfInfo *pAmdExtCreateInfo, + REFIID iid, void **ppPipelineState) +{ + FIXME("%p %p %s %p stub!\n", iface, pAmdExtCreateInfo, debugstr_guid(iid), ppPipelineState); + return E_NOTIMPL; +} - if(IsEqualGUID(iid, &IID_IAmdExtStub2)) +void STDMETHODCALLTYPE AmdExtD3DDevice8_SetKernelArguments(IAmdExtD3DDevice8 *iface, + ID3D12GraphicsCommandList *pCmdList, + ULONG first, ULONG count, const void *ppValues) +{ + FIXME("%p %p %lu %lu %p stub!\n", iface, pCmdList, first, count, ppValues); +} + +void STDMETHODCALLTYPE AmdExtD3DDevice8_GetGpuRtInterfaceVersion(IAmdExtD3DDevice8 *iface, + AmdExtD3DGpuRtVersion *pInterfaceVersion) +{ + FIXME("%p %p stub!\n", iface, pInterfaceVersion); +} + +void STDMETHODCALLTYPE AmdExtD3DDevice8_GetGpuRtBinaryVersion(IAmdExtD3DDevice8 *iface, + AmdExtD3DGpuRtVersion *pBinaryVersion) +{ + FIXME("%p %p stub!\n", iface, pBinaryVersion); +} + +HRESULT STDMETHODCALLTYPE AmdExtD3DDevice8_CreateComputePipelineCrossCompile(IAmdExtD3DDevice8 *iface, + const AmdExtD3DPipelineCrossCompileInfo* pAmdExtCreateInfo, + REFIID iid, void **ppPipelineState) +{ + FIXME("%p %p %s %p stub!\n", iface, pAmdExtCreateInfo, debugstr_guid(iid), ppPipelineState); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE AmdExtD3DDevice8_GetWaveMatrixProperties(IAmdExtD3DDevice8 *iface, + SIZE_T *pCount, AmdExtWaveMatrixProperties *pProperties) +{ + struct AmdExtD3DDevice8 *this = impl_from_IAmdExtD3DDevice8(iface); + static AmdExtWaveMatrixProperties prop[1] = {{ + 16, 16, 16, AMD_EXT_WMMA_TYPE_FP8, AMD_EXT_WMMA_TYPE_FP8, + AMD_EXT_WMMA_TYPE_FP32, AMD_EXT_WMMA_TYPE_FP32, FALSE}}; + + TRACE("%p %p %p\n", iface, pCount, pProperties); + + if (!pCount) return E_INVALIDARG; + + if (*pCount >= 1) { - struct AMDExtStub2 *this = calloc(1, sizeof(struct AMDExtStub2)); + if (this->fsr4_supported) + { + *pCount = 1; + memcpy(pProperties, prop, sizeof(prop)); + return S_OK; + } else { + *pCount = 0; + return S_OK; + } + } /* FIXME: Handle pCount == 0 */ + + return S_OK; +} + +static const struct IAmdExtD3DDevice8Vtbl AmdExtD3DDevice8_vtable = { + AmdExtD3DDevice8_QueryInterface, + AmdExtD3DDevice8_AddRef, + AmdExtD3DDevice8_Release, + AmdExtD3DDevice8_CreateGraphicsPipelineState, + AmdExtD3DDevice8_PushMarker, + AmdExtD3DDevice8_PopMarker, + AmdExtD3DDevice8_SetMarker, + AmdExtD3DDevice8_CheckExtFeatureSupport, + AmdExtD3DDevice8_CreateComputePipelineState, + AmdExtD3DDevice8_CreatePipelineState, + AmdExtD3DDevice8_SetPrimitiveTopology, + AmdExtD3DDevice8_CreateComputePipelineFromElf, + AmdExtD3DDevice8_SetKernelArguments, + AmdExtD3DDevice8_GetGpuRtInterfaceVersion, + AmdExtD3DDevice8_GetGpuRtBinaryVersion, + AmdExtD3DDevice8_CreateComputePipelineCrossCompile, + AmdExtD3DDevice8_GetWaveMatrixProperties +}; - this->IAmdExtStub2_iface.lpVtbl = &AMDSTUB2_vtable; +struct AmdExtD3DFactory +{ + IAmdExtD3DFactory IAmdExtD3DFactory_iface; + LONG ref; +}; + +struct AmdExtD3DFactory* impl_from_IAmdExtD3DFactory(IAmdExtD3DFactory *iface) +{ + return CONTAINING_RECORD(iface, struct AmdExtD3DFactory, IAmdExtD3DFactory_iface); +} + +ULONG STDMETHODCALLTYPE AmdExtD3DFactory_AddRef(IAmdExtD3DFactory *iface) +{ + struct AmdExtD3DFactory *this = impl_from_IAmdExtD3DFactory(iface); + return InterlockedIncrement(&this->ref); +} + +ULONG STDMETHODCALLTYPE AmdExtD3DFactory_Release(IAmdExtD3DFactory *iface) +{ + struct AmdExtD3DFactory *this = impl_from_IAmdExtD3DFactory(iface); + ULONG ret = InterlockedDecrement(&this->ref); + if (!ret) free(this); + return ret; +} + +HRESULT STDMETHODCALLTYPE AmdExtD3DFactory_CreateInterface(IAmdExtD3DFactory *iface, IUnknown *outer, REFIID iid, void **out) +{ + TRACE("%p %p %s %p\n", iface, outer, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IAmdExtD3DShaderIntrinsics)) + { + struct AmdExtD3DShaderIntrinsics *this = calloc(1, sizeof(struct AmdExtD3DShaderIntrinsics)); + this->IAmdExtD3DShaderIntrinsics_iface.lpVtbl = &AmdExtD3DShaderIntrinsics_vtable; this->ref = 1; - *out = &this->IAmdExtStub2_iface; + *out = &this->IAmdExtD3DShaderIntrinsics_iface; + return S_OK; + } else if (IsEqualGUID(iid, &IID_IAmdExtD3DDevice8)) { + struct AmdExtD3DDevice8 *this = calloc(1, sizeof(struct AmdExtD3DDevice8)); + this->IAmdExtD3DDevice8_iface.lpVtbl = &AmdExtD3DDevice8_vtable; + this->ref = 1; + this->fsr4_supported = check_fsr4_supported((ID3D12Device *)outer); + TRACE("FSR 4 supported: %d\n", this->fsr4_supported); + *out = &this->IAmdExtD3DDevice8_iface; return S_OK; } else { FIXME("unknown guid %s\n", debugstr_guid(iid)); @@ -209,16 +480,17 @@ HRESULT STDMETHODCALLTYPE AmdExtStub1_QueryInterface2(IAmdExtStub1 *iface, void* return E_NOINTERFACE; } -HRESULT STDMETHODCALLTYPE AmdExtStub1_QueryInterface(IAmdExtStub1 *iface, REFIID iid, void **out) +HRESULT STDMETHODCALLTYPE AmdExtD3DFactory_QueryInterface(IAmdExtD3DFactory *iface, REFIID iid, void **out) { - return AmdExtStub1_QueryInterface2(iface, NULL, iid, out); + TRACE("%p %s %p\n", iface, debugstr_guid(iid), out); + return E_NOINTERFACE; } -static const struct IAmdExtStub1Vtbl AMDSTUB1_vtable = { - AmdExtStub1_QueryInterface, - AMDExtStub1_AddRef, - AMDExtStub1_Release, - AmdExtStub1_QueryInterface2 +static const struct IAmdExtD3DFactoryVtbl AmdExtD3DFactory_vtable = { + AmdExtD3DFactory_QueryInterface, + AmdExtD3DFactory_AddRef, + AmdExtD3DFactory_Release, + AmdExtD3DFactory_CreateInterface }; HRESULT CDECL AmdExtD3DCreateInterface(IUnknown *outer, REFIID iid, void **obj) @@ -230,15 +502,17 @@ HRESULT CDECL AmdExtD3DCreateInterface(IUnknown *outer, REFIID iid, void **obj) struct AMDFSR4FFX* ffx = calloc(1, sizeof(struct AMDFSR4FFX)); ffx->IAmdExtFfxApi_iface.lpVtbl = &AMDFSR4FFX_vtable; ffx->ref = 1; + ffx->fsr4_supported = check_fsr4_supported((ID3D12Device *)outer); + TRACE("FSR 4 supported: %d\n", ffx->fsr4_supported); *obj = &ffx->IAmdExtFfxApi_iface; return S_OK; } else if (IsEqualGUID(iid, &IID_IAmdExtAntiLagApi)) { return ID3D12Device_QueryInterface((ID3D12Device *)outer, &IID_IAmdExtAntiLagApi, obj); - } else if(IsEqualGUID(iid, &IID_IAmdExtStub1)) { - struct AMDExtStub1 *this = calloc(1, sizeof(struct AMDExtStub1)); - this->IAmdExtStub1_iface.lpVtbl = &AMDSTUB1_vtable; + } else if(IsEqualGUID(iid, &IID_IAmdExtD3DFactory)) { + struct AmdExtD3DFactory *this = calloc(1, sizeof(struct AmdExtD3DFactory)); + this->IAmdExtD3DFactory_iface.lpVtbl = &AmdExtD3DFactory_vtable; this->ref = 1; - *obj = &this->IAmdExtStub1_iface; + *obj = &this->IAmdExtD3DFactory_iface; return S_OK; } else { FIXME("unknown guid: %s\n", debugstr_guid(iid)); @@ -251,3 +525,23 @@ HMODULE WINAPI AmdGetDxcModuleHandle(void) { return GetModuleHandleA(NULL); } + +BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved) +{ + const char *env; + + switch (reason) + { + case DLL_PROCESS_ATTACH: + { + if ((env = getenv("FSR4_WATERMARK")) && !strcmp(env, "1")) + { + _putenv("MLSR-WATERMARK=1"); + } + break; + } + default: break; + } + + return TRUE; +}