emit_glsl_floating_point.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <string_view>
  5. #include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
  6. #include "shader_recompiler/backend/glsl/glsl_emit_context.h"
  7. #include "shader_recompiler/frontend/ir/modifiers.h"
  8. #include "shader_recompiler/frontend/ir/value.h"
  9. namespace Shader::Backend::GLSL {
  10. namespace {
  11. void Compare(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string_view rhs,
  12. std::string_view op, bool ordered) {
  13. const auto nan_op{ordered ? "&&!" : "||"};
  14. ctx.AddU1("{}={}{}{}"
  15. "{}isnan({}){}isnan({});",
  16. inst, lhs, op, rhs, nan_op, lhs, nan_op, rhs);
  17. }
  18. bool IsPrecise(const IR::Inst& inst) {
  19. return inst.Flags<IR::FpControl>().no_contraction;
  20. }
  21. } // Anonymous namespace
  22. void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  23. [[maybe_unused]] std::string_view value) {
  24. NotImplemented();
  25. }
  26. void EmitFPAbs32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  27. ctx.AddF32("{}=abs({});", inst, value);
  28. }
  29. void EmitFPAbs64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  30. ctx.AddF64("{}=abs({});", inst, value);
  31. }
  32. void EmitFPAdd16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  33. [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) {
  34. NotImplemented();
  35. }
  36. void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
  37. if (IsPrecise(inst)) {
  38. ctx.AddPrecF32("{}={}+{};", inst, a, b);
  39. } else {
  40. ctx.AddF32("{}={}+{};", inst, a, b);
  41. }
  42. }
  43. void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
  44. if (IsPrecise(inst)) {
  45. ctx.AddPrecF64("{}={}+{};", inst, a, b);
  46. } else {
  47. ctx.AddF64("{}={}+{};", inst, a, b);
  48. }
  49. }
  50. void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  51. [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b,
  52. [[maybe_unused]] std::string_view c) {
  53. NotImplemented();
  54. }
  55. void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b,
  56. std::string_view c) {
  57. if (IsPrecise(inst)) {
  58. ctx.AddPrecF32("{}=fma({},{},{});", inst, a, b, c);
  59. } else {
  60. ctx.AddF32("{}=fma({},{},{});", inst, a, b, c);
  61. }
  62. }
  63. void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b,
  64. std::string_view c) {
  65. if (IsPrecise(inst)) {
  66. ctx.AddPrecF64("{}=fma({},{},{});", inst, a, b, c);
  67. } else {
  68. ctx.AddF64("{}=fma({},{},{});", inst, a, b, c);
  69. }
  70. }
  71. void EmitFPMax32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
  72. ctx.AddF32("{}=max({},{});", inst, a, b);
  73. }
  74. void EmitFPMax64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
  75. ctx.AddF64("{}=max({},{});", inst, a, b);
  76. }
  77. void EmitFPMin32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
  78. ctx.AddF32("{}=min({},{});", inst, a, b);
  79. }
  80. void EmitFPMin64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
  81. ctx.AddF64("{}=min({},{});", inst, a, b);
  82. }
  83. void EmitFPMul16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  84. [[maybe_unused]] std::string_view a, [[maybe_unused]] std::string_view b) {
  85. NotImplemented();
  86. }
  87. void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
  88. if (IsPrecise(inst)) {
  89. ctx.AddPrecF32("{}={}*{};", inst, a, b);
  90. } else {
  91. ctx.AddF32("{}={}*{};", inst, a, b);
  92. }
  93. }
  94. void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
  95. if (IsPrecise(inst)) {
  96. ctx.AddPrecF64("{}={}*{};", inst, a, b);
  97. } else {
  98. ctx.AddF64("{}={}*{};", inst, a, b);
  99. }
  100. }
  101. void EmitFPNeg16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  102. [[maybe_unused]] std::string_view value) {
  103. NotImplemented();
  104. }
  105. void EmitFPNeg32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  106. ctx.AddF32("{}=0.f-({});", inst, value);
  107. }
  108. void EmitFPNeg64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  109. ctx.AddF64("{}=double(0.)-({});", inst, value);
  110. }
  111. void EmitFPSin(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  112. ctx.AddF32("{}=sin({});", inst, value);
  113. }
  114. void EmitFPCos(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  115. ctx.AddF32("{}=cos({});", inst, value);
  116. }
  117. void EmitFPExp2(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  118. ctx.AddF32("{}=exp2({});", inst, value);
  119. }
  120. void EmitFPLog2(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  121. ctx.AddF32("{}=log2({});", inst, value);
  122. }
  123. void EmitFPRecip32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  124. ctx.AddF32("{}=(1.0f)/{};", inst, value);
  125. }
  126. void EmitFPRecip64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  127. ctx.AddF64("{}=1.0/{};", inst, value);
  128. }
  129. void EmitFPRecipSqrt32([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  130. [[maybe_unused]] std::string_view value) {
  131. ctx.AddF32("{}=inversesqrt({});", inst, value);
  132. }
  133. void EmitFPRecipSqrt64([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  134. [[maybe_unused]] std::string_view value) {
  135. NotImplemented();
  136. }
  137. void EmitFPSqrt(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  138. ctx.AddF32("{}=sqrt({});", inst, value);
  139. }
  140. void EmitFPSaturate16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  141. [[maybe_unused]] std::string_view value) {
  142. NotImplemented();
  143. }
  144. void EmitFPSaturate32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  145. ctx.AddF32("{}=min(max({},0.0),1.0);", inst, value);
  146. }
  147. void EmitFPSaturate64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  148. ctx.AddF64("{}=min(max({},0.0),1.0);", inst, value);
  149. }
  150. void EmitFPClamp16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  151. [[maybe_unused]] std::string_view value,
  152. [[maybe_unused]] std::string_view min_value,
  153. [[maybe_unused]] std::string_view max_value) {
  154. NotImplemented();
  155. }
  156. void EmitFPClamp32(EmitContext& ctx, IR::Inst& inst, std::string_view value,
  157. std::string_view min_value, std::string_view max_value) {
  158. // GLSL's clamp does not produce desirable results
  159. ctx.AddF32("{}=min(max({},float({})),float({}));", inst, value, min_value, max_value);
  160. }
  161. void EmitFPClamp64(EmitContext& ctx, IR::Inst& inst, std::string_view value,
  162. std::string_view min_value, std::string_view max_value) {
  163. // GLSL's clamp does not produce desirable results
  164. ctx.AddF64("{}=min(max({},double({})),double({}));", inst, value, min_value, max_value);
  165. }
  166. void EmitFPRoundEven16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  167. [[maybe_unused]] std::string_view value) {
  168. NotImplemented();
  169. }
  170. void EmitFPRoundEven32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  171. ctx.AddF32("{}=roundEven({});", inst, value);
  172. }
  173. void EmitFPRoundEven64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  174. ctx.AddF64("{}=roundEven({});", inst, value);
  175. }
  176. void EmitFPFloor16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  177. [[maybe_unused]] std::string_view value) {
  178. NotImplemented();
  179. }
  180. void EmitFPFloor32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  181. ctx.AddF32("{}=floor({});", inst, value);
  182. }
  183. void EmitFPFloor64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  184. ctx.AddF64("{}=floor({});", inst, value);
  185. }
  186. void EmitFPCeil16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  187. [[maybe_unused]] std::string_view value) {
  188. NotImplemented();
  189. }
  190. void EmitFPCeil32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  191. ctx.AddF32("{}=ceil({});", inst, value);
  192. }
  193. void EmitFPCeil64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  194. ctx.AddF64("{}=ceil({});", inst, value);
  195. }
  196. void EmitFPTrunc16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  197. [[maybe_unused]] std::string_view value) {
  198. NotImplemented();
  199. }
  200. void EmitFPTrunc32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  201. ctx.AddF32("{}=trunc({});", inst, value);
  202. }
  203. void EmitFPTrunc64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  204. ctx.AddF64("{}=trunc({});", inst, value);
  205. }
  206. void EmitFPOrdEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs,
  207. [[maybe_unused]] std::string_view rhs) {
  208. NotImplemented();
  209. }
  210. void EmitFPOrdEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  211. std::string_view rhs) {
  212. Compare(ctx, inst, lhs, rhs, "==", true);
  213. }
  214. void EmitFPOrdEqual64(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  215. std::string_view rhs) {
  216. Compare(ctx, inst, lhs, rhs, "==", true);
  217. }
  218. void EmitFPUnordEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs,
  219. [[maybe_unused]] std::string_view rhs) {
  220. NotImplemented();
  221. }
  222. void EmitFPUnordEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  223. std::string_view rhs) {
  224. Compare(ctx, inst, lhs, rhs, "==", false);
  225. }
  226. void EmitFPUnordEqual64(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  227. std::string_view rhs) {
  228. Compare(ctx, inst, lhs, rhs, "==", false);
  229. }
  230. void EmitFPOrdNotEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs,
  231. [[maybe_unused]] std::string_view rhs) {
  232. NotImplemented();
  233. }
  234. void EmitFPOrdNotEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  235. std::string_view rhs) {
  236. Compare(ctx, inst, lhs, rhs, "!=", true);
  237. }
  238. void EmitFPOrdNotEqual64(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  239. std::string_view rhs) {
  240. Compare(ctx, inst, lhs, rhs, "!=", true);
  241. }
  242. void EmitFPUnordNotEqual16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs,
  243. [[maybe_unused]] std::string_view rhs) {
  244. NotImplemented();
  245. }
  246. void EmitFPUnordNotEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  247. std::string_view rhs) {
  248. Compare(ctx, inst, lhs, rhs, "!=", false);
  249. }
  250. void EmitFPUnordNotEqual64(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  251. std::string_view rhs) {
  252. Compare(ctx, inst, lhs, rhs, "!=", false);
  253. }
  254. void EmitFPOrdLessThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs,
  255. [[maybe_unused]] std::string_view rhs) {
  256. NotImplemented();
  257. }
  258. void EmitFPOrdLessThan32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  259. std::string_view rhs) {
  260. Compare(ctx, inst, lhs, rhs, "<", true);
  261. }
  262. void EmitFPOrdLessThan64(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  263. std::string_view rhs) {
  264. Compare(ctx, inst, lhs, rhs, "<", true);
  265. }
  266. void EmitFPUnordLessThan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] std::string_view lhs,
  267. [[maybe_unused]] std::string_view rhs) {
  268. NotImplemented();
  269. }
  270. void EmitFPUnordLessThan32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  271. std::string_view rhs) {
  272. Compare(ctx, inst, lhs, rhs, "<", false);
  273. }
  274. void EmitFPUnordLessThan64(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  275. std::string_view rhs) {
  276. Compare(ctx, inst, lhs, rhs, "<", false);
  277. }
  278. void EmitFPOrdGreaterThan16([[maybe_unused]] EmitContext& ctx,
  279. [[maybe_unused]] std::string_view lhs,
  280. [[maybe_unused]] std::string_view rhs) {
  281. NotImplemented();
  282. }
  283. void EmitFPOrdGreaterThan32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  284. std::string_view rhs) {
  285. Compare(ctx, inst, lhs, rhs, ">", true);
  286. }
  287. void EmitFPOrdGreaterThan64(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  288. std::string_view rhs) {
  289. Compare(ctx, inst, lhs, rhs, ">", true);
  290. }
  291. void EmitFPUnordGreaterThan16([[maybe_unused]] EmitContext& ctx,
  292. [[maybe_unused]] std::string_view lhs,
  293. [[maybe_unused]] std::string_view rhs) {
  294. NotImplemented();
  295. }
  296. void EmitFPUnordGreaterThan32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  297. std::string_view rhs) {
  298. Compare(ctx, inst, lhs, rhs, ">", false);
  299. }
  300. void EmitFPUnordGreaterThan64(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  301. std::string_view rhs) {
  302. Compare(ctx, inst, lhs, rhs, ">", false);
  303. }
  304. void EmitFPOrdLessThanEqual16([[maybe_unused]] EmitContext& ctx,
  305. [[maybe_unused]] std::string_view lhs,
  306. [[maybe_unused]] std::string_view rhs) {
  307. NotImplemented();
  308. }
  309. void EmitFPOrdLessThanEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  310. std::string_view rhs) {
  311. Compare(ctx, inst, lhs, rhs, "<=", true);
  312. }
  313. void EmitFPOrdLessThanEqual64(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  314. std::string_view rhs) {
  315. Compare(ctx, inst, lhs, rhs, "<=", true);
  316. }
  317. void EmitFPUnordLessThanEqual16([[maybe_unused]] EmitContext& ctx,
  318. [[maybe_unused]] std::string_view lhs,
  319. [[maybe_unused]] std::string_view rhs) {
  320. NotImplemented();
  321. }
  322. void EmitFPUnordLessThanEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  323. std::string_view rhs) {
  324. Compare(ctx, inst, lhs, rhs, "<=", false);
  325. }
  326. void EmitFPUnordLessThanEqual64(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  327. std::string_view rhs) {
  328. Compare(ctx, inst, lhs, rhs, "<=", false);
  329. }
  330. void EmitFPOrdGreaterThanEqual16([[maybe_unused]] EmitContext& ctx,
  331. [[maybe_unused]] std::string_view lhs,
  332. [[maybe_unused]] std::string_view rhs) {
  333. NotImplemented();
  334. }
  335. void EmitFPOrdGreaterThanEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  336. std::string_view rhs) {
  337. Compare(ctx, inst, lhs, rhs, ">=", true);
  338. }
  339. void EmitFPOrdGreaterThanEqual64(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  340. std::string_view rhs) {
  341. Compare(ctx, inst, lhs, rhs, ">=", true);
  342. }
  343. void EmitFPUnordGreaterThanEqual16([[maybe_unused]] EmitContext& ctx,
  344. [[maybe_unused]] std::string_view lhs,
  345. [[maybe_unused]] std::string_view rhs) {
  346. NotImplemented();
  347. }
  348. void EmitFPUnordGreaterThanEqual32(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  349. std::string_view rhs) {
  350. Compare(ctx, inst, lhs, rhs, ">=", false);
  351. }
  352. void EmitFPUnordGreaterThanEqual64(EmitContext& ctx, IR::Inst& inst, std::string_view lhs,
  353. std::string_view rhs) {
  354. Compare(ctx, inst, lhs, rhs, ">=", false);
  355. }
  356. void EmitFPIsNan16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
  357. [[maybe_unused]] std::string_view value) {
  358. NotImplemented();
  359. }
  360. void EmitFPIsNan32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  361. ctx.AddU1("{}=isnan({});", inst, value);
  362. }
  363. void EmitFPIsNan64(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
  364. ctx.AddU1("{}=isnan({});", inst, value);
  365. }
  366. } // namespace Shader::Backend::GLSL