Skip to content

Commit 513a818

Browse files
committed
fix(dlss): improve StreamlineV2 interface wrapping
- guard DXGI factory wrapping against unsupported flags to avoid steam overlay hooking - validate proxy factory lookup and Streamline upgrade results - hook D3D12GetInterface - reuse thread-local buffers when rewriting resource tags
1 parent 4c0bb97 commit 513a818

1 file changed

Lines changed: 161 additions & 51 deletions

File tree

src/utils/dlss/streamline_v2.hpp

Lines changed: 161 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ SL_API sl::Result Hooked_slInit(const sl::Preferences& pref, uint64_t sdkVersion
164164
return sl::Result::eOk;
165165
}
166166

167-
#if defined(DEBUG_LEVEL_1) && !defined(NDEBUG)
167+
#if defined(DEBUG_LEVEL_3) && !defined(NDEBUG)
168168
const auto ret = Real_slInit(pref_copy, sdkVersion);
169169
#else
170170
const auto ret = Real_slInit(pref, sdkVersion);
@@ -199,6 +199,10 @@ struct TrackedCommandQueueInfo {
199199
using TrackedCommandQueueMap = utils::data::ParallelFlatHashMap<ID3D12CommandQueue*, TrackedCommandQueueInfo, std::shared_mutex>;
200200
TrackedCommandQueueMap tracked_command_queues;
201201

202+
static constexpr bool SUPPORT_UNKNOWN_CREATE_DXGI_FACTORY2_FLAGS = false;
203+
// Only zero and DXGI_CREATE_FACTORY_DEBUG are documented; bypass RenoDX/Streamline factory wrapping for anything else unless explicitly enabled above.
204+
static constexpr UINT CREATE_DXGI_FACTORY2_ALLOWED_FLAGS = DXGI_CREATE_FACTORY_DEBUG;
205+
202206
// Result slUpgradeInterface(void** baseInterface)
203207
extern "C" decltype(&slUpgradeInterface) Real_slUpgradeInterface = nullptr;
204208
extern "C" sl::Result Hooked_slUpgradeInterface(void** baseInterface) {
@@ -257,18 +261,21 @@ extern "C" sl::Result Hooked_slUpgradeInterface(void** baseInterface) {
257261

258262
IDXGIFactory7* dxgi_factory7{};
259263
if (SUCCEEDED(unknown->QueryInterface(&dxgi_factory7))) {
260-
// dxgiFactory7->Release();
261-
262264
// Upgrade ReShade's internal factory to use the Streamline factory
263265
DXGIFactory* reshade_factory = nullptr;
264266
UINT size = sizeof(reshade_factory);
265-
dxgi_factory7->GetPrivateData(__uuidof(DXGIFactory), &size, &reshade_factory);
266-
if (reshade_factory == nullptr) {
267+
const HRESULT proxy_result = dxgi_factory7->GetPrivateData(__uuidof(DXGIFactory), &size, &reshade_factory);
268+
if (FAILED(proxy_result) || reshade_factory == nullptr) {
267269
log::e("utils::streamline_v2::slUpgradeInterface() - Failed to get DXGIFactory proxy from IDXGIFactory7");
270+
return Real_slUpgradeInterface(baseInterface);
268271
}
269272
auto* Real_factory = (IDXGIFactory7*)reshade_factory->_orig;
270273

271-
Real_slUpgradeInterface((void**)&Real_factory);
274+
auto ret = Real_slUpgradeInterface((void**)&Real_factory);
275+
if (ret != sl::Result::eOk) {
276+
log::e("utils::streamline_v2::slUpgradeInterface() - Failed to upgrade DXGIFactory interface");
277+
return ret;
278+
}
272279

273280
reshade_factory->_orig = Real_factory;
274281

@@ -564,13 +571,58 @@ extern "C" HRESULT Hooked_D3D12CreateDevice(IUnknown* pAdapter, D3D_FEATURE_LEVE
564571
// assert(IsDebuggerPresent());
565572
renodx::utils::directx::Initialize();
566573

574+
#ifdef DEBUG_LEVEL_0
575+
log::i(std::format(
576+
"utils::streamline_v2::D3D12CreateDevice(adapter: {:p}, feature_level: {:#x}, ppDevice: {:p})",
577+
(void*)pAdapter,
578+
static_cast<uint32_t>(MinimumFeatureLevel),
579+
(void*)ppDevice)
580+
.c_str());
581+
#endif
582+
567583
assert(is_streamline_device == false);
568584
is_streamline_device = true;
569585
auto hr = renodx::utils::directx::pD3D12CreateDevice != nullptr
570586
? renodx::utils::directx::pD3D12CreateDevice(pAdapter, MinimumFeatureLevel, riid, ppDevice)
571587
: E_FAIL;
572588
is_streamline_device = false;
573589

590+
#ifdef DEBUG_LEVEL_0
591+
log::i(std::format(
592+
"utils::streamline_v2::D3D12CreateDevice -> hr: {:#010x}, device: {:p}",
593+
static_cast<uint32_t>(hr),
594+
ppDevice != nullptr ? *ppDevice : nullptr)
595+
.c_str());
596+
#endif
597+
598+
return hr;
599+
}
600+
601+
extern "C" decltype(&D3D12GetInterface) Real_D3D12GetInterface = nullptr;
602+
extern "C" HRESULT Hooked_D3D12GetInterface(REFCLSID rclsid, REFIID riid, void** ppvDebug) {
603+
renodx::utils::directx::Initialize();
604+
605+
#ifdef DEBUG_LEVEL_0
606+
log::i(std::format(
607+
"utils::streamline_v2::D3D12GetInterface(rclsid: {}, riid: {}, out: {:p})",
608+
rclsid.Data1,
609+
riid.Data1,
610+
(void*)ppvDebug)
611+
.c_str());
612+
#endif
613+
614+
auto hr = renodx::utils::directx::pD3D12GetInterface != nullptr
615+
? renodx::utils::directx::pD3D12GetInterface(rclsid, riid, ppvDebug)
616+
: E_NOINTERFACE;
617+
618+
#ifdef DEBUG_LEVEL_0
619+
log::i(std::format(
620+
"utils::streamline_v2::D3D12GetInterface -> hr: {:#010x}, interface: {:p}",
621+
static_cast<uint32_t>(hr),
622+
ppvDebug != nullptr ? *ppvDebug : nullptr)
623+
.c_str());
624+
#endif
625+
574626
return hr;
575627
}
576628

@@ -582,33 +634,77 @@ extern "C" HRESULT Hooked_CreateDXGIFactory1(REFIID riid, void** ppFactory) {
582634
static decltype(&CreateDXGIFactory2) Real_CreateDXGIFactory2 = nullptr;
583635
SL_API HRESULT Hooked_CreateDXGIFactory2(UINT flags, REFIID riid, void** ppFactory) {
584636
renodx::utils::directx::Initialize();
637+
#ifdef DEBUG_LEVEL_0
638+
log::i(std::format(
639+
"utils::streamline_v2::CreateDXGIFactory2(flags: {:#x}, ppFactory: {:p})",
640+
flags,
641+
(void*)ppFactory)
642+
.c_str());
643+
#endif
644+
645+
if (!SUPPORT_UNKNOWN_CREATE_DXGI_FACTORY2_FLAGS && (flags & ~CREATE_DXGI_FACTORY2_ALLOWED_FLAGS) != 0u) {
646+
if (renodx::utils::directx::pCreateDXGIFactory2 != nullptr) {
647+
return renodx::utils::directx::pCreateDXGIFactory2(flags, riid, ppFactory);
648+
}
649+
if (Real_CreateDXGIFactory2 != nullptr) {
650+
return Real_CreateDXGIFactory2(flags, riid, ppFactory);
651+
}
652+
return E_NOINTERFACE;
653+
}
654+
655+
if (ppFactory == nullptr) {
656+
return E_POINTER;
657+
}
658+
659+
if (renodx::utils::directx::pCreateDXGIFactory2 == nullptr) {
660+
return E_NOINTERFACE;
661+
}
662+
585663
// Make real ReShade Factory instead of Streamline factory
586664
IDXGIFactory2* unknown = nullptr;
587665
auto ret = renodx::utils::directx::pCreateDXGIFactory2(flags, riid, reinterpret_cast<void**>(&unknown));
588-
if (ret != S_OK) {
666+
#ifdef DEBUG_LEVEL_0
667+
log::i(std::format(
668+
"utils::streamline_v2::CreateDXGIFactory2 -> reshade hr: {:#010x}, unknown: {:p}",
669+
static_cast<uint32_t>(ret),
670+
(void*)unknown)
671+
.c_str());
672+
#endif
673+
if (FAILED(ret) || unknown == nullptr) {
589674
log::e("utils::streamline_v2::CreateDXGIFactory2() - Failed to create DXGIFactory2");
590675
return ret;
591676
}
592-
IDXGIFactory7* dxgi_factory7{};
593-
if (SUCCEEDED(unknown->QueryInterface(&dxgi_factory7))) {
594-
dxgi_factory7->Release();
595-
596-
// Upgrade ReShade's internal factory to use the Streamline factory
597-
DXGIFactory* reshade_factory = nullptr;
598-
UINT size = sizeof(reshade_factory);
599-
dxgi_factory7->GetPrivateData(__uuidof(DXGIFactory), &size, &reshade_factory);
600-
if (reshade_factory == nullptr) {
601-
log::e("utils::streamline_v2::CreateDXGIFactory2() - Failed to get DXGIFactory proxy from IDXGIFactory7");
602-
}
603-
auto* real_factory = (IDXGIFactory7*)reshade_factory->_orig;
604677

605-
Real_slUpgradeInterface((void**)&real_factory); // Now Streamline factory
678+
*ppFactory = unknown;
606679

607-
reshade_factory->_orig = real_factory;
680+
// Upgrade ReShade's internal factory to use the Streamline factory
681+
DXGIFactory* reshade_factory = nullptr;
682+
UINT size = sizeof(reshade_factory);
683+
const HRESULT proxy_result = unknown->GetPrivateData(__uuidof(DXGIFactory), &size, &reshade_factory);
684+
if (FAILED(proxy_result) || reshade_factory == nullptr) {
685+
log::e("utils::streamline_v2::CreateDXGIFactory2() - Failed to get DXGIFactory proxy from IDXGIFactory7");
686+
return ret;
687+
}
688+
auto* real_factory = (IDXGIFactory7*)reshade_factory->_orig;
608689

609-
*ppFactory = reshade_factory;
690+
auto upgrade_result = Real_slUpgradeInterface((void**)&real_factory); // Now Streamline factory
691+
if (upgrade_result != sl::Result::eOk || real_factory == nullptr) {
692+
log::e("utils::streamline_v2::CreateDXGIFactory2() - Failed to upgrade DXGIFactory interface");
693+
return ret;
610694
}
611695

696+
#ifdef DEBUG_LEVEL_0
697+
log::i(std::format(
698+
"utils::streamline_v2::CreateDXGIFactory2 -> upgraded factory: reshade {:p}, original {:p}",
699+
(void*)reshade_factory,
700+
(void*)real_factory)
701+
.c_str());
702+
#endif
703+
704+
reshade_factory->_orig = real_factory;
705+
706+
*ppFactory = reshade_factory;
707+
612708
return ret;
613709
}
614710

@@ -903,8 +999,17 @@ static sl::Result Hooked_slSetTag(const sl::ViewportHandle& viewport, const sl::
903999
}
9041000
#endif
9051001

906-
sl::ResourceTag* new_tags = nullptr;
907-
std::vector<sl::Resource> rewritten_resources = {};
1002+
static thread_local std::vector<sl::ResourceTag> rewritten_tags;
1003+
static thread_local std::vector<sl::Resource> rewritten_resources;
1004+
uint32_t rewritten_resource_count = 0u;
1005+
uint32_t last_written_tag_index = 0u;
1006+
auto copy_tags_until = [&](uint32_t end_index) {
1007+
if (rewritten_tags.size() < numTags) rewritten_tags.resize(numTags);
1008+
if (last_written_tag_index < end_index) {
1009+
memcpy(rewritten_tags.data() + last_written_tag_index, tags + last_written_tag_index, sizeof(sl::ResourceTag) * (end_index - last_written_tag_index));
1010+
last_written_tag_index = end_index;
1011+
}
1012+
};
9081013
for (auto i = 0u; i < numTags; ++i) {
9091014
const auto& tag = tags[i];
9101015
// if (tag.type == sl::kBufferTypeBackbuffer) continue;
@@ -937,31 +1042,28 @@ static sl::Result Hooked_slSetTag(const sl::ViewportHandle& viewport, const sl::
9371042
}
9381043

9391044
if (redirected_native != tag.resource->native) {
940-
if (new_tags == nullptr) {
941-
auto size = sizeof(sl::ResourceTag) * numTags;
942-
new_tags = reinterpret_cast<sl::ResourceTag*>(malloc(sizeof(sl::ResourceTag) * numTags));
943-
memcpy(new_tags, tags, sizeof(sl::ResourceTag) * numTags);
944-
rewritten_resources.reserve(numTags);
1045+
if (rewritten_resource_count == 0u) {
1046+
if (rewritten_resources.size() < numTags) rewritten_resources.resize(numTags);
9451047
}
1048+
copy_tags_until(i);
9461049

947-
rewritten_resources.emplace_back(tag.resource->type, redirected_native, tag.resource->state);
948-
auto new_sl_resource_tag = sl::ResourceTag(&rewritten_resources.back(), tag.type, tag.lifecycle, &tag.extent);
949-
new_tags[i] = new_sl_resource_tag;
1050+
rewritten_resources[rewritten_resource_count] = sl::Resource(tag.resource->type, redirected_native, tag.resource->state);
1051+
auto new_sl_resource_tag = sl::ResourceTag(&rewritten_resources[rewritten_resource_count++], tag.type, tag.lifecycle, &tag.extent);
1052+
rewritten_tags[i] = new_sl_resource_tag;
1053+
last_written_tag_index = i + 1u;
9501054
}
951-
// }
9521055
}
9531056

9541057
const bool unwrapped = utils::directx::NativeFromReShadeProxy(&cmdBuffer);
9551058
assert((unwrapped || cmdBuffer == nullptr) && "slSetTag expected a ReShade proxy command buffer.");
9561059

9571060
// return sl::Result::eOk;
958-
if (new_tags == nullptr) {
1061+
if (rewritten_resource_count == 0u) {
9591062
return Real_slSetTag(viewport, tags, numTags, cmdBuffer);
9601063
}
1064+
copy_tags_until(numTags);
9611065

962-
sl::Result result = Real_slSetTag(viewport, new_tags, numTags, cmdBuffer);
963-
free(new_tags);
964-
new_tags = nullptr;
1066+
sl::Result result = Real_slSetTag(viewport, rewritten_tags.data(), numTags, cmdBuffer);
9651067
return result;
9661068
}
9671069

@@ -1102,8 +1204,17 @@ static sl::Result Hooked_slSetTagForFrame(const sl::FrameToken& frame, const sl:
11021204
}
11031205
#endif
11041206

1105-
sl::ResourceTag* new_tags = nullptr;
1106-
std::vector<sl::Resource> rewritten_resources = {};
1207+
static thread_local std::vector<sl::ResourceTag> rewritten_tags;
1208+
static thread_local std::vector<sl::Resource> rewritten_resources;
1209+
uint32_t rewritten_resource_count = 0u;
1210+
uint32_t last_written_tag_index = 0u;
1211+
auto copy_tags_until = [&](uint32_t end_index) {
1212+
if (rewritten_tags.size() < numTags) rewritten_tags.resize(numTags);
1213+
if (last_written_tag_index < end_index) {
1214+
memcpy(rewritten_tags.data() + last_written_tag_index, tags + last_written_tag_index, sizeof(sl::ResourceTag) * (end_index - last_written_tag_index));
1215+
last_written_tag_index = end_index;
1216+
}
1217+
};
11071218
for (auto i = 0u; i < numTags; ++i) {
11081219
const auto& tag = tags[i];
11091220
if (tag.type == sl::kBufferTypeBackbuffer) continue;
@@ -1123,29 +1234,27 @@ static sl::Result Hooked_slSetTagForFrame(const sl::FrameToken& frame, const sl:
11231234
}
11241235

11251236
if (redirected_native != tag.resource->native) {
1126-
if (new_tags == nullptr) {
1127-
auto size = sizeof(sl::ResourceTag) * numTags;
1128-
new_tags = reinterpret_cast<sl::ResourceTag*>(malloc(sizeof(sl::ResourceTag) * numTags));
1129-
memcpy(new_tags, tags, sizeof(sl::ResourceTag) * numTags);
1130-
rewritten_resources.reserve(numTags);
1237+
if (rewritten_resource_count == 0u) {
1238+
if (rewritten_resources.size() < numTags) rewritten_resources.resize(numTags);
11311239
}
1240+
copy_tags_until(i);
11321241

1133-
rewritten_resources.emplace_back(tag.resource->type, redirected_native, tag.resource->state);
1134-
auto new_sl_resource_tag = sl::ResourceTag(&rewritten_resources.back(), tag.type, tag.lifecycle, &tag.extent);
1135-
new_tags[i] = new_sl_resource_tag;
1242+
rewritten_resources[rewritten_resource_count] = sl::Resource(tag.resource->type, redirected_native, tag.resource->state);
1243+
auto new_sl_resource_tag = sl::ResourceTag(&rewritten_resources[rewritten_resource_count++], tag.type, tag.lifecycle, &tag.extent);
1244+
rewritten_tags[i] = new_sl_resource_tag;
1245+
last_written_tag_index = i + 1u;
11361246
}
11371247
}
11381248

11391249
const bool unwrapped = utils::directx::NativeFromReShadeProxy(&cmdBuffer);
11401250
assert((unwrapped || cmdBuffer == nullptr) && "slSetTagForFrame expected a ReShade proxy command buffer.");
11411251

1142-
if (new_tags == nullptr) {
1252+
if (rewritten_resource_count == 0u) {
11431253
return Real_slSetTagForFrame(frame, viewport, tags, numTags, cmdBuffer);
11441254
}
1255+
copy_tags_until(numTags);
11451256

1146-
sl::Result result = Real_slSetTagForFrame(frame, viewport, new_tags, numTags, cmdBuffer);
1147-
free(new_tags);
1148-
new_tags = nullptr;
1257+
sl::Result result = Real_slSetTagForFrame(frame, viewport, rewritten_tags.data(), numTags, cmdBuffer);
11491258
return result;
11501259
}
11511260

@@ -1162,6 +1271,7 @@ static const std::vector<std::tuple<const char*, void**, void*>> INTERPOSER_HOOK
11621271
{"CreateDXGIFactory1", (void**)&Real_CreateDXGIFactory1, &Hooked_CreateDXGIFactory1},
11631272
{"CreateDXGIFactory2", (void**)&Real_CreateDXGIFactory2, &Hooked_CreateDXGIFactory2},
11641273
{"D3D12CreateDevice", (void**)&Real_D3D12CreateDevice, &Hooked_D3D12CreateDevice},
1274+
{"D3D12GetInterface", (void**)&Real_D3D12GetInterface, &Hooked_D3D12GetInterface},
11651275
};
11661276

11671277
} // namespace renodx::utils::streamline::v2

0 commit comments

Comments
 (0)