@@ -360,6 +360,13 @@ HRESULT WINAPI hk_D3D11CreateDeviceAndSwapChain(
360360 if (streamline->featureDLSSG ) {
361361 logger::info (" [Frame Generation] Using D3D12 proxy via Streamline" );
362362
363+ if (globals::state->IsHdrRendering ()) {
364+ logger::info (" [Streamline] Enabling 10bit swapchain" );
365+ pSwapChainDesc->BufferDesc .Format = DXGI_FORMAT_R10G10B10A2_UNORM;
366+ logger::info (" [Streamline] Enabling BT.2020 ST2084 (PQ) HDR colorspace" );
367+ pSwapChainDesc->BufferDesc .ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
368+ }
369+
363370 auto ret = streamline->slD3D11CreateDeviceAndSwapChain (pAdapter,
364371 DriverType,
365372 Software,
@@ -434,6 +441,13 @@ HRESULT WINAPI hk_D3D11CreateDeviceAndSwapChain(
434441 }
435442 }
436443
444+ if (globals::state->IsHdrRendering ()) {
445+ logger::info (" [Hooks] Enabling 10bit swapchain" );
446+ pSwapChainDesc->BufferDesc .Format = DXGI_FORMAT_R10G10B10A2_UNORM;
447+ logger::info (" [Hooks] Enabling HDR colorspace" );
448+ pSwapChainDesc->BufferDesc .ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
449+ }
450+
437451 auto ret = ptrD3D11CreateDeviceAndSwapChain (pAdapter,
438452 DriverType,
439453 Software,
@@ -447,7 +461,63 @@ HRESULT WINAPI hk_D3D11CreateDeviceAndSwapChain(
447461 pFeatureLevel,
448462 ppImmediateContext);
449463
464+ if (globals::state->IsHdrRendering ()) {
465+ logger::info (" [Hooks] Setting HDR metadata" );
466+ IDXGISwapChain4* swapChain4 = nullptr ;
467+ IDXGIOutput* output = nullptr ;
468+ IDXGIOutput6* output6 = nullptr ;
469+ DXGI_OUTPUT_DESC1 displayDesc = {};
470+ DXGI_HDR_METADATA_HDR10 metadata = {};
471+
472+ if (SUCCEEDED ((*ppSwapChain)->QueryInterface (__uuidof (IDXGISwapChain4), (void **)&swapChain4))) {
473+ swapChain4->GetContainingOutput (&output);
474+ output->QueryInterface (IID_PPV_ARGS (&output6));
475+ output6->GetDesc1 (&displayDesc);
476+
477+ // Log color primaries
478+ logger::info (" Display Color Primaries:" );
479+ logger::info (" Red Primary: ({:.4f}, {:.4f})" , displayDesc.RedPrimary [0 ], displayDesc.RedPrimary [1 ]);
480+ logger::info (" Green Primary: ({:.4f}, {:.4f})" , displayDesc.GreenPrimary [0 ], displayDesc.GreenPrimary [1 ]);
481+ logger::info (" Blue Primary: ({:.4f}, {:.4f})" , displayDesc.BluePrimary [0 ], displayDesc.BluePrimary [1 ]);
482+ logger::info (" White Point: ({:.4f}, {:.4f})" , displayDesc.WhitePoint [0 ], displayDesc.WhitePoint [1 ]);
483+
484+ // Log luminance values
485+ logger::info (" Display Luminance Range:" );
486+ logger::info (" Min Luminance: {:.2f} nits" , displayDesc.MinLuminance );
487+ logger::info (" Max Luminance: {:.2f} nits" , displayDesc.MaxLuminance );
488+ logger::info (" MaxFullFrameLuminance: {:.2f} nits" , displayDesc.MaxFullFrameLuminance );
489+
490+ // Convert display primaries (display values are 0-1, metadata needs them scaled by 50000)
491+ metadata.RedPrimary [0 ] = static_cast <UINT16>(displayDesc.RedPrimary [0 ] * 50000 );
492+ metadata.RedPrimary [1 ] = static_cast <UINT16>(displayDesc.RedPrimary [1 ] * 50000 );
493+
494+ metadata.GreenPrimary [0 ] = static_cast <UINT16>(displayDesc.GreenPrimary [0 ] * 50000 );
495+ metadata.GreenPrimary [1 ] = static_cast <UINT16>(displayDesc.GreenPrimary [1 ] * 50000 );
496+
497+ metadata.BluePrimary [0 ] = static_cast <UINT16>(displayDesc.BluePrimary [0 ] * 50000 );
498+ metadata.BluePrimary [1 ] = static_cast <UINT16>(displayDesc.BluePrimary [1 ] * 50000 );
499+
500+ metadata.WhitePoint [0 ] = static_cast <UINT16>(displayDesc.WhitePoint [0 ] * 50000 );
501+ metadata.WhitePoint [1 ] = static_cast <UINT16>(displayDesc.WhitePoint [1 ] * 50000 );
502+
503+ metadata.MaxMasteringLuminance = 1000 ; // Pulled out of my ass, 10 times the SDR, whole nits
504+ metadata.MinMasteringLuminance = 1000 ; // 0.1 nits = 1000 * 0.0001, black is black, 1/10000th of a nit
505+
506+ // Set content light levels (these are in actual nits)
507+ metadata.MaxContentLightLevel = static_cast <UINT16>(displayDesc.MaxLuminance );
508+ metadata.MaxFrameAverageLightLevel = static_cast <UINT16>(displayDesc.MaxFullFrameLuminance );
509+
510+ swapChain4->SetColorSpace1 (DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
511+ swapChain4->SetHDRMetaData (DXGI_HDR_METADATA_TYPE_HDR10, sizeof (metadata), &metadata);
512+
513+ output6->Release ();
514+ output->Release ();
515+ swapChain4->Release ();
516+ }
517+ }
518+
450519 if (streamline->initialized ) {
520+ logger::info (" [Hooks] Setting Streamline D3D device" );
451521 streamline->slSetD3DDevice (*ppDevice);
452522 streamline->PostDevice ();
453523 }
@@ -563,12 +633,99 @@ namespace Hooks
563633 {
564634 static void thunk (RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties)
565635 {
636+ if (globals::state->IsHdrRendering ()) {
637+ a_properties->format = RE::BSGraphics::Format::kR16G16B16A16_FLOAT ;
638+ }
566639 globals::state->ModifyRenderTarget (a_target, a_properties);
567640 func (This, a_target, a_properties);
568641 }
569642 static inline REL::Relocation<decltype (thunk)> func;
570643 };
571644
645+ struct CreateRenderTarget_ImagespaceTempCopy
646+ {
647+ static void thunk (RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties)
648+ {
649+ if (globals::state->IsHdrRendering ()) {
650+ a_properties->format = RE::BSGraphics::Format::kR16G16B16A16_FLOAT ;
651+ }
652+ globals::state->ModifyRenderTarget (a_target, a_properties);
653+ func (This, a_target, a_properties);
654+ }
655+
656+ static inline REL::Relocation<decltype (thunk)> func;
657+ };
658+
659+ struct CreateRenderTarget_ImagespaceTempCopy2
660+ {
661+ static void thunk (RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties)
662+ {
663+ if (globals::state->IsHdrRendering ()) {
664+ a_properties->format = RE::BSGraphics::Format::kR16G16B16A16_FLOAT ;
665+ }
666+ globals::state->ModifyRenderTarget (a_target, a_properties);
667+ func (This, a_target, a_properties);
668+ }
669+
670+ static inline REL::Relocation<decltype (thunk)> func;
671+ };
672+
673+ struct CreateRenderTarget_LDRBlurSwap
674+ {
675+ static void thunk (RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties)
676+ {
677+ if (globals::state->IsHdrRendering ()) {
678+ a_properties->format = RE::BSGraphics::Format::kR16G16B16A16_FLOAT ;
679+ }
680+ globals::state->ModifyRenderTarget (a_target, a_properties);
681+ func (This, a_target, a_properties);
682+ }
683+
684+ static inline REL::Relocation<decltype (thunk)> func;
685+ };
686+
687+ struct CreateRenderTarget_LDRDownsample
688+ {
689+ static void thunk (RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties)
690+ {
691+ if (globals::state->IsHdrRendering ()) {
692+ a_properties->format = RE::BSGraphics::Format::kR16G16B16A16_FLOAT ;
693+ }
694+ globals::state->ModifyRenderTarget (a_target, a_properties);
695+ func (This, a_target, a_properties);
696+ }
697+
698+ static inline REL::Relocation<decltype (thunk)> func;
699+ };
700+
701+ struct CreateRenderTarget_TemporalAAAccumulation0
702+ {
703+ static void thunk (RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties)
704+ {
705+ if (globals::state->IsHdrRendering ()) {
706+ a_properties->format = RE::BSGraphics::Format::kR16G16B16A16_FLOAT ;
707+ }
708+ globals::state->ModifyRenderTarget (a_target, a_properties);
709+ func (This, a_target, a_properties);
710+ }
711+
712+ static inline REL::Relocation<decltype (thunk)> func;
713+ };
714+
715+ struct CreateRenderTarget_TemporalAAAccumulation1
716+ {
717+ static void thunk (RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties)
718+ {
719+ if (globals::state->IsHdrRendering ()) {
720+ a_properties->format = RE::BSGraphics::Format::kR16G16B16A16_FLOAT ;
721+ }
722+ globals::state->ModifyRenderTarget (a_target, a_properties);
723+ func (This, a_target, a_properties);
724+ }
725+
726+ static inline REL::Relocation<decltype (thunk)> func;
727+ };
728+
572729 struct CreateRenderTarget_Normals
573730 {
574731 static void thunk (RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties)
@@ -958,6 +1115,12 @@ namespace Hooks
9581115
9591116 logger::info (" Hooking BSShaderRenderTargets::Create::CreateRenderTarget(s)" );
9601117 stl::write_thunk_call<CreateRenderTarget_Main>(REL::RelocationID (100458 , 107175 ).address () + REL::Relocate (0x3F0 , 0x3F3 , 0x548 ));
1118+ stl::write_thunk_call<CreateRenderTarget_ImagespaceTempCopy>(REL::RelocationID (100458 , 107175 ).address () + REL::Relocate (0x62F , 0x62E ));
1119+ stl::write_thunk_call<CreateRenderTarget_ImagespaceTempCopy2>(REL::RelocationID (100458 , 107175 ).address () + REL::Relocate (0x642 , 0x641 ));
1120+ stl::write_thunk_call<CreateRenderTarget_LDRBlurSwap>(REL::RelocationID (100458 , 107175 ).address () + REL::Relocate (0x529 , 0x528 ));
1121+ stl::write_thunk_call<CreateRenderTarget_LDRDownsample>(REL::RelocationID (100458 , 107175 ).address () + REL::Relocate (0xB2E , 0xB2E ));
1122+ stl::write_thunk_call<CreateRenderTarget_TemporalAAAccumulation0>(REL::RelocationID (100458 , 107175 ).address () + REL::Relocate (0xE68 , 0xE6A ));
1123+ stl::write_thunk_call<CreateRenderTarget_TemporalAAAccumulation1>(REL::RelocationID (100458 , 107175 ).address () + REL::Relocate (0xE7E , 0xE80 ));
9611124 stl::write_thunk_call<CreateRenderTarget_Normals>(REL::RelocationID (100458 , 107175 ).address () + REL::Relocate (0x458 , 0x45B , 0x5B0 ));
9621125 stl::write_thunk_call<CreateRenderTarget_NormalsSwap>(REL::RelocationID (100458 , 107175 ).address () + REL::Relocate (0x46B , 0x46E , 0x5C3 ));
9631126 stl::write_thunk_call<CreateRenderTarget_Snow>(REL::RelocationID (100458 , 107175 ).address () + REL::Relocate (0x406 , 0x409 , 0x55e ));
0 commit comments