[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

@@ -2308,6 +2308,82 @@ void SpirvShaderTranslator::ProcessTextureFetchInstruction(
}
}
// num_format is applied after signs/gamma. Fixed textures sample as
// normalized host values, so integer num_format scales them back to
// guest integer units here.
id_vector_temp_.clear();
id_vector_temp_.push_back(
builder_->makeIntConstant(kSystemConstantTextureIntegerScaleBits));
id_vector_temp_.push_back(
builder_->makeIntConstant(int32_t(fetch_constant_index >> 2)));
id_vector_temp_.push_back(
builder_->makeIntConstant(int32_t(fetch_constant_index & 3)));
spv::Id integer_scale_bits_packed = builder_->createLoad(
builder_->createAccessChain(spv::StorageClassUniform,
uniform_system_constants_,
id_vector_temp_),
spv::NoPrecision);
{
// Uniform early out. Zero means leave the sample alone. Only integer
// num_format on fixed textures has scale bits.
spv::Id integer_scale_active = builder_->createBinOp(
spv::OpINotEqual, type_bool_, integer_scale_bits_packed,
builder_->makeUintConstant(0));
SpirvBuilder::IfBuilder if_integer_scale(
integer_scale_active, spv::SelectionControlMaskNone, *builder_);
spv::Id scaled_result[4] = {};
{
spv::Id const_uint_1 = builder_->makeUintConstant(1);
uint32_t result_remaining_components =
used_result_nonzero_components;
uint32_t result_component_index;
while (xe::bit_scan_forward(result_remaining_components,
&result_component_index)) {
result_remaining_components &=
~(UINT32_C(1) << result_component_index);
spv::Id scale_bits = builder_->createTriOp(
spv::OpBitFieldUExtract, type_uint_,
integer_scale_bits_packed,
builder_->makeUintConstant(result_component_index * 5),
builder_->makeUintConstant(5));
spv::Id scale_shift = builder_->createBinOp(
spv::OpIAdd, type_uint_,
builder_->createBinOp(spv::OpBitwiseAnd, type_uint_,
scale_bits,
builder_->makeUintConstant(0xF)),
const_uint_1);
scale_shift = builder_->createBinOp(
spv::OpISub, type_uint_, scale_shift,
builder_->createTriOp(spv::OpBitFieldUExtract, type_uint_,
scale_bits,
builder_->makeUintConstant(4),
builder_->makeUintConstant(1)));
spv::Id scale_uint = builder_->createBinOp(
spv::OpISub, type_uint_,
builder_->createBinOp(spv::OpShiftLeftLogical, type_uint_,
const_uint_1, scale_shift),
const_uint_1);
scaled_result[result_component_index] =
builder_->createNoContractionBinOp(
spv::OpFMul, type_float_, result[result_component_index],
builder_->createUnaryOp(spv::OpConvertUToF, type_float_,
scale_uint));
}
}
if_integer_scale.makeEndIf();
// Keep the original result when the scale branch is skipped.
uint32_t result_remaining_components = used_result_nonzero_components;
uint32_t result_component_index;
while (xe::bit_scan_forward(result_remaining_components,
&result_component_index)) {
result_remaining_components &=
~(UINT32_C(1) << result_component_index);
result[result_component_index] = if_integer_scale.createMergePhi(
scaled_result[result_component_index],
result[result_component_index]);
}
}
// Apply the exponent bias from the bits 13:18 of the fetch constant
// word 3.
spv::Id result_exponent_bias = builder_->createBinBuiltinCall(