[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:
committed by
Radosław Gliński
parent
573cce0fe2
commit
d119505289
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user