shader_recompiler: Add more instructions

This commit is contained in:
IndecisiveTurtle 2024-06-21 17:35:53 +03:00 committed by georgemoralis
parent ce31fad222
commit 8850c2f4be
7 changed files with 122 additions and 7 deletions

View File

@ -54,7 +54,11 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id of
Id ms) {
const auto& texture = ctx.images[handle & 0xFFFF];
const Id image = ctx.OpLoad(texture.image_type, texture.id);
return ctx.OpImageFetch(ctx.F32[4], image, coords, spv::ImageOperandsMask::Lod, lod);
if (Sirit::ValidId(lod)) {
return ctx.OpImageFetch(ctx.F32[4], image, coords, spv::ImageOperandsMask::Lod, lod);
} else {
return ctx.OpImageFetch(ctx.F32[4], image, coords);
}
}
Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod,

View File

@ -216,6 +216,14 @@ void Translator::S_AND_B32(const GcnInst& inst) {
ir.SetScc(ir.INotEqual(result, ir.Imm32(0)));
}
void Translator::S_OR_B32(const GcnInst& inst) {
const IR::U32 src0{GetSrc(inst.src[0])};
const IR::U32 src1{GetSrc(inst.src[1])};
const IR::U32 result{ir.BitwiseOr(src0, src1)};
SetDst(inst.dst[0], result);
ir.SetScc(ir.INotEqual(result, ir.Imm32(0)));
}
void Translator::S_LSHR_B32(const GcnInst& inst) {
const IR::U32 src0{GetSrc(inst.src[0])};
const IR::U32 src1{GetSrc(inst.src[1])};
@ -285,4 +293,32 @@ void Translator::S_BFM_B32(const GcnInst& inst) {
SetDst(inst.dst[0], ir.ShiftLeftLogical(mask, src1));
}
void Translator::S_NOT_B64(const GcnInst& inst) {
const auto get_src = [&](const InstOperand& operand) {
switch (operand.field) {
case OperandField::VccLo:
return ir.GetVcc();
case OperandField::ExecLo:
return ir.GetExec();
case OperandField::ScalarGPR:
return ir.GetThreadBitScalarReg(IR::ScalarReg(operand.code));
default:
UNREACHABLE();
}
};
const IR::U1 src0{get_src(inst.src[0])};
const IR::U1 result = ir.LogicalNot(src0);
ir.SetScc(result);
switch (inst.dst[0].field) {
case OperandField::VccLo:
ir.SetVcc(result);
break;
case OperandField::ScalarGPR:
ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[0].code), result);
break;
default:
UNREACHABLE();
}
}
} // namespace Shader::Gcn

View File

@ -324,7 +324,10 @@ void Translate(IR::Block* block, std::span<const GcnInst> inst_list, Info& info)
translator.IMAGE_STORE(inst);
break;
case Opcode::IMAGE_LOAD_MIP:
translator.IMAGE_LOAD_MIP(inst);
translator.IMAGE_LOAD(true, inst);
break;
case Opcode::IMAGE_LOAD:
translator.IMAGE_LOAD(false, inst);
break;
case Opcode::V_CMP_GE_I32:
translator.V_CMP_U32(ConditionOp::GE, true, false, inst);
@ -335,6 +338,9 @@ void Translate(IR::Block* block, std::span<const GcnInst> inst_list, Info& info)
case Opcode::V_CMP_LE_I32:
translator.V_CMP_U32(ConditionOp::LE, true, false, inst);
break;
case Opcode::V_CMP_NE_I32:
translator.V_CMP_U32(ConditionOp::LG, true, false, inst);
break;
case Opcode::V_CMP_NE_U32:
translator.V_CMP_U32(ConditionOp::LG, false, false, inst);
break;
@ -386,6 +392,9 @@ void Translate(IR::Block* block, std::span<const GcnInst> inst_list, Info& info)
case Opcode::V_CMP_NLT_F32:
translator.V_CMP_F32(ConditionOp::GE, false, inst);
break;
case Opcode::S_CMP_LT_U32:
translator.S_CMP(ConditionOp::LT, false, inst);
break;
case Opcode::S_CMP_LG_U32:
translator.S_CMP(ConditionOp::LG, false, inst);
break;
@ -585,6 +594,9 @@ void Translate(IR::Block* block, std::span<const GcnInst> inst_list, Info& info)
case Opcode::S_AND_B64:
translator.S_AND_B64(false, inst);
break;
case Opcode::S_NOT_B64:
translator.S_NOT_B64(inst);
break;
case Opcode::S_NAND_B64:
translator.S_AND_B64(true, inst);
break;
@ -627,6 +639,9 @@ void Translate(IR::Block* block, std::span<const GcnInst> inst_list, Info& info)
case Opcode::S_AND_B32:
translator.S_AND_B32(inst);
break;
case Opcode::S_OR_B32:
translator.S_OR_B32(inst);
break;
case Opcode::S_LSHR_B32:
translator.S_LSHR_B32(inst);
break;
@ -657,9 +672,21 @@ void Translate(IR::Block* block, std::span<const GcnInst> inst_list, Info& info)
case Opcode::S_BFM_B32:
translator.S_BFM_B32(inst);
break;
case Opcode::V_MIN_U32:
translator.V_MIN_U32(inst);
break;
case Opcode::V_CMP_NE_U64:
translator.V_CMP_NE_U64(inst);
break;
case Opcode::V_TRUNC_F32:
translator.V_TRUNC_F32(inst);
break;
case Opcode::V_CEIL_F32:
translator.V_CEIL_F32(inst);
break;
case Opcode::S_TTRACEDATA:
LOG_WARNING(Render_Vulkan, "S_TTRACEDATA instruction!");
break;
case Opcode::S_NOP:
case Opcode::S_CBRANCH_EXECZ:
case Opcode::S_CBRANCH_SCC0:

