[GPU] Texture integer scaling fetches; 8_8_8_8_GAMMA resolve

Integer num_format fetches now get their scale CPU-side instead of trying to guess in the shader. This is authoritative; no cvar. Both translators now use texture_integer_scale_bits after signs/gamma and before exponent bias. This alone fixes black screens and a bunch of rendering bugs across at least several dozen titles.

This new information lives in the updated FormatInfo table, including fixed component widths.

Resolve also has two new fixes.

8_8_8_8_GAMMA EDRAM sources can now decode through the PWL curve while still in linear space, before MSAA resolve or format conversion, then re-encoded for gamma destinations. This is also now default enabled via gamma_decode_pwl_resolve and has improved blowout in at least 4 titles, with no obvious regressions thus far.

Full resolve can also now pack fixed destinations according to copy_dest_number.
This commit is contained in:
goldislead
2026-06-30 20:40:19 -07:00
committed by Radosław Gliński
parent 573cce0fe2
commit d119505289
24 changed files with 669 additions and 156 deletions

View File

@@ -93,57 +93,103 @@
#define kXenosDepthRenderTargetFormat_D24S8 0u
#define kXenosDepthRenderTargetFormat_D24FS8 1u
#define kXenosSurfaceNumberFormat_UnsignedRepeatingFraction 0u
#define kXenosSurfaceNumberFormat_SignedRepeatingFraction 1u
#define kXenosSurfaceNumberFormat_UnsignedInteger 2u
#define kXenosSurfaceNumberFormat_SignedInteger 3u
#define kXenosSurfaceNumberFormat_Float 7u
// ColorFormat packing, according to the Direct3D 11.3 functional specification.
uint XePackR5G5B5A1UNorm(float4_xe f) {
uint4_xe n = uint4_xe(saturate_xe(f) * float2_xe(31.0f, 1.0f).xxxy + 0.5f);
uint XePackFixed(float value, uint bits, uint num_format) {
uint unsigned_max = (1u << bits) - 1u;
uint packed = 0u;
if (num_format == kXenosSurfaceNumberFormat_SignedRepeatingFraction) {
// Signed fraction uses the positive endpoint, then keeps the destination
// bit width.
float positive_max = float((1u << (bits - 1u)) - 1u);
packed = uint(int(min(max(value, -1.0f), 1.0f) * positive_max +
(value >= 0.0f ? 0.5f : -0.5f)));
} else if (num_format == kXenosSurfaceNumberFormat_UnsignedInteger) {
packed = uint(min(max(value, 0.0f), float(unsigned_max)) + 0.5f);
} else if (num_format == kXenosSurfaceNumberFormat_SignedInteger) {
int signed_min = -int(1u << (bits - 1u));
int signed_max = int((1u << (bits - 1u)) - 1u);
packed = uint(int(min(max(value, float(signed_min)), float(signed_max)) +
(value >= 0.0f ? 0.5f : -0.5f)));
} else {
// Unsigned fraction, float-on-fixed, or anything unexpected: keep the
// usual unsigned-fraction pack.
packed = uint(saturate_xe(value) * float(unsigned_max) + 0.5f);
}
return packed & unsigned_max;
}
uint4_xe XePackFixed4(float4_xe f, uint4_xe bits, uint num_format) {
return uint4_xe(XePackFixed(f.x, bits.x, num_format),
XePackFixed(f.y, bits.y, num_format),
XePackFixed(f.z, bits.z, num_format),
XePackFixed(f.w, bits.w, num_format));
}
uint3_xe XePackFixed3(float3_xe f, uint3_xe bits, uint num_format) {
return uint3_xe(XePackFixed(f.x, bits.x, num_format),
XePackFixed(f.y, bits.y, num_format),
XePackFixed(f.z, bits.z, num_format));
}
uint2_xe XePackFixed2(float2_xe f, uint2_xe bits, uint num_format) {
return uint2_xe(XePackFixed(f.x, bits.x, num_format),
XePackFixed(f.y, bits.y, num_format));
}
uint XePackR5G5B5A1(float4_xe f, uint num_format) {
uint4_xe n = XePackFixed4(f, uint2_xe(5u, 1u).xxxy, num_format);
return n.r | (n.g << 5) | (n.b << 10) | (n.a << 15);
}
uint XePackR5G6B5UNorm(float3_xe f) {
uint3_xe n = uint3_xe(saturate_xe(f) * float3_xe(31.0f, 63.0f, 31.0f) + 0.5f);
uint XePackR5G6B5(float3_xe f, uint num_format) {
uint3_xe n = XePackFixed3(f, uint3_xe(5u, 6u, 5u), num_format);
return n.r | (n.g << 5) | (n.b << 11);
}
uint XePackR5G5B6UNorm(float3_xe f) {
uint3_xe n = uint3_xe(saturate_xe(f) * float3_xe(31.0f, 31.0f, 63.0f) + 0.5f);
uint XePackR5G5B6(float3_xe f, uint num_format) {
uint3_xe n = XePackFixed3(f, uint3_xe(5u, 5u, 6u), num_format);
return n.r | (n.g << 5) | (n.b << 10);
}
uint XePackR8G8B8A8UNorm(float4_xe f) {
uint4_xe n = uint4_xe(saturate_xe(f) * 255.0f + 0.5f);
uint XePackR8G8B8A8(float4_xe f, uint num_format) {
uint4_xe n = XePackFixed4(f, uint_x4_xe(8u), num_format);
return n.r | (n.g << 8) | (n.b << 16) | (n.a << 24);
}
uint XePackR10G10B10A2UNorm(float4_xe f) {
uint4_xe n = uint4_xe(saturate_xe(f) * float2_xe(1023.0f, 3.0f).xxxy + 0.5f);
uint XePackR10G10B10A2(float4_xe f, uint num_format) {
uint4_xe n = XePackFixed4(f, uint2_xe(10u, 2u).xxxy, num_format);
return n.r | (n.g << 10) | (n.b << 20) | (n.a << 30);
}
uint XePackR4G4B4A4UNorm(float4_xe f) {
uint4_xe n = uint4_xe(saturate_xe(f) * 15.0f + 0.5f);
uint XePackR4G4B4A4(float4_xe f, uint num_format) {
uint4_xe n = XePackFixed4(f, uint_x4_xe(4u), num_format);
return n.r | (n.g << 4) | (n.b << 8) | (n.a << 12);
}
uint XePackR11G11B10UNorm(float3_xe f) {
uint3_xe n =
uint3_xe(saturate_xe(f) * float3_xe(2047.0f, 2047.0f, 1023.0f) + 0.5);
uint XePackR11G11B10(float3_xe f, uint num_format) {
uint3_xe n = XePackFixed3(f, uint3_xe(11u, 11u, 10u), num_format);
return n.r | (n.g << 11) | (n.b << 22);
}
uint XePackR10G11B11UNorm(float3_xe f) {
uint3_xe n =
uint3_xe(saturate_xe(f) * float3_xe(1023.0f, 2047.0f, 2047.0f) + 0.5f);
uint XePackR10G11B11(float3_xe f, uint num_format) {
uint3_xe n = XePackFixed3(f, uint3_xe(10u, 11u, 11u), num_format);
return n.r | (n.g << 10) | (n.b << 21);
}
uint XePackR16G16UNorm(float2_xe f) {
uint2_xe n = uint2_xe(saturate_xe(f) * 65535.0f + 0.5f);
uint XePackR16G16(float2_xe f, uint num_format) {
uint2_xe n = XePackFixed2(f, uint_x2_xe(16u), num_format);
return n.r | (n.g << 16);
}
uint2_xe XePackR16G16B16A16UNorm(float4_xe f) {
uint4_xe n = uint4_xe(saturate_xe(f) * 65535.0f + 0.5f);
uint2_xe XePackR16G16B16A16(float4_xe f, uint num_format) {
uint4_xe n = XePackFixed4(f, uint_x4_xe(16u), num_format);
return n.rb | (n.ga << 16);
}
@@ -162,40 +208,43 @@ uint2_xe XePackR16G16B16A16Edram(float4_xe f) {
uint2_xe XePack16bpp4PixelsInUInt2(float4_xe pixel_0, float4_xe pixel_1,
float4_xe pixel_2, float4_xe pixel_3,
uint format) {
uint format, uint num_format) {
uint2_xe packed;
switch (format) {
case kXenosFormat_1_5_5_5:
packed.x = XePackR5G5B5A1UNorm(pixel_0) |
(XePackR5G5B5A1UNorm(pixel_1) << 16u);
packed.y = XePackR5G5B5A1UNorm(pixel_2) |
(XePackR5G5B5A1UNorm(pixel_3) << 16u);
packed.x = XePackR5G5B5A1(pixel_0, num_format) |
(XePackR5G5B5A1(pixel_1, num_format) << 16u);
packed.y = XePackR5G5B5A1(pixel_2, num_format) |
(XePackR5G5B5A1(pixel_3, num_format) << 16u);
break;
case kXenosFormat_5_6_5:
packed.x = XePackR5G6B5UNorm(pixel_0.rgb) |
(XePackR5G6B5UNorm(pixel_1.rgb) << 16u);
packed.y = XePackR5G6B5UNorm(pixel_2.rgb) |
(XePackR5G6B5UNorm(pixel_3.rgb) << 16u);
packed.x = XePackR5G6B5(pixel_0.rgb, num_format) |
(XePackR5G6B5(pixel_1.rgb, num_format) << 16u);
packed.y = XePackR5G6B5(pixel_2.rgb, num_format) |
(XePackR5G6B5(pixel_3.rgb, num_format) << 16u);
break;
case kXenosFormat_6_5_5:
packed.x = XePackR5G5B6UNorm(pixel_0.rgb) |
(XePackR5G5B6UNorm(pixel_1.rgb) << 16u);
packed.y = XePackR5G5B6UNorm(pixel_2.rgb) |
(XePackR5G5B6UNorm(pixel_3.rgb) << 16u);
packed.x = XePackR5G5B6(pixel_0.rgb, num_format) |
(XePackR5G5B6(pixel_1.rgb, num_format) << 16u);
packed.y = XePackR5G5B6(pixel_2.rgb, num_format) |
(XePackR5G5B6(pixel_3.rgb, num_format) << 16u);
break;
case kXenosFormat_8_8:
packed.x = XePackR8G8B8A8UNorm(float4_xe(pixel_0.rg, pixel_1.rg));
packed.y = XePackR8G8B8A8UNorm(float4_xe(pixel_2.rg, pixel_3.rg));
packed.x =
XePackR8G8B8A8(float4_xe(pixel_0.rg, pixel_1.rg), num_format);
packed.y =
XePackR8G8B8A8(float4_xe(pixel_2.rg, pixel_3.rg), num_format);
break;
case kXenosFormat_4_4_4_4:
packed.x = XePackR4G4B4A4UNorm(pixel_0) |
(XePackR4G4B4A4UNorm(pixel_1) << 16u);
packed.y = XePackR4G4B4A4UNorm(pixel_2) |
(XePackR4G4B4A4UNorm(pixel_3) << 16u);
packed.x = XePackR4G4B4A4(pixel_0, num_format) |
(XePackR4G4B4A4(pixel_1, num_format) << 16u);
packed.y = XePackR4G4B4A4(pixel_2, num_format) |
(XePackR4G4B4A4(pixel_3, num_format) << 16u);
break;
case kXenosFormat_16:
packed = XePackR16G16B16A16UNorm(float4_xe(pixel_0.r, pixel_1.r,
pixel_2.r, pixel_3.r));
packed = XePackR16G16B16A16(float4_xe(pixel_0.r, pixel_1.r, pixel_2.r,
pixel_3.r),
num_format);
break;
default:
// Treat as something (16_FLOAT).
@@ -208,45 +257,45 @@ uint2_xe XePack16bpp4PixelsInUInt2(float4_xe pixel_0, float4_xe pixel_1,
uint4_xe XePack32bpp4Pixels(float4_xe pixel_0, float4_xe pixel_1,
float4_xe pixel_2, float4_xe pixel_3,
uint format) {
uint format, uint num_format) {
uint4_xe packed;
switch (format) {
case kXenosFormat_8_8_8_8:
// TODO(Triang3l): Investigate 8_8_8_8_A.
case kXenosFormat_8_8_8_8_A:
case kXenosFormat_8_8_8_8_AS_16_16_16_16:
packed.x = XePackR8G8B8A8UNorm(pixel_0);
packed.y = XePackR8G8B8A8UNorm(pixel_1);
packed.z = XePackR8G8B8A8UNorm(pixel_2);
packed.w = XePackR8G8B8A8UNorm(pixel_3);
packed.x = XePackR8G8B8A8(pixel_0, num_format);
packed.y = XePackR8G8B8A8(pixel_1, num_format);
packed.z = XePackR8G8B8A8(pixel_2, num_format);
packed.w = XePackR8G8B8A8(pixel_3, num_format);
break;
case kXenosFormat_2_10_10_10:
case kXenosFormat_2_10_10_10_AS_16_16_16_16:
packed.x = XePackR10G10B10A2UNorm(pixel_0);
packed.y = XePackR10G10B10A2UNorm(pixel_1);
packed.z = XePackR10G10B10A2UNorm(pixel_2);
packed.w = XePackR10G10B10A2UNorm(pixel_3);
packed.x = XePackR10G10B10A2(pixel_0, num_format);
packed.y = XePackR10G10B10A2(pixel_1, num_format);
packed.z = XePackR10G10B10A2(pixel_2, num_format);
packed.w = XePackR10G10B10A2(pixel_3, num_format);
break;
case kXenosFormat_10_11_11:
case kXenosFormat_10_11_11_AS_16_16_16_16:
packed.x = XePackR11G11B10UNorm(pixel_0.rgb);
packed.y = XePackR11G11B10UNorm(pixel_1.rgb);
packed.z = XePackR11G11B10UNorm(pixel_2.rgb);
packed.w = XePackR11G11B10UNorm(pixel_3.rgb);
packed.x = XePackR11G11B10(pixel_0.rgb, num_format);
packed.y = XePackR11G11B10(pixel_1.rgb, num_format);
packed.z = XePackR11G11B10(pixel_2.rgb, num_format);
packed.w = XePackR11G11B10(pixel_3.rgb, num_format);
break;
case kXenosFormat_11_11_10:
case kXenosFormat_11_11_10_AS_16_16_16_16:
packed.x = XePackR10G11B11UNorm(pixel_0.rgb);
packed.y = XePackR10G11B11UNorm(pixel_1.rgb);
packed.z = XePackR10G11B11UNorm(pixel_2.rgb);
packed.w = XePackR10G11B11UNorm(pixel_3.rgb);
packed.x = XePackR10G11B11(pixel_0.rgb, num_format);
packed.y = XePackR10G11B11(pixel_1.rgb, num_format);
packed.z = XePackR10G11B11(pixel_2.rgb, num_format);
packed.w = XePackR10G11B11(pixel_3.rgb, num_format);
break;
case kXenosFormat_16_16_EDRAM:
case kXenosFormat_16_16:
packed.x = XePackR16G16UNorm(pixel_0.rg);
packed.y = XePackR16G16UNorm(pixel_1.rg);
packed.z = XePackR16G16UNorm(pixel_2.rg);
packed.w = XePackR16G16UNorm(pixel_3.rg);
packed.x = XePackR16G16(pixel_0.rg, num_format);
packed.y = XePackR16G16(pixel_1.rg, num_format);
packed.z = XePackR16G16(pixel_2.rg, num_format);
packed.w = XePackR16G16(pixel_3.rg, num_format);
break;
case kXenosFormat_16_16_FLOAT:
packed.x = pack_half_2x16_xe(float2_xe(pixel_0.r, pixel_0.g));
@@ -267,15 +316,16 @@ uint4_xe XePack32bpp4Pixels(float4_xe pixel_0, float4_xe pixel_1,
void XePack64bpp4Pixels(float4_xe pixel_0, float4_xe pixel_1,
float4_xe pixel_2, float4_xe pixel_3, uint format,
uint num_format,
out_param_xe(uint4_xe, packed_01),
out_param_xe(uint4_xe, packed_23)) {
switch (format) {
case kXenosFormat_16_16_16_16_EDRAM:
case kXenosFormat_16_16_16_16:
packed_01.xy = XePackR16G16B16A16UNorm(pixel_0);
packed_01.zw = XePackR16G16B16A16UNorm(pixel_1);
packed_23.xy = XePackR16G16B16A16UNorm(pixel_2);
packed_23.zw = XePackR16G16B16A16UNorm(pixel_3);
packed_01.xy = XePackR16G16B16A16(pixel_0, num_format);
packed_01.zw = XePackR16G16B16A16(pixel_1, num_format);
packed_23.xy = XePackR16G16B16A16(pixel_2, num_format);
packed_23.zw = XePackR16G16B16A16(pixel_3, num_format);
break;
case kXenosFormat_16_16_16_16_FLOAT:
packed_01.x = pack_half_2x16_xe(float2_xe(pixel_0.r, pixel_0.g));

View File

@@ -70,6 +70,7 @@ struct XeResolveInfo {
uint edram_base_tiles;
uint edram_format;
uint edram_format_ints_log2;
bool decode_pwl_gamma;
uint2_xe resolution_scale;
uint2_xe half_pixel_offset_fill_source;
uint2_xe edram_offset_scaled;
@@ -81,6 +82,7 @@ struct XeResolveInfo {
bool dest_is_array;
uint dest_slice;
uint dest_format;
uint dest_num_format;
float dest_exp_bias_factor;
bool dest_swap;
uint dest_row_pitch_macro_tiles;
@@ -101,6 +103,7 @@ XeResolveInfo XeResolveGetInfo(param_push_consts_xe) {
resolve_info.edram_base_tiles = (edram_info >> 13u) & ((1u << 11u) - 1u);
resolve_info.edram_format = (edram_info >> 24u) & ((1u << 4u) - 1u);
resolve_info.edram_format_ints_log2 = (edram_info >> 28u) & 1u;
resolve_info.decode_pwl_gamma = (edram_info & (1u << 30u)) != 0u;
#ifdef XE_RESOLVE_RESOLUTION_SCALED
resolve_info.resolution_scale =
(uint_x2_xe(coordinate_info) >> uint2_xe(16u, 19u)) & 7u;
@@ -132,6 +135,7 @@ XeResolveInfo XeResolveGetInfo(param_push_consts_xe) {
resolve_info.dest_is_array = (dest_info & (1u << 3u)) != 0u;
resolve_info.dest_slice = (dest_info >> 4u) & ((1u << 3u) - 1u);
resolve_info.dest_format = (dest_info >> 7u) & ((1u << 6u) - 1u);
resolve_info.dest_num_format = (dest_info >> 13u) & ((1u << 3u) - 1u);
resolve_info.dest_exp_bias_factor = int_bits_to_float_xe(
(int(dest_info) << (32 - (16 + 6)) >> (32 - 6) << 23) +
float_bits_to_int_xe(1.0f));
@@ -580,6 +584,127 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
}
}
// Gamma RTs store linear 10 bit color through an 8 bit PWL curve.
// Host sRGB is not a substitute. Some titles appear overexposed if full
// 8_8_8_8_GAMMA resolves average the encoded bytes directly (5345085D,
// 45410934), so we decode before MSAA averaging and encode again only
// for compatible 8_8_8_8 destinations.
float XePWLGammaToLinear(float gamma) {
gamma = saturate_xe(gamma);
float scale;
float offset;
if (gamma >= 96.0f / 255.0f) {
if (gamma >= 192.0f / 255.0f) {
scale = 8.0f / 1024.0f;
offset = -1024.0f;
} else {
scale = 4.0f / 1024.0f;
offset = -256.0f;
}
} else {
if (gamma >= 64.0f / 255.0f) {
scale = 2.0f / 1024.0f;
offset = -64.0f;
} else {
scale = 1.0f / 1024.0f;
offset = 0.0f;
}
}
float linear_value = gamma * (255.0f * 1024.0f) * scale + offset;
linear_value += trunc(linear_value * scale);
return linear_value * (1.0f / 1023.0f);
}
float3_xe XePWLGammaToLinear3(float3_xe gamma) {
return float3_xe(XePWLGammaToLinear(gamma.x),
XePWLGammaToLinear(gamma.y),
XePWLGammaToLinear(gamma.z));
}
float4_xe XePWLGammaToLinear4(float4_xe gamma) {
return float4_xe(XePWLGammaToLinear(gamma.x),
XePWLGammaToLinear(gamma.y),
XePWLGammaToLinear(gamma.z),
XePWLGammaToLinear(gamma.w));
}
float XeLinearToPWLGamma(float linear_value) {
linear_value = saturate_xe(linear_value);
float scale;
float offset;
if (linear_value >= 128.0f / 1023.0f) {
if (linear_value >= 512.0f / 1023.0f) {
scale = 1023.0f / 8.0f;
offset = 128.0f / 255.0f;
} else {
scale = 1023.0f / 4.0f;
offset = 64.0f / 255.0f;
}
} else {
if (linear_value >= 64.0f / 1023.0f) {
scale = 1023.0f / 2.0f;
offset = 32.0f / 255.0f;
} else {
scale = 1023.0f;
offset = 0.0f;
}
}
return trunc(linear_value * scale) * (1.0f / 255.0f) + offset;
}
float3_xe XeLinearToPWLGamma3(float3_xe linear_value) {
return float3_xe(XeLinearToPWLGamma(linear_value.x),
XeLinearToPWLGamma(linear_value.y),
XeLinearToPWLGamma(linear_value.z));
}
bool XeResolveSourceUsesPWLGamma(XeResolveInfo resolve_info) {
return resolve_info.decode_pwl_gamma &&
resolve_info.edram_format ==
kXenosColorRenderTargetFormat_8_8_8_8_GAMMA;
}
bool XeResolveDestStoresPWLGamma(XeResolveInfo resolve_info) {
// Resolve constants don't carry a destination gamma bit. Treat an
// unsigned 8_8_8_8 destination as PWL gamma storage.
bool dest_number_is_unorm =
resolve_info.dest_num_format ==
kXenosSurfaceNumberFormat_UnsignedRepeatingFraction;
bool dest_is_8888 =
resolve_info.dest_format == kXenosFormat_8_8_8_8 ||
resolve_info.dest_format == kXenosFormat_8_8_8_8_A ||
resolve_info.dest_format ==
kXenosFormat_8_8_8_8_AS_16_16_16_16;
return dest_number_is_unorm && dest_is_8888;
}
void XeResolvePWLGammaToLinearRGB(inout_param_xe(float4_xe, pixel)) {
pixel.rgb = XePWLGammaToLinear3(pixel.rgb);
}
void XeResolveLinearToPWLGammaRGB(inout_param_xe(float4_xe, pixel)) {
pixel.rgb = XeLinearToPWLGamma3(pixel.rgb);
}
void XeResolveDecodePWLGammaSource(
XeResolveInfo resolve_info, inout_param_xe(float4_xe, pixel)) {
// Source gamma is RGB only. 8_8_8_8_GAMMA still stores alpha as ordinary
// fixed data, so alpha needs to stay with normal resolve.
dont_flatten_xe if (XeResolveSourceUsesPWLGamma(resolve_info)) {
XeResolvePWLGammaToLinearRGB(pixel);
}
}
void XeResolveEncodePWLGammaDest(
XeResolveInfo resolve_info, inout_param_xe(float4_xe, pixel)) {
// Only re-encode when the source was PWL gamma and the destination is the
// 8_8_8_8 UNORM storage we treat as the same PWL byte stream.
dont_flatten_xe if (XeResolveSourceUsesPWLGamma(resolve_info) &&
XeResolveDestStoresPWLGamma(resolve_info)) {
XeResolveLinearToPWLGammaRGB(pixel);
}
}
void XeResolveLoad2RGBAColors(
param_byte_buffer_xe(xe_resolve_edram) param_next_after_byte_buffer_xe
XeResolveInfo resolve_info, uint address_bytes,
@@ -590,11 +715,12 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
address_bytes, pixel_stride_bytes,
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
pixel_0, pixel_1);
XeResolveDecodePWLGammaSource(resolve_info, pixel_0);
XeResolveDecodePWLGammaSource(resolve_info, pixel_1);
float exp_bias = resolve_info.dest_exp_bias_factor;
dont_flatten_xe
if (resolve_info.sample_select >= kXenosCopySampleSelect_01) {
uint tile_row_stride_bytes = 4u * 80u * resolve_info.resolution_scale.x;
// TODO(Triang3l): Gamma-correct resolve for 8_8_8_8_GAMMA.
exp_bias *= 0.5f;
float4_xe msaa_resolve_pixel_0, msaa_resolve_pixel_1;
XeResolveLoad2RGBAUnswappedPixelSamplesFromRaw(
@@ -602,6 +728,8 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
address_bytes + tile_row_stride_bytes, pixel_stride_bytes,
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
msaa_resolve_pixel_0, msaa_resolve_pixel_1);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_0);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_1);
pixel_0 += msaa_resolve_pixel_0;
pixel_1 += msaa_resolve_pixel_1;
dont_flatten_xe
@@ -614,6 +742,8 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
address_bytes + sample_stride_bytes, pixel_stride_bytes,
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
msaa_resolve_pixel_0, msaa_resolve_pixel_1);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_0);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_1);
pixel_0 += msaa_resolve_pixel_0;
pixel_1 += msaa_resolve_pixel_1;
XeResolveLoad2RGBAUnswappedPixelSamplesFromRaw(
@@ -623,12 +753,16 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
pixel_stride_bytes, resolve_info.edram_format_ints_log2,
resolve_info.edram_format, msaa_resolve_pixel_0,
msaa_resolve_pixel_1);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_0);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_1);
pixel_0 += msaa_resolve_pixel_0;
pixel_1 += msaa_resolve_pixel_1;
}
}
pixel_0 *= exp_bias;
pixel_1 *= exp_bias;
XeResolveEncodePWLGammaDest(resolve_info, pixel_0);
XeResolveEncodePWLGammaDest(resolve_info, pixel_1);
dont_flatten_xe if (resolve_info.dest_swap) {
pixel_0 = pixel_0.bgra;
pixel_1 = pixel_1.bgra;
@@ -646,11 +780,14 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
address_bytes, pixel_stride_bytes,
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
pixel_0, pixel_1, pixel_2, pixel_3);
XeResolveDecodePWLGammaSource(resolve_info, pixel_0);
XeResolveDecodePWLGammaSource(resolve_info, pixel_1);
XeResolveDecodePWLGammaSource(resolve_info, pixel_2);
XeResolveDecodePWLGammaSource(resolve_info, pixel_3);
float exp_bias = resolve_info.dest_exp_bias_factor;
dont_flatten_xe
if (resolve_info.sample_select >= kXenosCopySampleSelect_01) {
uint tile_row_stride_bytes = 4u * 80u * resolve_info.resolution_scale.x;
// TODO(Triang3l): Gamma-correct resolve for 8_8_8_8_GAMMA.
exp_bias *= 0.5f;
float4_xe msaa_resolve_pixel_0;
float4_xe msaa_resolve_pixel_1;
@@ -662,6 +799,10 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
msaa_resolve_pixel_0, msaa_resolve_pixel_1, msaa_resolve_pixel_2,
msaa_resolve_pixel_3);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_0);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_1);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_2);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_3);
pixel_0 += msaa_resolve_pixel_0;
pixel_1 += msaa_resolve_pixel_1;
pixel_2 += msaa_resolve_pixel_2;
@@ -677,6 +818,10 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
msaa_resolve_pixel_0, msaa_resolve_pixel_1, msaa_resolve_pixel_2,
msaa_resolve_pixel_3);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_0);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_1);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_2);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_3);
pixel_0 += msaa_resolve_pixel_0;
pixel_1 += msaa_resolve_pixel_1;
pixel_2 += msaa_resolve_pixel_2;
@@ -688,6 +833,10 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
pixel_stride_bytes, resolve_info.edram_format_ints_log2,
resolve_info.edram_format, msaa_resolve_pixel_0,
msaa_resolve_pixel_1, msaa_resolve_pixel_2, msaa_resolve_pixel_3);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_0);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_1);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_2);
XeResolveDecodePWLGammaSource(resolve_info, msaa_resolve_pixel_3);
pixel_0 += msaa_resolve_pixel_0;
pixel_1 += msaa_resolve_pixel_1;
pixel_2 += msaa_resolve_pixel_2;
@@ -698,6 +847,10 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
pixel_1 *= exp_bias;
pixel_2 *= exp_bias;
pixel_3 *= exp_bias;
XeResolveEncodePWLGammaDest(resolve_info, pixel_0);
XeResolveEncodePWLGammaDest(resolve_info, pixel_1);
XeResolveEncodePWLGammaDest(resolve_info, pixel_2);
XeResolveEncodePWLGammaDest(resolve_info, pixel_3);
dont_flatten_xe if (resolve_info.dest_swap) {
pixel_0 = pixel_0.bgra;
pixel_1 = pixel_1.bgra;
@@ -721,11 +874,14 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
address_bytes, pixel_stride_bytes,
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
resolve_info.dest_swap, pixels_0123, pixels_4567);
dont_flatten_xe if (XeResolveSourceUsesPWLGamma(resolve_info)) {
pixels_0123 = XePWLGammaToLinear4(pixels_0123);
pixels_4567 = XePWLGammaToLinear4(pixels_4567);
}
float exp_bias = resolve_info.dest_exp_bias_factor;
dont_flatten_xe
if (resolve_info.sample_select >= kXenosCopySampleSelect_01) {
uint tile_row_stride_bytes = 4u * 80u * resolve_info.resolution_scale.x;
// TODO(Triang3l): Gamma-correct resolve for 8_8_8_8_GAMMA.
exp_bias *= 0.5f;
float4_xe msaa_resolve_pixels_0123, msaa_resolve_pixels_4567;
XeResolveLoad8RedPixelSamplesFromRaw(
@@ -734,6 +890,12 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
resolve_info.dest_swap, msaa_resolve_pixels_0123,
msaa_resolve_pixels_4567);
dont_flatten_xe if (XeResolveSourceUsesPWLGamma(resolve_info)) {
msaa_resolve_pixels_0123 =
XePWLGammaToLinear4(msaa_resolve_pixels_0123);
msaa_resolve_pixels_4567 =
XePWLGammaToLinear4(msaa_resolve_pixels_4567);
}
pixels_0123 += msaa_resolve_pixels_0123;
pixels_4567 += msaa_resolve_pixels_4567;
dont_flatten_xe
@@ -747,6 +909,12 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
resolve_info.dest_swap, msaa_resolve_pixels_0123,
msaa_resolve_pixels_4567);
dont_flatten_xe if (XeResolveSourceUsesPWLGamma(resolve_info)) {
msaa_resolve_pixels_0123 =
XePWLGammaToLinear4(msaa_resolve_pixels_0123);
msaa_resolve_pixels_4567 =
XePWLGammaToLinear4(msaa_resolve_pixels_4567);
}
pixels_0123 += msaa_resolve_pixels_0123;
pixels_4567 += msaa_resolve_pixels_4567;
XeResolveLoad8RedPixelSamplesFromRaw(
@@ -756,6 +924,12 @@ uint XeResolveEdramPixelStrideBytes(XeResolveInfo resolve_info) {
pixel_stride_bytes, resolve_info.edram_format_ints_log2,
resolve_info.edram_format, resolve_info.dest_swap,
msaa_resolve_pixels_0123, msaa_resolve_pixels_4567);
dont_flatten_xe if (XeResolveSourceUsesPWLGamma(resolve_info)) {
msaa_resolve_pixels_0123 =
XePWLGammaToLinear4(msaa_resolve_pixels_0123);
msaa_resolve_pixels_4567 =
XePWLGammaToLinear4(msaa_resolve_pixels_4567);
}
pixels_0123 += msaa_resolve_pixels_0123;
pixels_4567 += msaa_resolve_pixels_4567;
}

