diff options
| author | 2021-03-08 18:31:53 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:23 -0400 | |
| commit | ab463712474de5f99eec137a9c6233e55fe184f0 (patch) | |
| tree | 30d79ac64dd03d5cfafd07c0c42c2baadc82de98 /src/shader_recompiler/frontend/ir/ir_emitter.cpp | |
| parent | shader: Implement R2P (diff) | |
| download | yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.gz yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.xz yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.zip | |
shader: Initial support for textures and TEX
Diffstat (limited to 'src/shader_recompiler/frontend/ir/ir_emitter.cpp')
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.cpp | 133 |
1 files changed, 131 insertions, 2 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index f38b46bac..ae3354c66 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -7,11 +7,24 @@ | |||
| 7 | #include "shader_recompiler/frontend/ir/value.h" | 7 | #include "shader_recompiler/frontend/ir/value.h" |
| 8 | 8 | ||
| 9 | namespace Shader::IR { | 9 | namespace Shader::IR { |
| 10 | 10 | namespace { | |
| 11 | [[noreturn]] static void ThrowInvalidType(Type type) { | 11 | [[noreturn]] void ThrowInvalidType(Type type) { |
| 12 | throw InvalidArgument("Invalid type {}", type); | 12 | throw InvalidArgument("Invalid type {}", type); |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | Value MakeLodClampPair(IREmitter& ir, const F32& bias_lod, const F32& lod_clamp) { | ||
| 16 | if (!bias_lod.IsEmpty() && !lod_clamp.IsEmpty()) { | ||
| 17 | return ir.CompositeConstruct(bias_lod, lod_clamp); | ||
| 18 | } else if (!bias_lod.IsEmpty()) { | ||
| 19 | return bias_lod; | ||
| 20 | } else if (!lod_clamp.IsEmpty()) { | ||
| 21 | return lod_clamp; | ||
| 22 | } else { | ||
| 23 | return Value{}; | ||
| 24 | } | ||
| 25 | } | ||
| 26 | } // Anonymous namespace | ||
| 27 | |||
| 15 | U1 IREmitter::Imm1(bool value) const { | 28 | U1 IREmitter::Imm1(bool value) const { |
| 16 | return U1{Value{value}}; | 29 | return U1{Value{value}}; |
| 17 | } | 30 | } |
| @@ -261,6 +274,10 @@ U1 IREmitter::GetOverflowFromOp(const Value& op) { | |||
| 261 | return Inst<U1>(Opcode::GetOverflowFromOp, op); | 274 | return Inst<U1>(Opcode::GetOverflowFromOp, op); |
| 262 | } | 275 | } |
| 263 | 276 | ||
| 277 | U1 IREmitter::GetSparseFromOp(const Value& op) { | ||
| 278 | return Inst<U1>(Opcode::GetSparseFromOp, op); | ||
| 279 | } | ||
| 280 | |||
| 264 | F16F32F64 IREmitter::FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control) { | 281 | F16F32F64 IREmitter::FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control) { |
| 265 | if (a.Type() != a.Type()) { | 282 | if (a.Type() != a.Type()) { |
| 266 | throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); | 283 | throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); |
| @@ -1035,6 +1052,82 @@ U32U64 IREmitter::ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& v | |||
| 1035 | } | 1052 | } |
| 1036 | } | 1053 | } |
| 1037 | 1054 | ||
| 1055 | F16F32F64 IREmitter::ConvertSToF(size_t bitsize, const U32U64& value) { | ||
| 1056 | switch (bitsize) { | ||
| 1057 | case 16: | ||
| 1058 | switch (value.Type()) { | ||
| 1059 | case Type::U32: | ||
| 1060 | return Inst<F16>(Opcode::ConvertF16S32, value); | ||
| 1061 | case Type::U64: | ||
| 1062 | return Inst<F16>(Opcode::ConvertF16S64, value); | ||
| 1063 | default: | ||
| 1064 | ThrowInvalidType(value.Type()); | ||
| 1065 | } | ||
| 1066 | case 32: | ||
| 1067 | switch (value.Type()) { | ||
| 1068 | case Type::U32: | ||
| 1069 | return Inst<F32>(Opcode::ConvertF32S32, value); | ||
| 1070 | case Type::U64: | ||
| 1071 | return Inst<F32>(Opcode::ConvertF32S64, value); | ||
| 1072 | default: | ||
| 1073 | ThrowInvalidType(value.Type()); | ||
| 1074 | } | ||
| 1075 | case 64: | ||
| 1076 | switch (value.Type()) { | ||
| 1077 | case Type::U32: | ||
| 1078 | return Inst<F16>(Opcode::ConvertF64S32, value); | ||
| 1079 | case Type::U64: | ||
| 1080 | return Inst<F16>(Opcode::ConvertF64S64, value); | ||
| 1081 | default: | ||
| 1082 | ThrowInvalidType(value.Type()); | ||
| 1083 | } | ||
| 1084 | default: | ||
| 1085 | throw InvalidArgument("Invalid destination bitsize {}", bitsize); | ||
| 1086 | } | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | F16F32F64 IREmitter::ConvertUToF(size_t bitsize, const U32U64& value) { | ||
| 1090 | switch (bitsize) { | ||
| 1091 | case 16: | ||
| 1092 | switch (value.Type()) { | ||
| 1093 | case Type::U32: | ||
| 1094 | return Inst<F16>(Opcode::ConvertF16U32, value); | ||
| 1095 | case Type::U64: | ||
| 1096 | return Inst<F16>(Opcode::ConvertF16U64, value); | ||
| 1097 | default: | ||
| 1098 | ThrowInvalidType(value.Type()); | ||
| 1099 | } | ||
| 1100 | case 32: | ||
| 1101 | switch (value.Type()) { | ||
| 1102 | case Type::U32: | ||
| 1103 | return Inst<F32>(Opcode::ConvertF32U32, value); | ||
| 1104 | case Type::U64: | ||
| 1105 | return Inst<F32>(Opcode::ConvertF32U64, value); | ||
| 1106 | default: | ||
| 1107 | ThrowInvalidType(value.Type()); | ||
| 1108 | } | ||
| 1109 | case 64: | ||
| 1110 | switch (value.Type()) { | ||
| 1111 | case Type::U32: | ||
| 1112 | return Inst<F16>(Opcode::ConvertF64U32, value); | ||
| 1113 | case Type::U64: | ||
| 1114 | return Inst<F16>(Opcode::ConvertF64U64, value); | ||
| 1115 | default: | ||
| 1116 | ThrowInvalidType(value.Type()); | ||
| 1117 | } | ||
| 1118 | default: | ||
| 1119 | throw InvalidArgument("Invalid destination bitsize {}", bitsize); | ||
| 1120 | } | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | F16F32F64 IREmitter::ConvertIToF(size_t bitsize, bool is_signed, const U32U64& value) { | ||
| 1124 | if (is_signed) { | ||
| 1125 | return ConvertSToF(bitsize, value); | ||
| 1126 | } else { | ||
| 1127 | return ConvertUToF(bitsize, value); | ||
| 1128 | } | ||
| 1129 | } | ||
| 1130 | |||
| 1038 | U32U64 IREmitter::UConvert(size_t result_bitsize, const U32U64& value) { | 1131 | U32U64 IREmitter::UConvert(size_t result_bitsize, const U32U64& value) { |
| 1039 | switch (result_bitsize) { | 1132 | switch (result_bitsize) { |
| 1040 | case 32: | 1133 | case 32: |
| @@ -1107,4 +1200,40 @@ F16F32F64 IREmitter::FPConvert(size_t result_bitsize, const F16F32F64& value) { | |||
| 1107 | throw NotImplementedException("Conversion from {} to {} bits", value.Type(), result_bitsize); | 1200 | throw NotImplementedException("Conversion from {} to {} bits", value.Type(), result_bitsize); |
| 1108 | } | 1201 | } |
| 1109 | 1202 | ||
| 1203 | Value IREmitter::ImageSampleImplicitLod(const Value& handle, const Value& coords, const F32& bias, | ||
| 1204 | const Value& offset, const F32& lod_clamp, | ||
| 1205 | TextureInstInfo info) { | ||
| 1206 | const Value bias_lc{MakeLodClampPair(*this, bias, lod_clamp)}; | ||
| 1207 | const Opcode op{handle.IsImmediate() ? Opcode::BoundImageSampleImplicitLod | ||
| 1208 | : Opcode::BindlessImageSampleImplicitLod}; | ||
| 1209 | return Inst(op, Flags{info}, handle, coords, bias_lc, offset); | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | Value IREmitter::ImageSampleExplicitLod(const Value& handle, const Value& coords, const F32& lod, | ||
| 1213 | const Value& offset, const F32& lod_clamp, | ||
| 1214 | TextureInstInfo info) { | ||
| 1215 | const Value lod_lc{MakeLodClampPair(*this, lod, lod_clamp)}; | ||
| 1216 | const Opcode op{handle.IsImmediate() ? Opcode::BoundImageSampleExplicitLod | ||
| 1217 | : Opcode::BindlessImageSampleExplicitLod}; | ||
| 1218 | return Inst(op, Flags{info}, handle, coords, lod_lc, offset); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | F32 IREmitter::ImageSampleDrefImplicitLod(const Value& handle, const Value& coords, const F32& dref, | ||
| 1222 | const F32& bias, const Value& offset, | ||
| 1223 | const F32& lod_clamp, TextureInstInfo info) { | ||
| 1224 | const Value bias_lc{MakeLodClampPair(*this, bias, lod_clamp)}; | ||
| 1225 | const Opcode op{handle.IsImmediate() ? Opcode::BoundImageSampleDrefImplicitLod | ||
| 1226 | : Opcode::BindlessImageSampleDrefImplicitLod}; | ||
| 1227 | return Inst<F32>(op, Flags{info}, handle, coords, dref, bias_lc, offset); | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | F32 IREmitter::ImageSampleDrefExplicitLod(const Value& handle, const Value& coords, const F32& dref, | ||
| 1231 | const F32& lod, const Value& offset, const F32& lod_clamp, | ||
| 1232 | TextureInstInfo info) { | ||
| 1233 | const Value lod_lc{MakeLodClampPair(*this, lod, lod_clamp)}; | ||
| 1234 | const Opcode op{handle.IsImmediate() ? Opcode::BoundImageSampleDrefExplicitLod | ||
| 1235 | : Opcode::BindlessImageSampleDrefExplicitLod}; | ||
| 1236 | return Inst<F32>(op, Flags{info}, handle, coords, dref, lod_lc, offset); | ||
| 1237 | } | ||
| 1238 | |||
| 1110 | } // namespace Shader::IR | 1239 | } // namespace Shader::IR |