View File

@ -45,12 +45,14 @@ public:
void S_AND_B64(bool negate, const GcnInst& inst);
void S_ADD_I32(const GcnInst& inst);
void S_AND_B32(const GcnInst& inst);
void S_OR_B32(const GcnInst& inst);
void S_LSHR_B32(const GcnInst& inst);
void S_CSELECT_B32(const GcnInst& inst);
void S_CSELECT_B64(const GcnInst& inst);
void S_BFE_U32(const GcnInst& inst);
void S_LSHL_B32(const GcnInst& inst);
void S_BFM_B32(const GcnInst& inst);
void S_NOT_B64(const GcnInst& inst);
// Scalar Memory
void S_LOAD_DWORD(int num_dwords, const GcnInst& inst);
@ -115,6 +117,9 @@ public:
void V_MIN_I32(const GcnInst& inst);
void V_MUL_LO_U32(const GcnInst& inst);
void V_TRUNC_F32(const GcnInst& inst);
void V_CEIL_F32(const GcnInst& inst);
void V_MIN_U32(const GcnInst& inst);
void V_CMP_NE_U64(const GcnInst& inst);
// Vector Memory
void BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, const GcnInst& inst);
@ -132,7 +137,7 @@ public:
void IMAGE_GET_RESINFO(const GcnInst& inst);
void IMAGE_SAMPLE(const GcnInst& inst);
void IMAGE_STORE(const GcnInst& inst);
void IMAGE_LOAD_MIP(const GcnInst& inst);
void IMAGE_LOAD(bool has_mip, const GcnInst& inst);
// Export
void EXP(const GcnInst& inst);

View File

@ -430,4 +430,44 @@ void Translator::V_TRUNC_F32(const GcnInst& inst) {
SetDst(inst.dst[0], ir.FPTrunc(src0));
}
void Translator::V_CEIL_F32(const GcnInst& inst) {
const IR::F32 src0{GetSrc(inst.src[0], true)};
SetDst(inst.dst[0], ir.FPCeil(src0));
}
void Translator::V_MIN_U32(const GcnInst& inst) {
const IR::U32 src0{GetSrc(inst.src[0])};
const IR::U32 src1{GetSrc(inst.src[1])};
SetDst(inst.dst[0], ir.IMin(src0, src1, false));
}
void Translator::V_CMP_NE_U64(const GcnInst& inst) {
const auto get_src = [&](const InstOperand& operand) {
switch (operand.field) {
case OperandField::VccLo:
return ir.GetVcc();
case OperandField::ExecLo:
return ir.GetExec();
case OperandField::ScalarGPR:
return ir.GetThreadBitScalarReg(IR::ScalarReg(operand.code));
case OperandField::ConstZero:
return ir.Imm1(false);
default:
UNREACHABLE();
}
};
const IR::U1 src0{get_src(inst.src[0])};
ASSERT(inst.src[1].field == OperandField::ConstZero); // src0 != 0
switch (inst.dst[1].field) {
case OperandField::VccLo:
ir.SetVcc(src0);
break;
case OperandField::ScalarGPR:
ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[1].code), src0);
break;
default:
UNREACHABLE();
}
}
} // namespace Shader::Gcn

View File

@ -31,7 +31,9 @@ void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) {
void Translator::IMAGE_SAMPLE(const GcnInst& inst) {
const auto& mimg = inst.control.mimg;
ASSERT(!mimg.da);
if (mimg.da) {
LOG_WARNING(Render_Vulkan, "Image instruction declares an array");
}
IR::VectorReg addr_reg{inst.src[0].code};
IR::VectorReg dest_reg{inst.dst[0].code};
@ -107,7 +109,7 @@ void Translator::IMAGE_SAMPLE(const GcnInst& inst) {
}
}
void Translator::IMAGE_LOAD_MIP(const GcnInst& inst) {
void Translator::IMAGE_LOAD(bool has_mip, const GcnInst& inst) {
const auto& mimg = inst.control.mimg;
IR::VectorReg addr_reg{inst.src[0].code};
IR::VectorReg dest_reg{inst.dst[0].code};
@ -119,7 +121,7 @@ void Translator::IMAGE_LOAD_MIP(const GcnInst& inst) {
ir.GetVectorReg(addr_reg + 2), ir.GetVectorReg(addr_reg + 3));
IR::TextureInstInfo info{};
info.explicit_lod.Assign(1);
info.explicit_lod.Assign(has_mip);
const IR::Value texel = ir.ImageFetch(handle, body, {}, {}, {}, info);
for (u32 i = 0; i < 4; i++) {

View File

@ -251,7 +251,8 @@ IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value&
void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) {
IR::Inst* producer = inst.Arg(0).InstRecursive();
ASSERT(producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2 ||
ASSERT(producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2 || // IMAGE_SAMPLE (image+sampler)
producer->GetOpcode() == IR::Opcode::ReadConst || // IMAGE_LOAD (image only)
producer->GetOpcode() == IR::Opcode::GetUserData);
const auto [tsharp_handle, ssharp_handle] = [&] -> std::pair<IR::Inst*, IR::Inst*> {
if (producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2) {