emit_glsl_floating_point.cpp 16 KB

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