mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
graphics: render packed 11-11-10 UNorm targets with exact rounding
Co-authored-by: fxpw <fxpw@outlook.com>
This commit is contained in:
@@ -567,6 +567,28 @@ void EmitSetAttribute(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
mapping.Map(3));
|
||||
value = mapped;
|
||||
}
|
||||
if ((state.input_info.pixel->target_packed_unorm_mask & (1u << exp.index)) != 0u) {
|
||||
if (exp.compr || MrtOutputMode(state, exp) != 9u ||
|
||||
(mapping.ApplyMask(exp.en) & 7u) != 7u) {
|
||||
EXIT("unsupported packed UNorm EXP: export=%u mode=%u en=0x%x compr=%u\n",
|
||||
exp.index, MrtOutputMode(state, exp), exp.en, static_cast<uint32_t>(exp.compr));
|
||||
}
|
||||
const auto info = Format::GetFormatInfo(Prospero::BufferFormat::k11_11_10UNorm);
|
||||
const auto rounding = (state.input_info.pixel->target_round_mode & (1u << exp.index)) != 0
|
||||
? UnormRounding::Truncate : UnormRounding::HalfUp;
|
||||
const auto raw = Unary(state, spv::OpBitcast, TypeU32Vector(state, 4), value);
|
||||
auto packed = ConstantU32(state, 0);
|
||||
for (uint32_t component = 0; component < info.component_count; component++) {
|
||||
const auto encoded = EncodePackedColorComponent(
|
||||
state, info, component, ExportRawComponent(ctx, raw, component), 32u, rounding);
|
||||
packed = component == 0u ? encoded
|
||||
: Binary(state, spv::OpBitwiseOr, TypeU32(state), packed, encoded);
|
||||
}
|
||||
value = state.builder.AllocateId();
|
||||
state.builder.AddFunction(spv::OpCompositeConstruct, TypeU32Vector(state, 4), value,
|
||||
packed, ConstantU32(state, 0), ConstantU32(state, 0),
|
||||
ConstantU32(state, 0));
|
||||
}
|
||||
}
|
||||
if (exp.kind == IR::ExportTargetKind::Position &&
|
||||
state.input_info.vertex->clip_space.enabled) {
|
||||
|
||||
@@ -456,11 +456,15 @@ uint32_t EmitUFloatToF32Bits(EmitterState& state, uint32_t raw, uint32_t bits);
|
||||
uint32_t NormalizeFormatComponent(EmitterState& state, const Format::BufferFormatInfo& info,
|
||||
uint32_t component, uint32_t raw);
|
||||
|
||||
enum class UnormRounding { RoundEven, HalfUp, Truncate };
|
||||
|
||||
uint32_t EncodeFormattedStoreComponent(EmitterState& state, const Format::BufferFormatInfo& info,
|
||||
uint32_t component, uint32_t data, uint32_t data_bits);
|
||||
uint32_t component, uint32_t data, uint32_t data_bits,
|
||||
UnormRounding rounding = UnormRounding::RoundEven);
|
||||
|
||||
uint32_t EncodePackedColorComponent(EmitterState& state, const Format::BufferFormatInfo& info,
|
||||
uint32_t component, uint32_t data, uint32_t data_bits);
|
||||
uint32_t component, uint32_t data, uint32_t data_bits,
|
||||
UnormRounding rounding = UnormRounding::RoundEven);
|
||||
|
||||
spv::Op SpirvAtomicOpcode(IR::ValueOpcode opcode);
|
||||
|
||||
|
||||
@@ -429,7 +429,9 @@ uint32_t NormalizeFormatComponent(EmitterState& state, const Format::BufferForma
|
||||
}
|
||||
|
||||
uint32_t EncodeFormattedStoreComponent(EmitterState& state, const Format::BufferFormatInfo& info,
|
||||
uint32_t component, uint32_t data, uint32_t data_bits) {
|
||||
uint32_t component, uint32_t data, uint32_t data_bits,
|
||||
UnormRounding rounding) {
|
||||
EXIT_IF(rounding != UnormRounding::RoundEven && info.type != Format::ComponentType::Unorm);
|
||||
const auto bits = info.component_bits[component];
|
||||
if (data_bits == 16u) {
|
||||
if (info.type == Format::ComponentType::Uint) {
|
||||
@@ -464,8 +466,12 @@ uint32_t EncodeFormattedStoreComponent(EmitterState& state, const Format::Buffer
|
||||
value = EmitGlsl<GLSLstd450FClamp, IR::Type::F32>(
|
||||
state, value, ConstantF32Value(state, lower), ConstantF32Value(state, upper));
|
||||
if (normalized) {
|
||||
value = EmitFPRoundEven32(
|
||||
state, EmitFPMul32(state, value, ConstantF32Value(state, max_value)));
|
||||
value = EmitFPMul32(state, value, ConstantF32Value(state, max_value));
|
||||
if (rounding == UnormRounding::RoundEven) {
|
||||
value = EmitFPRoundEven32(state, value);
|
||||
} else if (rounding == UnormRounding::HalfUp) {
|
||||
value = EmitFPAdd32(state, value, ConstantF32Value(state, 0.5f));
|
||||
}
|
||||
}
|
||||
// Float-to-integer conversion truncates scaled values toward zero.
|
||||
value = Unary(state, is_signed ? spv::OpConvertFToS : spv::OpConvertFToU,
|
||||
@@ -481,8 +487,9 @@ uint32_t EncodeFormattedStoreComponent(EmitterState& state, const Format::Buffer
|
||||
}
|
||||
|
||||
uint32_t EncodePackedColorComponent(EmitterState& state, const Format::BufferFormatInfo& info,
|
||||
uint32_t component, uint32_t data, uint32_t data_bits) {
|
||||
auto value = EncodeFormattedStoreComponent(state, info, component, data, data_bits);
|
||||
uint32_t component, uint32_t data, uint32_t data_bits,
|
||||
UnormRounding rounding) {
|
||||
auto value = EncodeFormattedStoreComponent(state, info, component, data, data_bits, rounding);
|
||||
if (info.type == Format::ComponentType::Uint) {
|
||||
value = EmitUMin32(state, value,
|
||||
ConstantU32(state, (1u << info.component_bits[component]) - 1u));
|
||||
|
||||
@@ -663,7 +663,8 @@ void DefineOutputs(EmitterState& state) {
|
||||
binding.kind == IR::StageOutputKind::Mrt &&
|
||||
state.program.stage == ShaderType::Pixel &&
|
||||
binding.index < std::size(state.input_info.pixel->target_output_mode) &&
|
||||
state.input_info.pixel->target_output_mode[binding.index] == 7u;
|
||||
(state.input_info.pixel->target_output_mode[binding.index] == 7u ||
|
||||
(state.input_info.pixel->target_packed_unorm_mask & (1u << binding.index)) != 0u);
|
||||
const auto type = uint_output ? TypeU32Vector(state, 4) : TypeF32Vector(state, 4);
|
||||
binding.variable_id = DefineInterfaceVariable(state, type, spv::StorageClassOutput,
|
||||
binding.debug_name.c_str());
|
||||
|
||||
Reference in New Issue
Block a user