rr: Cyberpunk's extra inputs (SSS guide, colour before particles) and hardware depth

- GameFrameR/RFrameImages: DLSSD.ScreenSpaceSubsurfaceScatteringGuide (arg 264)
  and DLSSD.ColorBeforeParticles (output stage, texture 416 with its own history
  pair 384/392, zero-initialised on first use); guides array 6 -> 8
- DLSS.Use.HW.Depth: byte 980 and output byte 443 bit 24 (Cyberpunk passes the
  nonlinear depth buffer); replay's 'inverted' field becomes a bitmask
- shim: bind the two new resources, read the HW-depth flag, and accept every
  preset hint except E's 5 by mapping it to D's diamond_wallaby kernels
  (harness captures show 0x80000002/0x80000005 run preset D)
- harness: D4R_HARNESS_RR_EXTRA=particles,sss and D4R_HARNESS_RR_HW_DEPTH=1
- ptx2rr: out-of-range integer fetches return zero, matching ZLUDA's behaviour
  (the reference the stages are checked against)
- engine/rr/README: the capture findings behind the offsets
This commit is contained in:
woutermans committed 2026-10-12 13:06:59 +02:00
1 parent 50fa65d87b
commit db24805160
10 files changed
+133 -28

No files matched your search

+34 -1
View File
@@ -1336,6 +1336,8 @@ int main(int argc, char** argv)
// capture shows where the denoiser reads them.
ID3D12Resource* hitDistance = nullptr;
ID3D12Resource* disocclusionMask = nullptr;
ID3D12Resource* colorBeforeParticles = nullptr;
ID3D12Resource* subsurfaceGuide = nullptr;
if (const char* extra = reconstruction ? std::getenv("D4R_HARNESS_RR_EXTRA") : nullptr)
{
if (std::strstr(extra, "hit") != nullptr)
@@ -1360,6 +1362,31 @@ int main(int argc, char** argv)
if (!disocclusionMask) return 1;
upload(disocclusionMask, mask.data(), resourceWidth * sizeof(uint16_t), srv);
}
// "particles" / "sss": Cyberpunk 2077's DLSSD.ColorBeforeParticles (RGBA16F) and
// DLSSD.ScreenSpaceSubsurfaceScatteringGuide (R16F)
if (std::strstr(extra, "particles") != nullptr)
{
std::vector<uint16_t> before(static_cast<size_t>(resourceWidth) * inHeight * 4);
for (UINT y = 0; y < inHeight; ++y)
for (UINT x = 0; x < resourceWidth; ++x)
for (UINT c = 0; c < 4; ++c)
before[(static_cast<size_t>(y) * resourceWidth + x) * 4 + c] = std::bit_cast<uint16_t>(static_cast<_Float16>(
c == 3 ? 1.0f : 0.05f + 0.6f * static_cast<float>((x / 20 + 2 * (y / 20) + c) % 5) / 4.0f));
colorBeforeParticles = create_texture(resourceWidth, inHeight, DXGI_FORMAT_R16G16B16A16_FLOAT, D3D12_RESOURCE_FLAG_NONE);
if (!colorBeforeParticles) return 1;
upload(colorBeforeParticles, before.data(), resourceWidth * 4 * sizeof(uint16_t), srv);
}
if (std::strstr(extra, "sss") != nullptr)
{
std::vector<uint16_t> guide(static_cast<size_t>(resourceWidth) * inHeight);
for (UINT y = 0; y < inHeight; ++y)
for (UINT x = 0; x < resourceWidth; ++x)
guide[static_cast<size_t>(y) * resourceWidth + x] = std::bit_cast<uint16_t>(static_cast<_Float16>(
((x / 28 + y / 28) % 3 == 0) ? 0.75f : 0.0f));
subsurfaceGuide = create_texture(resourceWidth, inHeight, DXGI_FORMAT_R16_FLOAT, D3D12_RESOURCE_FLAG_NONE);
if (!subsurfaceGuide) return 1;
upload(subsurfaceGuide, guide.data(), resourceWidth * sizeof(uint16_t), srv);
}
std::printf("Ray Reconstruction extra inputs:%s%s\n", hitDistance ? " DLSSD.SpecularHitDistance" : "",
disocclusionMask ? " DLSS.DisocclusionMask" : "");
}
@@ -1520,7 +1547,9 @@ int main(int argc, char** argv)
{
d4r_ngx_set_int(parameters, "DLSS.Denoise.Mode", 1);
d4r_ngx_set_int(parameters, "DLSS.Roughness.Mode", 0);
d4r_ngx_set_int(parameters, "DLSS.Use.HW.Depth", 0);
// D4R_HARNESS_RR_HW_DEPTH=1: the depth is the hardware (nonlinear) depth buffer, as Cyberpunk 2077 declares it
d4r_ngx_set_int(parameters, "DLSS.Use.HW.Depth",
std::getenv("D4R_HARNESS_RR_HW_DEPTH") != nullptr ? std::atoi(std::getenv("D4R_HARNESS_RR_HW_DEPTH")) : 0);
d4r_ngx_set_void(parameters, "WorldToViewMatrix", worldToView.data());
d4r_ngx_set_void(parameters, "ViewToClipMatrix", viewToClip.data());
const char* preset = std::getenv("D4R_HARNESS_RR_PRESET");
@@ -1580,6 +1609,10 @@ int main(int argc, char** argv)
d4r_ngx_set_d3d12_resource(parameters, "DLSSD.SpecularHitDistance", hitDistance);
if (disocclusionMask != nullptr && replayDir == nullptr)
d4r_ngx_set_d3d12_resource(parameters, "DLSS.DisocclusionMask", disocclusionMask);
if (colorBeforeParticles != nullptr && replayDir == nullptr)
d4r_ngx_set_d3d12_resource(parameters, "DLSSD.ColorBeforeParticles", colorBeforeParticles);
if (subsurfaceGuide != nullptr && replayDir == nullptr)
d4r_ngx_set_d3d12_resource(parameters, "DLSSD.ScreenSpaceSubsurfaceScatteringGuide", subsurfaceGuide);
// DLSSD.Alpha is a guide the capture records in its own right, so the synthetic alpha
// scenario would double-bind that name; it belongs to the static probe only.
if (alphaScenario && replayDir == nullptr)
+16 -6
View File
@@ -8300,10 +8300,10 @@ static bool engine_evaluate_rr(Feature& feature, ID3D12GraphicsCommandList* list
feature.handle.Id, frame);
return false;
};
// NGX 310.7 runs preset D's kernels when the game names no preset (harness, 2026-10-11).
// NGX 310.7 runs preset E's kernels for the hint 5 only and preset D's (diamond_wallaby) for every other value:
// none, the retired A / B / C (1-3), 6, and values with the top bit set such as Cyberpunk 2077's 0x80000002 or
// 0x80000005 (harness captures with D4R_RR_PRESET, 2026-10-12).
const bool presetE = feature.preset == 5;
if (feature.preset != 0 && feature.preset != 4 && feature.preset != 5)
return refuse("only presets D and E are implemented");
std::call_once(g_engineR.once[presetE], [presetE] {
g_engineR.state[presetE] = 1;
// D4R_ENGINE_RR_SYNC=1 (harness comparisons): load in place so the engine serves the first frame
@@ -8348,7 +8348,10 @@ static bool engine_evaluate_rr(Feature& feature, ID3D12GraphicsCommandList* list
// the optional inputs a game may add (RE Requiem passes both): bound when present, like NGX
ID3D12Resource* const hitDistance = get_resource(parameters, "DLSSD.SpecularHitDistance");
ID3D12Resource* const disocclusion = get_resource(parameters, "DLSS.DisocclusionMask");
for (ID3D12Resource* input : {color, depth, motion, guides[0], guides[1], guides[2], guides[3], hitDistance, disocclusion})
// and Cyberpunk 2077's: the subsurface scattering guide and the colour before particles
ID3D12Resource* const subsurface = get_resource(parameters, "DLSSD.ScreenSpaceSubsurfaceScatteringGuide");
ID3D12Resource* const beforeParticles = get_resource(parameters, "DLSSD.ColorBeforeParticles");
for (ID3D12Resource* input : {color, depth, motion, guides[0], guides[1], guides[2], guides[3], hitDistance, disocclusion, subsurface, beforeParticles})
if (input == output)
return refuse("input/output texture aliasing is not supported");
d4r::GameFrameR game;
@@ -8372,6 +8375,10 @@ static bool engine_evaluate_rr(Feature& feature, ID3D12GraphicsCommandList* list
sources.push_back({hitDistance, &game.specularHitDistance, 0, 0, rw, rh, inputState, D3D12_RESOURCE_STATE_COPY_SOURCE});
if (disocclusion != nullptr)
sources.push_back({disocclusion, &game.disocclusionMask, 0, 0, rw, rh, inputState, D3D12_RESOURCE_STATE_COPY_SOURCE});
if (subsurface != nullptr)
sources.push_back({subsurface, &game.subsurfaceGuide, 0, 0, rw, rh, inputState, D3D12_RESOURCE_STATE_COPY_SOURCE});
if (beforeParticles != nullptr)
sources.push_back({beforeParticles, &game.colorBeforeParticles, 0, 0, rw, rh, inputState, D3D12_RESOURCE_STATE_COPY_SOURCE});
// a guide with its own subrect origin (DLSS.Input.Normals.Subrect.Base etc.) is not implemented
for (size_t i = 0; i < sizeof(kAuxSubrectNames) / sizeof(kAuxSubrectNames[0]); ++i)
if (p.auxSubrect[i][0] != 0 || p.auxSubrect[i][1] != 0)
@@ -8437,11 +8444,14 @@ static bool engine_evaluate_rr(Feature& feature, ID3D12GraphicsCommandList* list
s.frameTimeMs = p.frameTime;
s.reset = p.reset != 0 || feature.engineR == nullptr;
s.depthInverted = (feature.flags & 0x8) != 0;
s.hardwareDepth = get_uint_or(parameters, "DLSS.Use.HW.Depth", 0) != 0;
s.roughnessPacked = roughnessPacked;
if (frame <= 2)
logf("engine backend (Ray Reconstruction): roughness %s, specular hit distance %s, disocclusion mask %s",
logf("engine backend (Ray Reconstruction): roughness %s, specular hit distance %s, disocclusion mask %s, "
"subsurface guide %s, colour before particles %s, hardware depth %d",
roughnessPacked ? "packed in the normals' w" : "texture", hitDistance != nullptr ? "bound" : "none",
disocclusion != nullptr ? "bound" : "none");
disocclusion != nullptr ? "bound" : "none", subsurface != nullptr ? "bound" : "none",
beforeParticles != nullptr ? "bound" : "none", s.hardwareDepth ? 1 : 0);
std::copy(std::begin(p.auxMatrix[0]), std::end(p.auxMatrix[0]), s.worldToView);
std::copy(std::begin(p.auxMatrix[1]), std::end(p.auxMatrix[1]), s.viewToClip);
try