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:
1 parent
50fa65d87b
commit
db24805160
10 files changed
+133
-28
No files matched your search
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user