summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/ir/ir_emitter.cpp
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-03-08 18:31:53 -0300
committerGravatar ameerj2021-07-22 21:51:23 -0400
commitab463712474de5f99eec137a9c6233e55fe184f0 (patch)
tree30d79ac64dd03d5cfafd07c0c42c2baadc82de98 /src/shader_recompiler/frontend/ir/ir_emitter.cpp
parentshader: Implement R2P (diff)
downloadyuzu-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.cpp133
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
9namespace Shader::IR { 9namespace Shader::IR {
10 10namespace {
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
15Value 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
15U1 IREmitter::Imm1(bool value) const { 28U1 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
277U1 IREmitter::GetSparseFromOp(const Value& op) {
278 return Inst<U1>(Opcode::GetSparseFromOp, op);
279}
280
264F16F32F64 IREmitter::FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control) { 281F16F32F64 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
1055F16F32F64 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
1089F16F32F64 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
1123F16F32F64 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
1038U32U64 IREmitter::UConvert(size_t result_bitsize, const U32U64& value) { 1131U32U64 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
1203Value 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
1212Value 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
1221F32 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
1230F32 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