View File

@@ -42,7 +42,8 @@ entry_inputs_end_code_begin_compute_xe
resolve_info, pixel_index),
pixel_0, pixel_1, pixel_2, pixel_3);
uint2_xe packed = XePack16bpp4PixelsInUInt2(
pixel_0, pixel_1, pixel_2, pixel_3, resolve_info.dest_format);
pixel_0, pixel_1, pixel_2, pixel_3, resolve_info.dest_format,
resolve_info.dest_num_format);
dont_flatten_xe
if (pixel_index.x == 0u &&
resolve_info.half_pixel_offset_fill_source.x != 0u) {

View File

@@ -44,7 +44,8 @@ entry_inputs_end_code_begin_compute_xe
resolve_info, pixel_index),
pixel_0, pixel_1, pixel_2, pixel_3);
uint4_xe packed = XePack32bpp4Pixels(pixel_0, pixel_1, pixel_2, pixel_3,
resolve_info.dest_format);
resolve_info.dest_format,
resolve_info.dest_num_format);
dont_flatten_xe
if (pixel_index.x == 0u &&
resolve_info.half_pixel_offset_fill_source.x != 0u) {

View File

@@ -43,7 +43,8 @@ entry_inputs_end_code_begin_compute_xe
pixel_0, pixel_1, pixel_2, pixel_3);
uint4_xe packed_01, packed_23;
XePack64bpp4Pixels(pixel_0, pixel_1, pixel_2, pixel_3,
resolve_info.dest_format, packed_01, packed_23);
resolve_info.dest_format,
resolve_info.dest_num_format, packed_01, packed_23);
dont_flatten_xe
if (pixel_index.x == 0u &&
resolve_info.half_pixel_offset_fill_source.x != 0u) {

View File

@@ -56,7 +56,7 @@ entry_inputs_end_code_begin_compute_xe
// TODO(Triang3l): Investigate formats 8_A and 8_B.
byte_buffer_align8_store8_xe(
xe_resolve_dest, XeResolveDestPixelAddress(resolve_info, pixel_index, 0u),
uint2_xe(XePackR8G8B8A8UNorm(pixels_0123),
XePackR8G8B8A8UNorm(pixels_4567)));
uint2_xe(XePackR8G8B8A8(pixels_0123, resolve_info.dest_num_format),
XePackR8G8B8A8(pixels_4567, resolve_info.dest_num_format)));
}
entry_code_end_compute_xe

View File

@@ -49,6 +49,8 @@ cbuffer xe_system_cbuffer : register(b0) {
uint4 xe_edram_rt_blend_factors_ops;
float4 xe_edram_blend_constant;
uint4 xe_texture_integer_scale_bits[8];
};
struct XeHSControlPointInputIndexed {