Skip to content

Commit 0377e57

Browse files
committed
amd_ags_x64: Implement agsSetDisplayMode
Gets HDR working with Elden Ring. Signed-off-by: Joshua Ashton <[email protected]>
1 parent 02f0a32 commit 0377e57

File tree

2 files changed

+120
-1
lines changed

2 files changed

+120
-1
lines changed

dlls/amd_ags_x64/amd_ags_x64_main.c

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ struct AGSContext
136136
VkPhysicalDeviceProperties *properties;
137137
VkPhysicalDeviceMemoryProperties *memory_properties;
138138
IDXGIFactory1 *dxgi_factory;
139+
IDXGIVkInteropFactory1 *dxgi_interop;
139140
ID3D11DeviceContext *d3d11_context;
140141
AGSDX11ExtensionsSupported_600 extensions;
141142
};
@@ -538,6 +539,12 @@ static AGSReturnCode init_ags_context(AGSContext *context)
538539
return AGS_DX_FAILURE;
539540
}
540541

542+
if (FAILED(IDXGIFactory1_QueryInterface(context->dxgi_factory, &IID_IDXGIVkInteropFactory1, (void**)&context->dxgi_interop)))
543+
{
544+
ERR("Failed to get IDXGIVkInteropFactory1.\n");
545+
return AGS_DX_FAILURE;
546+
}
547+
541548
context->version = determine_ags_version();
542549

543550
ret = vk_get_physical_device_properties(&context->device_count, &context->properties, &context->memory_properties);
@@ -711,6 +718,11 @@ AGSReturnCode WINAPI agsDeInitialize(AGSContext *context)
711718
if (!context)
712719
return AGS_SUCCESS;
713720

721+
if (context->dxgi_interop)
722+
{
723+
IDXGIVkInteropFactory1_Release(context->dxgi_interop);
724+
context->dxgi_interop = NULL;
725+
}
714726
if (context->dxgi_factory)
715727
{
716728
IDXGIFactory1_Release(context->dxgi_factory);
@@ -735,14 +747,85 @@ AGSReturnCode WINAPI agsDeInitialize(AGSContext *context)
735747
return AGS_SUCCESS;
736748
}
737749

