shim: adaptive marker polling, opt-in GPU-side input wait/completion and RGBA8 output
- [Interop] MarkerPollUs = auto is the new default: the input-marker wait learns when each feature's inputs become ready, sleeps in <=200 us chunks, yields near the prediction and backs off when late (d4r_input_wait.h); a number keeps fixed pacing (0 yields). d4r_config.py no longer exports 200 when the key is unset - D4R_SHIM_GPU_INPUT_WAIT=1 (experimental, split VRAM, age 0): NGX's null stream waits on a coherent Vulkan word imported into HIP (d4rStreamWaitValue32Eq) instead of CPU polling. The original readback marker stays the authority; a CPU watchdog releases discarded lists and timeouts. Denoiser, verify, capture and dilation frames keep the CPU wait - D4R_SHIM_GPU_COMPLETION=1 (needs GPU_INPUT_WAIT): the bridge writes a completion word right after the native output kernel (d4rNgxWriteValue32), and the game's queue polls it with a bounded compute wait (kernels/support/vulkan_wait.comp), replacing the split list's CPU timeline signal. frame_retired writes the same word on every failure path - D4R_SHIM_NATIVE_COMPLETION=1: a null-stream callback in the bridge signals the split timeline (d4rNgxTimeline*); D4rFrameCompletion::can_signal only releases the oldest outstanding frame - RGBA8 output: tex_common.h adds an 'R4' redirect tag, so K's native output kernel stores packed RGBA8 directly (D4R_SHIM_OUTPUT_RGBA8=1, checked against the kernel manifest by d4rOutputKernelRgba8). Host packing handles RGBA8 too. patches/vkd3d-proton/0004 (VKD3D_D4R_LINEAR_RGBA8=WxH) makes such outputs linear and exportable so the result can be written in place - D4R_SHIM_FUSE_RGBA8_INPUT=1: one Vulkan pass converts and copies RGBA8 color input (vulkan_read.comp mode 5 matches the blit's toward-zero halves, plus a row stride) - profiling: thread CPU time from the Unix bridge (Wine's GetThreadTimes ticks at 10 ms); game-queue D3D12 timestamps (vk_input/vk_dlss_wait/vk_output/vk_total); gpu_eval split into input_gpu_wait and dlss_gpu; D4R_PROFILE_GPU_EVENTS, _TIMESTAMPS, _LOG and _CPU_TIME=0 switch off individual parts for bisection - bridge: D4R_NGX_STREAM_PRIORITY=high|normal runs NGX on a priority stream (off by default; no gain measured) - release_feature: a feature already marked retiring by a failed drain can still be released normally - harness: RGBA8 with motion and jitter scenes (re-quantized each frame), D4R_HARNESS_RGBA8_RAMP, D4R_HARNESS_THRASH_MB to evict L2/Infinity Cache before each evaluation - kernels/native: in_hoist.py and split_output_paths.py (opt-in scheduling experiments); scripts/build_k_ldr_output.sh builds K's LDR output with an optional D4R_LDR_OUTPUT_MAX_VGPR cap - tests: test_input_wait.py and test_latency_optimizations.py; MarkerPollUs and frame-completion tests updated
This commit is contained in:
1 parent
f0b55a850a
commit
162bbd77c8
22 files changed
+1989
-109
No files matched your search
@@ -1125,9 +1125,9 @@ int main(int argc, char** argv)
|
||||
std::fprintf(stderr, "RGB10A2 output cannot be combined with RGBA8 or the quality scene\n");
|
||||
return 2;
|
||||
}
|
||||
if (rgba8 && (qualityScene || motionScene || jitterScene || replayDir != nullptr))
|
||||
if (rgba8 && (qualityScene || replayDir != nullptr))
|
||||
{
|
||||
std::fprintf(stderr, "RGBA8 format probe requires the static synthetic scene\n");
|
||||
std::fprintf(stderr, "RGBA8 format probe supports static, motion and jitter scenes\n");
|
||||
return 2;
|
||||
}
|
||||
const bool temporal = std::getenv("D4R_HARNESS_TEMPORAL") != nullptr || motionScene || jitterScene || qualityScene ||
|
||||
@@ -1226,6 +1226,8 @@ int main(int argc, char** argv)
|
||||
for (size_t index = 0; index < color.size(); ++index)
|
||||
color8[index] = static_cast<uint8_t>(std::lround(
|
||||
std::clamp(static_cast<float>(std::bit_cast<_Float16>(color[index])), 0.0f, 1.0f) * 255.0f));
|
||||
if (std::getenv("D4R_HARNESS_RGBA8_RAMP") != nullptr)
|
||||
for (size_t i = 0; i < color8.size(); ++i) color8[i] = static_cast<uint8_t>(i);
|
||||
outputInit8.resize(static_cast<size_t>(outWidth) * outHeight * 4);
|
||||
}
|
||||
|
||||
@@ -1421,6 +1423,17 @@ int main(int argc, char** argv)
|
||||
: rgb10 ? DXGI_FORMAT_R10G10B10A2_UNORM
|
||||
: DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
|
||||
// Moving/jittered RGBA8 fixtures quantize the same canonical half input as the initial upload.
|
||||
// Never upload the half byte layout into an RGBA8 resource: that would make a format test silently
|
||||
// exercise different content instead of checking the conversion/packing route used by the game.
|
||||
const auto update_color = [&] {
|
||||
if (rgba8)
|
||||
for (size_t i = 0; i < color.size(); ++i)
|
||||
color8[i] = static_cast<uint8_t>(std::lround(std::clamp(
|
||||
static_cast<float>(std::bit_cast<_Float16>(color[i])), 0.0f, 1.0f) * 255.0f));
|
||||
update_texture(colorTexture, rgba8 ? static_cast<const void*>(color8.data())
|
||||
: static_cast<const void*>(color.data()), resourceWidth * (rgba8 ? 4 : 8), srv);
|
||||
};
|
||||
upload(colorTexture, rgba8 ? static_cast<const void*>(color8.data()) : static_cast<const void*>(color.data()),
|
||||
resourceWidth * (rgba8 ? 4 : 8), srv);
|
||||
upload(depthTexture, depth.data(), resourceWidth * 4, srv);
|
||||
@@ -1757,7 +1770,7 @@ int main(int argc, char** argv)
|
||||
color[pixel * 4 + 0] = color[pixel * 4 + 1] = color[pixel * 4 + 2] = half;
|
||||
color[pixel * 4 + 3] = 0x3c00u;
|
||||
}
|
||||
update_texture(colorTexture, color.data(), resourceWidth * 8, srv);
|
||||
update_color();
|
||||
if (frame == 1 && (panX != 0 || panY != 0))
|
||||
{
|
||||
// Current position -> previous position. Without MVLowRes DLSS
|
||||
@@ -1800,7 +1813,7 @@ int main(int argc, char** argv)
|
||||
{0.0f, 0.25f, -0.25f, -0.125f, 0.375f, 0.125f, -0.375f, 0.0f};
|
||||
const size_t phase = static_cast<size_t>(frame - 1) % jitterX.size();
|
||||
render_jittered_background(color, inWidth, inHeight, resourceWidth, jitterX[phase], jitterY[phase]);
|
||||
update_texture(colorTexture, color.data(), resourceWidth * 8, srv);
|
||||
update_color();
|
||||
d4r_ngx_set_float(parameters, "Jitter.Offset.X", jitterX[phase]);
|
||||
d4r_ngx_set_float(parameters, "Jitter.Offset.Y", jitterY[phase]);
|
||||
}
|
||||
@@ -1823,7 +1836,7 @@ int main(int argc, char** argv)
|
||||
motion[motionPixel * 2 + 0] = 0xc400u; // -4 render pixels: current position -> previous
|
||||
motion[motionPixel * 2 + 1] = 0;
|
||||
}
|
||||
update_texture(colorTexture, color.data(), resourceWidth * 8, srv);
|
||||
update_color();
|
||||
update_texture(depthTexture, depth.data(), resourceWidth * 4, srv);
|
||||
update_texture(motionTexture, motion_rows(motion.data()), motionRowBytes, srv);
|
||||
}
|
||||
@@ -2054,6 +2067,20 @@ int main(int argc, char** argv)
|
||||
LARGE_INTEGER counterStart, counterRecorded, counterEnd, counterFrequency;
|
||||
QueryPerformanceFrequency(&counterFrequency);
|
||||
QueryPerformanceCounter(&counterStart);
|
||||
// D4R_HARNESS_THRASH_MB=N: copy N MB between two private buffers ahead of the evaluation, as a game's
|
||||
// own rendering does, so DLSS starts with its weights and history evicted from L2 and Infinity Cache
|
||||
// instead of finding them warm from the previous back-to-back frame.
|
||||
static const UINT64 thrashBytes = std::getenv("D4R_HARNESS_THRASH_MB") != nullptr
|
||||
? std::clamp<UINT64>(std::strtoull(std::getenv("D4R_HARNESS_THRASH_MB"), nullptr, 10), 0, 1024) << 20 : 0;
|
||||
static ID3D12Resource* thrashSource = nullptr;
|
||||
static ID3D12Resource* thrashTarget = nullptr;
|
||||
if (thrashBytes != 0 && thrashSource == nullptr)
|
||||
{
|
||||
thrashSource = create_buffer(D3D12_HEAP_TYPE_DEFAULT, thrashBytes, D3D12_RESOURCE_STATE_COMMON);
|
||||
thrashTarget = create_buffer(D3D12_HEAP_TYPE_DEFAULT, thrashBytes, D3D12_RESOURCE_STATE_COMMON);
|
||||
}
|
||||
if (thrashSource != nullptr && thrashTarget != nullptr)
|
||||
g_list->CopyBufferRegion(thrashTarget, 0, thrashSource, 0, thrashBytes);
|
||||
result = evaluate(g_list, feature, parameters, nullptr);
|
||||
QueryPerformanceCounter(&counterRecorded);
|
||||
if (const char* delay = std::getenv("D4R_HARNESS_DELAY_SUBMIT_MS"))
|
||||
|
||||
Reference in new issue
Block a user