Add R16_FLOAT depth input support

Alan Wake 2 uses the format for depth when enabling Ray Reconstruction.
The CPU path converts half to float in convert_row_in.
The VRAM interop path blits R16F/R16UNORM depth to an R32F conversion image before copying into the canonical buffer.

Signed-off-by: Tk-Glitch <[email protected]>
This commit is contained in:
Tk-Glitch committed 2026-10-07 13:12:28 +02:00
1 parent 7c60d53cd0
commit 40e0094c19
1 file changed
+36 -2
+36 -2
View File
@@ -857,7 +857,8 @@ static bool supported_input(Plane plane, DXGI_FORMAT format)
format == DXGI_FORMAT_R32G8X24_TYPELESS || format == DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS ||
format == DXGI_FORMAT_D24_UNORM_S8_UINT || format == DXGI_FORMAT_R24G8_TYPELESS ||
format == DXGI_FORMAT_R24_UNORM_X8_TYPELESS || format == DXGI_FORMAT_D16_UNORM ||
format == DXGI_FORMAT_R16_UNORM || format == DXGI_FORMAT_R16_TYPELESS;
format == DXGI_FORMAT_R16_UNORM || format == DXGI_FORMAT_R16_TYPELESS ||
format == DXGI_FORMAT_R16_FLOAT;
case Plane::Motion:
return format == DXGI_FORMAT_R16G16_FLOAT || format == DXGI_FORMAT_R16G16_TYPELESS ||
format == DXGI_FORMAT_R32G32_FLOAT || format == DXGI_FORMAT_R32G32_TYPELESS ||
@@ -986,6 +987,13 @@ static void convert_row_in(Plane plane, DXGI_FORMAT format, const uint8_t* sourc
single[x] = unorm(value, 16);
break;
}
case DXGI_FORMAT_R16_FLOAT:
{
uint16_t value;
std::memcpy(&value, source + x * 2, 2);
single[x] = half_to_float(value);
break;
}
default: // 32-bit float depth (the depth plane of D32S8 copies as 4 bytes)
std::memcpy(single + x, source + x * 4, 4);
break;
@@ -1704,6 +1712,7 @@ struct Feature
// formats later stop qualifying.
bool vram = false, vramDecided = false;
VramImage colorConversion;
VramImage depthConversion;
VramImage motionConversion;
VramImage exposureConversion;
VramImage outputConversion;
@@ -2448,6 +2457,10 @@ static size_t vk_texel_bytes(VkFormat format)
case VK_FORMAT_D32_SFLOAT:
case VK_FORMAT_D32_SFLOAT_S8_UINT: // the depth aspect alone
return 4;
case VK_FORMAT_R16_SFLOAT:
case VK_FORMAT_R16_UNORM:
case VK_FORMAT_R16_UINT:
return 2;
default:
return 0;
}
@@ -2505,6 +2518,19 @@ static bool vram_exposure_blit_supported(VkFormat format)
}
}
// Depth in a 16-bit format is widened to R32F by a blit (UNORM normalizes, SFLOAT converts).
static bool vram_depth_blit_supported(VkFormat format)
{
switch (format)
{
case VK_FORMAT_R16_SFLOAT:
case VK_FORMAT_R16_UNORM:
return vram_blit_supported(format, VK_FORMAT_R32_SFLOAT);
default:
return false;
}
}
// Motion vectors in a wider float format keep their first two components (as the host path does).
static bool vram_motion_blit_supported(VkFormat format)
{
@@ -2547,6 +2573,8 @@ static bool describe_vram_copy(ID3D12Resource* resource, Plane plane, VramCopy&
copy.convert = vram_exposure_blit_supported(format);
else if (plane == Plane::Motion)
copy.convert = vram_motion_blit_supported(format);
else if (plane == Plane::Depth)
copy.convert = vram_depth_blit_supported(format);
return copy.convert || vk_texel_bytes(format) == canonical_texel_bytes(plane);
}
@@ -2592,7 +2620,8 @@ static bool record_vram_inputs(Feature& feature, ID3D12GraphicsCommandList* list
// to R32F, then copy from the canonical image into the shared buffer.
VkImage conversion = kPlanes[index] == Plane::Exposure ? feature.exposureConversion.image
: kPlanes[index] == Plane::Motion ? feature.motionConversion.image
: feature.colorConversion.image;
: kPlanes[index] == Plane::Depth ? feature.depthConversion.image
: feature.colorConversion.image;
VkImageMemoryBarrier toDestination = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
toDestination.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
toDestination.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
@@ -2802,6 +2831,7 @@ static void release_vram(Feature& feature)
recycle_vram_buffer(buffer);
feature.retiredBuffers.clear();
destroy_vram_image(feature.colorConversion);
destroy_vram_image(feature.depthConversion);
destroy_vram_image(feature.motionConversion);
destroy_vram_image(feature.exposureConversion);
destroy_vram_image(feature.outputConversion);
@@ -4868,6 +4898,10 @@ static NgxResult evaluate(ID3D12GraphicsCommandList* list, const NgxHandle* hand
vramInputs[0].width, vramInputs[0].height,
VK_FORMAT_R16G16B16A16_SFLOAT))
return NGX_FAIL_PLATFORM_ERROR;
if (vramInputs[1].convert && !ensure_conversion_image(*feature, feature->depthConversion,
vramInputs[1].width, vramInputs[1].height,
VK_FORMAT_R32_SFLOAT))
return NGX_FAIL_PLATFORM_ERROR;
if (vramInputs[2].convert && !ensure_conversion_image(*feature, feature->motionConversion,
vramInputs[2].width, vramInputs[2].height,
VK_FORMAT_R16G16_SFLOAT))