750+
static DXGI_COLOR_SPACE_TYPE convert_ags_colorspace_506(AGSDisplaySettings_Mode_506 mode)
751+
{
752+
switch (mode)
753+
{
754+
default:
755+
ERR("Unknown color space in AGS: %d\n", mode);
756+
/* fallthrough */
757+
case Mode_506_SDR:
758+
TRACE("Setting Mode_506_SDR!\n");
759+
return DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
760+
case Mode_506_PQ:
761+
TRACE("Setting Mode_506_PQ!\n");
762+
return DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
763+
case Mode_506_scRGB:
764+
TRACE("Setting Mode_506_scRGB!\n");
765+
return DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
766+
}
767+
}
768+
769+
static DXGI_COLOR_SPACE_TYPE convert_ags_colorspace_600(AGSDisplaySettings_Mode_600 mode)
770+
{
771+
switch (mode)
772+
{
773+
default:
774+
ERR("Unknown color space in AGS: %d\n", mode);
775+
/* fallthrough */
776+
case Mode_600_SDR:
777+
TRACE("Setting Mode_600_SDR!\n");
778+
return DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
779+
case Mode_600_HDR10_PQ:
780+
TRACE("Setting Mode_600_HDR10_PQ!\n");
781+
return DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
782+
case Mode_600_HDR10_scRGB:
783+
TRACE("Setting Mode_600_HDR10_scRGB!\n");
784+
return DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
785+
}
786+
}
787+
788+
static DXGI_HDR_METADATA_HDR10 convert_ags_metadata(const AGSDisplaySettings_600 *settings)
789+
{
790+
DXGI_HDR_METADATA_HDR10 metadata;
791+
metadata.RedPrimary[0] = settings->chromaticityRedX * 50000;
792+
metadata.RedPrimary[1] = settings->chromaticityRedY * 50000;
793+
metadata.GreenPrimary[0] = settings->chromaticityGreenX * 50000;
794+
metadata.GreenPrimary[1] = settings->chromaticityGreenY * 50000;
795+
metadata.BluePrimary[0] = settings->chromaticityBlueX * 50000;
796+
metadata.BluePrimary[1] = settings->chromaticityBlueY * 50000;
797+
metadata.WhitePoint[0] = settings->chromaticityWhitePointX * 50000;
798+
metadata.WhitePoint[1] = settings->chromaticityWhitePointY * 50000;
799+
metadata.MaxMasteringLuminance = settings->maxLuminance;
800+
metadata.MinMasteringLuminance = settings->minLuminance / 0.0001f;
801+
metadata.MaxContentLightLevel = settings->maxContentLightLevel;
802+
metadata.MaxFrameAverageLightLevel = settings->maxFrameAverageLightLevel;
803+
return metadata;
804+
}
805+
738806
AGSReturnCode WINAPI agsSetDisplayMode(AGSContext *context, int device_index, int display_index, const AGSDisplaySettings *settings)
739807
{
740-
FIXME("context %p device_index %d display_index %d settings %p stub!\n", context, device_index,
808+
const AGSDisplaySettings_506 *settings506 = &settings->agsDisplaySettings506;
809+
const AGSDisplaySettings_600 *settings600 = &settings->agsDisplaySettings600;
810+
DXGI_COLOR_SPACE_TYPE colorspace;
811+
DXGI_HDR_METADATA_HDR10 metadata;
812+
813+
TRACE("context %p device_index %d display_index %d settings %p\n", context, device_index,
741814
display_index, settings);
742815

743816
if (!context)
744817
return AGS_INVALID_ARGS;
745818

819+
colorspace = context->version < AMD_AGS_VERSION_5_1_1
820+
? convert_ags_colorspace_506(settings506->mode)
821+
: convert_ags_colorspace_600(settings600->mode);
822+
/* Settings 506, 511 and 600 are identical aside from enum order + use
823+
* of bitfield flags we do not use. */
824+
metadata = convert_ags_metadata(settings600);
825+
826+
if (FAILED(IDXGIVkInteropFactory1_SetGlobalHDRState(context->dxgi_interop, colorspace, &metadata)))
827+
return AGS_DX_FAILURE;
828+
746829
return AGS_SUCCESS;
747830
}
748831

dlls/amd_ags_x64/dxvk_interfaces.idl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
*/
1818

1919
import "d3d11.idl";
20+
import "dxgi1_6.idl";
21+
22+
typedef struct VkInstance_T *VkInstance;
23+
typedef void (__stdcall *PFN_vkVoidFunction)(void);
24+
typedef PFN_vkVoidFunction (__stdcall *PFN_vkGetInstanceProcAddr)(VkInstance instance, const char* pName);
2025

2126
typedef enum D3D11_VK_EXTENSION
2227
{
@@ -114,3 +119,34 @@ interface ID3D11VkExtContext1 : ID3D11VkExtContext
114119
[in] const void *params, [in] UINT32 param_size, [in] void * const *read_resources,
115120
[in] UINT32 read_resource_count, [in] void* const *write_resources, [in] UINT32 write_resources_count);
116121
}
122+
123+
[
124+
object,
125+
uuid(4c5e1b0d-b0c8-4131-bfd8-9b2476f7f408),
126+
local,
127+
pointer_default(unique)
128+
]
129+
interface IDXGIVkInteropFactory : IUnknown
130+
{
131+
void GetVulkanInstance(
132+
[out] VkInstance *pInstance,
133+
[out] PFN_vkGetInstanceProcAddr *ppfnVkGetInstanceProcAddr);
134+
}
135+
136+
[
137+
object,
138+
uuid(2a289dbd-2d0a-4a51-89f7-f2adce465cd6),
139+
local,
140+
pointer_default(unique)
141+
]
142+
interface IDXGIVkInteropFactory1 : IDXGIVkInteropFactory
143+
{
144+
HRESULT GetGlobalHDRState(
145+
[out] DXGI_COLOR_SPACE_TYPE *pOutColorSpace,
146+
[out] DXGI_HDR_METADATA_HDR10 *ppOutMetadata) = 0;
147+
148+
HRESULT SetGlobalHDRState(
149+
[in] DXGI_COLOR_SPACE_TYPE ColorSpace,
150+
[in] const DXGI_HDR_METADATA_HDR10 *pMetadata) = 0;
151+
}
152+

0 commit comments

Comments
 (0)