feat: add d4r inference engines and Windows parity tooling
Add native K/M/RR inference engines, HIP kernels, replay and validation harnesses, and Windows DLSS setup and runtime support. Include GPU profiling tools, build and packaging scripts, platform integration patches, and implementation documentation.
This commit is contained in:
1 parent
25493b3198
commit
7c5d3c9157
430 files changed
+76191
No files matched your search
@@ -0,0 +1,82 @@
|
||||
#version 460
|
||||
// d4r engine, preset M: the last stage. The reconstruction works at three times the render resolution; this
|
||||
// resamples its packed result (11-11-10 bits, range-compressed) to the output resolution, 3 -> 2, with a separable
|
||||
// five-tap filter whose weights depend on the output pixel's parity, limits each pass to the range of its taps
|
||||
// (no ringing), and undoes the range compression and the exposure.
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types : require
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#include "output_store.glsl"
|
||||
// LDR (NGX's *_ldr_* kernel): the packed image is the display-referred colour itself.
|
||||
#ifndef LDR
|
||||
#define LDR 0
|
||||
#endif
|
||||
// D4RM0003: the runtime dispatches 8x64 output pixels per workgroup.
|
||||
#define BLOCK_X 8
|
||||
#define BLOCK_Y 64
|
||||
#define TILE_W (3 * BLOCK_X / 2 + 4)
|
||||
#define TILE_H (3 * BLOCK_Y / 2 + 4)
|
||||
layout(local_size_x = BLOCK_X, local_size_y = BLOCK_Y) in;
|
||||
layout(set = 0, binding = 0, std430) readonly buffer Params
|
||||
{
|
||||
ivec2 srcSize; // of the packed image
|
||||
ivec2 outOrigin;
|
||||
ivec2 colOrigin, colSize;
|
||||
vec2 out2rnd, rndOffs; // render texel of an output pixel centre: floor(centre * out2rnd + rndOffs)
|
||||
float expo;
|
||||
} p;
|
||||
layout(set = 0, binding = 1) uniform sampler2D colorTex; // render resolution; its alpha is passed through
|
||||
layout(set = 0, binding = 2, FINAL_OUTPUT_FORMAT) uniform writeonly image2D outImg;
|
||||
layout(set = 0, binding = 3, std430) readonly buffer Src { uint w[]; } src;
|
||||
shared f16vec4 tile[TILE_W * TILE_H]; // source texels around the block
|
||||
shared f16vec4 rows[TILE_H * BLOCK_X]; // after the horizontal pass
|
||||
// weights of taps -2 .. +2 for an even output coordinate; an odd one uses them mirrored
|
||||
// as binary16 bit patterns: NGX rounds its f32 constants to the nearest binary16 (cvt.rn), while glslang folds
|
||||
// float16_t(<literal>) toward zero (W0 became -0.041321 instead of -0.041351: 6% of the captured frame's outputs
|
||||
// one code or more off). The values are -0.041347627, 0.087289415, 0.6202144, 0.37212864, -0.038284853.
|
||||
#define W0 uint16BitsToFloat16(uint16_t(0xA94Bu))
|
||||
#define W1 uint16BitsToFloat16(uint16_t(0x2D96u))
|
||||
#define W2 uint16BitsToFloat16(uint16_t(0x38F6u))
|
||||
#define W3 uint16BitsToFloat16(uint16_t(0x35F4u))
|
||||
#define W4 uint16BitsToFloat16(uint16_t(0xA8E7u))
|
||||
f16vec3 filter5(f16vec3 a, f16vec3 b, f16vec3 c, f16vec3 d, f16vec3 e, bool odd)
|
||||
{
|
||||
const f16vec3 w0 = f16vec3(odd ? W4 : W0), w1 = f16vec3(odd ? W3 : W1), w3 = f16vec3(odd ? W1 : W3), w4 = f16vec3(odd ? W0 : W4);
|
||||
f16vec3 s = w0 * a;
|
||||
s = fma(w1, b, s); s = fma(f16vec3(W2), c, s); s = fma(w3, d, s); s = fma(w4, e, s);
|
||||
return min(max(s, min(min(min(a, b), min(c, d)), e)), max(max(max(a, b), max(c, d)), e));
|
||||
}
|
||||
void main()
|
||||
{
|
||||
const ivec2 lid = ivec2(gl_LocalInvocationID.xy), pix = ivec2(gl_GlobalInvocationID.xy);
|
||||
const ivec2 base = ivec2(3 * BLOCK_X / 2, 3 * BLOCK_Y / 2) * ivec2(gl_WorkGroupID.xy) - 2;
|
||||
for (int i = lid.y * BLOCK_X + lid.x; i < TILE_W * TILE_H; i += BLOCK_X * BLOCK_Y)
|
||||
{
|
||||
const ivec2 at = clamp(base + ivec2(i % TILE_W, i / TILE_W), ivec2(0), p.srcSize - 1);
|
||||
const uint w = src.w[at.y * p.srcSize.x + at.x];
|
||||
#if LDR
|
||||
tile[i] = f16vec4(vec4(float(w & 2047u) * (1.0 / 2047.0), float((w >> 11) & 2047u) * (1.0 / 2047.0), float(w >> 22) * (1.0 / 1023.0), 0.0));
|
||||
#else
|
||||
tile[i] = f16vec4(vec4(float(w & 2047u) * 0.0011968734906986356, float((w >> 11) & 2047u) * 0.0011968734906986356, float(w >> 22) * 0.002394916955381632, 0.0));
|
||||
#endif
|
||||
}
|
||||
memoryBarrierShared(); barrier();
|
||||
const ivec2 c = ivec2(floor((vec2(pix) + 0.5) * 1.5)) - base;
|
||||
for (int y = lid.y; y < TILE_H; y += BLOCK_Y)
|
||||
{
|
||||
const int o = y * TILE_W + c.x;
|
||||
rows[y * BLOCK_X + lid.x].rgb = filter5(tile[o - 2].rgb, tile[o - 1].rgb, tile[o].rgb, tile[o + 1].rgb, tile[o + 2].rgb, (pix.x & 1) != 0);
|
||||
}
|
||||
memoryBarrierShared(); barrier();
|
||||
// After both shared barriers: borrowed images may extend beyond the feature's true output rectangle.
|
||||
// M accepts even output dimensions and srcSize = outputSize/2*3, so this bounds check is exact.
|
||||
if (3 * pix.x >= 2 * p.srcSize.x || 3 * pix.y >= 2 * p.srcSize.y) return;
|
||||
const int o = c.y * BLOCK_X + lid.x;
|
||||
#if LDR
|
||||
const vec3 lin = vec3(filter5(rows[o - 2 * BLOCK_X].rgb, rows[o - BLOCK_X].rgb, rows[o].rgb, rows[o + BLOCK_X].rgb, rows[o + 2 * BLOCK_X].rgb, (pix.y & 1) != 0));
|
||||
#else
|
||||
const vec3 v = clamp(vec3(filter5(rows[o - 2 * BLOCK_X].rgb, rows[o - BLOCK_X].rgb, rows[o].rgb, rows[o + BLOCK_X].rgb, rows[o + 2 * BLOCK_X].rgb, (pix.y & 1) != 0)), 1e-4, 3.0);
|
||||
const vec3 lin = (exp2(v * (1.0 / 0.36) * log2(10.0)) - 1.0) * (1.0 / 100.0) * (1.0 / (p.expo == 0.0 ? 1.0 : p.expo));
|
||||
#endif
|
||||
const ivec2 r = clamp(ivec2(floor((vec2(pix) + 0.5) * p.out2rnd + p.rndOffs)), ivec2(0), p.colSize - 1) + p.colOrigin;
|
||||
imageStore(outImg, p.outOrigin + pix, finalOutputValue(vec4(lin, texelFetch(colorTex, r, 0).a)));
|
||||
}
|
||||
Reference in new issue
Block a user