Patch read and write

TODO: atomic instructions
This commit is contained in:
Lander Gallastegi 2024-11-13 23:19:26 +01:00
parent a4010b3312
commit 78ad50bf56
2 changed files with 66 additions and 23 deletions

View File

@ -8,6 +8,7 @@
#include "shader_recompiler/ir/breadth_first_search.h" #include "shader_recompiler/ir/breadth_first_search.h"
#include "shader_recompiler/ir/ir_emitter.h" #include "shader_recompiler/ir/ir_emitter.h"
#include "shader_recompiler/ir/program.h" #include "shader_recompiler/ir/program.h"
#include "video_core/amdgpu/pixel_format.h"
#include "video_core/amdgpu/resource.h" #include "video_core/amdgpu/resource.h"
namespace Shader::Optimization { namespace Shader::Optimization {
@ -417,24 +418,54 @@ IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value&
} }
} }
bool ShouldPatchNormalization(const AmdGpu::Image& image) { void PatchNormalization(IR::Inst& inst, IR::IREmitter& ir, const AmdGpu::Image& image,
if (image.GetNumberFmt() == AmdGpu::NumberFormat::Unorm || bool is_write) {
image.GetNumberFmt() == AmdGpu::NumberFormat::Snorm) { if (!image.NeedsNormalizationPatch()) {
switch (image.GetDataFmt()) { return;
case AmdGpu::DataFormat::Format32:
case AmdGpu::DataFormat::Format32_32:
case AmdGpu::DataFormat::Format32_32_32:
case AmdGpu::DataFormat::Format32_32_32_32:
return true;
default:
return false;
}
}
return false;
} }
void PatchNormalization(IR::Inst& inst, IR::IREmitter& ir, const AmdGpu::Image& image, bool is_signed = image.GetNumberFmt() == AmdGpu::NumberFormat::Snorm;
bool is_write) {} int num_components = AmdGpu::NumComponents(image.GetDataFmt());
IR::F32 multipier = ir.Imm32(is_signed ? 2147483647.0f : 4294967295.0f);
if (!is_write)
multipier = ir.FPRecip(multipier);
switch (num_components) {
case 1:
break;
case 2:
multipier = IR::F32{ir.CompositeConstruct(multipier, multipier)};
case 3:
multipier = IR::F32{ir.CompositeConstruct(multipier, multipier, multipier)};
case 4:
multipier = IR::F32{ir.CompositeConstruct(multipier, multipier, multipier, multipier)};
default:
UNREACHABLE();
}
if (is_write) {
IR::F32 data = IR::F32{inst.Arg(2)};
data = ir.FPMul(data, multipier);
if (is_signed) {
inst.SetArg(2, ir.ConvertFToS(32, data));
} else {
inst.SetArg(2, ir.ConvertFToU(32, data));
}
} else {
IR::Value data = IR::Value(ir.CopyInst(inst));
if (is_signed) {
data = ir.ConvertSToF(32, 32, data);
} else {
data = ir.ConvertUToF(32, 32, data);
}
data = ir.FPMul(IR::F32(data), multipier);
inst.ReplaceUsesWith(data);
}
}
void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info, void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info,
Descriptors& descriptors, const IR::Inst* producer, Descriptors& descriptors, const IR::Inst* producer,
@ -618,10 +649,8 @@ void PatchImageSampleInstruction(IR::Block& block, IR::Inst& inst, Info& info,
}(); }();
inst.ReplaceUsesWith(new_inst); inst.ReplaceUsesWith(new_inst);
if (ShouldPatchNormalization(image)) {
PatchNormalization(*new_inst.Inst(), ir, image, false); PatchNormalization(*new_inst.Inst(), ir, image, false);
} }
}
void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) { void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) {
const auto pred = [](const IR::Inst* inst) -> std::optional<const IR::Inst*> { const auto pred = [](const IR::Inst* inst) -> std::optional<const IR::Inst*> {
@ -748,10 +777,8 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip
inst.SetArg(4, arg); inst.SetArg(4, arg);
} }
if (ShouldPatchNormalization(image)) {
PatchNormalization(inst, ir, image, inst.GetOpcode() == IR::Opcode::ImageWrite); PatchNormalization(inst, ir, image, inst.GetOpcode() == IR::Opcode::ImageWrite);
} }
}
void PatchDataRingInstruction(IR::Block& block, IR::Inst& inst, Info& info, void PatchDataRingInstruction(IR::Block& block, IR::Inst& inst, Info& info,
Descriptors& descriptors) { Descriptors& descriptors) {

View File

@ -291,6 +291,22 @@ struct Image {
return static_cast<TilingMode>(tiling_index); return static_cast<TilingMode>(tiling_index);
} }
bool NeedsNormalizationPatch() const {
if (GetNumberFmt() == AmdGpu::NumberFormat::Unorm ||
GetNumberFmt() == AmdGpu::NumberFormat::Snorm) {
switch (GetDataFmt()) {
case AmdGpu::DataFormat::Format32:
case AmdGpu::DataFormat::Format32_32:
case AmdGpu::DataFormat::Format32_32_32:
case AmdGpu::DataFormat::Format32_32_32_32:
return true;
default:
return false;
}
}
return false;
}
bool IsTiled() const { bool IsTiled() const {
return GetTilingMode() != TilingMode::Display_Linear; return GetTilingMode() != TilingMode::Display_Linear;
} }