glsl_decompiler.cpp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393
  1. // Copyright 2018 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <string>
  5. #include <string_view>
  6. #include <variant>
  7. #include <fmt/format.h>
  8. #include "common/alignment.h"
  9. #include "common/assert.h"
  10. #include "common/common_types.h"
  11. #include "video_core/engines/maxwell_3d.h"
  12. #include "video_core/shader/glsl_decompiler.h"
  13. #include "video_core/shader/shader_ir.h"
  14. namespace OpenGL::GLShader {
  15. using Tegra::Shader::Attribute;
  16. using Tegra::Shader::Header;
  17. using Tegra::Shader::IpaInterpMode;
  18. using Tegra::Shader::IpaMode;
  19. using Tegra::Shader::IpaSampleMode;
  20. using namespace VideoCommon::Shader;
  21. using Maxwell = Tegra::Engines::Maxwell3D::Regs;
  22. using ShaderStage = Tegra::Engines::Maxwell3D::Regs::ShaderStage;
  23. using Operation = const OperationNode&;
  24. enum : u32 { POSITION_VARYING_LOCATION = 0, GENERIC_VARYING_START_LOCATION = 1 };
  25. constexpr u32 MAX_CONSTBUFFER_ELEMENTS = 65536 / 16; // TODO(Rodrigo): Use rasterizer's value
  26. enum class Type { Bool, Float, Int, Uint, HalfFloat };
  27. class ShaderWriter {
  28. public:
  29. void AddExpression(std::string_view text) {
  30. DEBUG_ASSERT(scope >= 0);
  31. if (!text.empty()) {
  32. AppendIndentation();
  33. }
  34. shader_source += text;
  35. }
  36. void AddLine(std::string_view text) {
  37. AddExpression(text);
  38. AddNewLine();
  39. }
  40. void AddLine(char character) {
  41. DEBUG_ASSERT(scope >= 0);
  42. AppendIndentation();
  43. shader_source += character;
  44. AddNewLine();
  45. }
  46. void AddNewLine() {
  47. DEBUG_ASSERT(scope >= 0);
  48. shader_source += '\n';
  49. }
  50. std::string GenerateTemporal() {
  51. std::string temporal = "tmp";
  52. temporal += std::to_string(temporal_index++);
  53. return temporal;
  54. }
  55. std::string GetResult() {
  56. return std::move(shader_source);
  57. }
  58. s32 scope = 0;
  59. private:
  60. void AppendIndentation() {
  61. shader_source.append(static_cast<std::size_t>(scope) * 4, ' ');
  62. }
  63. std::string shader_source;
  64. u32 temporal_index = 1;
  65. };
  66. /// Generates code to use for a swizzle operation.
  67. static std::string GetSwizzle(u32 elem) {
  68. ASSERT(elem <= 3);
  69. std::string swizzle = ".";
  70. swizzle += "xyzw"[elem];
  71. return swizzle;
  72. }
  73. static bool IsPrecise(Operation operand) {
  74. const auto& meta = operand.GetMeta();
  75. if (std::holds_alternative<MetaArithmetic>(meta)) {
  76. return std::get<MetaArithmetic>(meta).precise;
  77. }
  78. if (std::holds_alternative<MetaHalfArithmetic>(meta)) {
  79. return std::get<MetaHalfArithmetic>(meta).precise;
  80. }
  81. return false;
  82. }
  83. static bool IsPrecise(Node node) {
  84. if (!std::holds_alternative<OperationNode>(*node)) {
  85. return false;
  86. }
  87. return IsPrecise(std::get<OperationNode>(*node));
  88. }
  89. class GLSLDecompiler final {
  90. public:
  91. explicit GLSLDecompiler(const ShaderIR& ir, ShaderStage stage, std::string suffix)
  92. : ir{ir}, stage{stage}, suffix{suffix}, header{ir.GetHeader()} {}
  93. void Decompile() {
  94. DeclareVertex();
  95. DeclareRegisters();
  96. DeclarePredicates();
  97. DeclareLocalMemory();
  98. DeclareInternalFlags();
  99. DeclareInputAttributes();
  100. DeclareOutputAttributes();
  101. DeclareConstantBuffers();
  102. DeclareSamplers();
  103. code.AddLine("void execute_" + suffix + "() {");
  104. ++code.scope;
  105. // VM's program counter
  106. const auto first_address = ir.GetBasicBlocks().begin()->first;
  107. code.AddLine("uint jmp_to = " + std::to_string(first_address) + "u;");
  108. // TODO(Subv): Figure out the actual depth of the flow stack, for now it seems
  109. // unlikely that shaders will use 20 nested SSYs and PBKs.
  110. constexpr u32 FLOW_STACK_SIZE = 20;
  111. code.AddLine(fmt::format("uint flow_stack[{}];", FLOW_STACK_SIZE));
  112. code.AddLine("uint flow_stack_top = 0u;");
  113. code.AddLine("while (true) {");
  114. ++code.scope;
  115. code.AddLine("switch (jmp_to) {");
  116. for (const auto& pair : ir.GetBasicBlocks()) {
  117. const auto [address, bb] = pair;
  118. code.AddLine(fmt::format("case 0x{:x}u: {{", address));
  119. ++code.scope;
  120. VisitBasicBlock(bb);
  121. --code.scope;
  122. code.AddLine('}');
  123. }
  124. code.AddLine("default: return;");
  125. code.AddLine('}');
  126. for (std::size_t i = 0; i < 2; ++i) {
  127. --code.scope;
  128. code.AddLine('}');
  129. }
  130. }
  131. std::string GetResult() {
  132. return code.GetResult();
  133. }
  134. ShaderEntries GetShaderEntries() const {
  135. ShaderEntries entries;
  136. for (const auto& cbuf : ir.GetConstantBuffers()) {
  137. ConstBufferEntry desc(cbuf.second, stage, GetConstBufferBlock(cbuf.first), cbuf.first);
  138. entries.const_buffers.push_back(desc);
  139. }
  140. for (const auto& sampler : ir.GetSamplers()) {
  141. SamplerEntry desc(sampler, stage, GetSampler(sampler));
  142. entries.samplers.push_back(desc);
  143. }
  144. entries.clip_distances = ir.GetClipDistances();
  145. entries.shader_length = ir.GetLength();
  146. return entries;
  147. }
  148. private:
  149. using OperationDecompilerFn = std::string (GLSLDecompiler::*)(Operation);
  150. using OperationDecompilersArray =
  151. std::array<OperationDecompilerFn, static_cast<std::size_t>(OperationCode::Amount)>;
  152. void DeclareVertex() {
  153. if (stage != ShaderStage::Vertex)
  154. return;
  155. bool clip_distances_declared = false;
  156. code.AddLine("out gl_PerVertex {");
  157. ++code.scope;
  158. code.AddLine("vec4 gl_Position;");
  159. for (const auto o : ir.GetOutputAttributes()) {
  160. if (o == Attribute::Index::PointSize)
  161. code.AddLine("float gl_PointSize;");
  162. if (!clip_distances_declared && (o == Attribute::Index::ClipDistances0123 ||
  163. o == Attribute::Index::ClipDistances4567)) {
  164. code.AddLine("float gl_ClipDistance[];");
  165. clip_distances_declared = true;
  166. }
  167. }
  168. --code.scope;
  169. code.AddLine("};");
  170. code.AddNewLine();
  171. }
  172. void DeclareRegisters() {
  173. const auto& registers = ir.GetRegisters();
  174. for (const u32 gpr : registers) {
  175. code.AddLine("float " + GetRegister(gpr) + " = 0;");
  176. }
  177. if (!registers.empty())
  178. code.AddNewLine();
  179. }
  180. void DeclarePredicates() {
  181. const auto& predicates = ir.GetPredicates();
  182. for (const auto pred : predicates) {
  183. code.AddLine("bool " + GetPredicate(pred) + " = false;");
  184. }
  185. if (!predicates.empty())
  186. code.AddNewLine();
  187. }
  188. void DeclareLocalMemory() {
  189. if (const u64 local_memory_size = header.GetLocalMemorySize(); local_memory_size > 0) {
  190. const auto element_count = Common::AlignUp(local_memory_size, 4) / 4;
  191. code.AddLine("float " + GetLocalMemory() + '[' + std::to_string(element_count) + "];");
  192. code.AddNewLine();
  193. }
  194. }
  195. void DeclareInternalFlags() {
  196. for (u32 flag = 0; flag < static_cast<u32>(InternalFlag::Amount); flag++) {
  197. const InternalFlag flag_code = static_cast<InternalFlag>(flag);
  198. code.AddLine("bool " + GetInternalFlag(flag_code) + " = false;");
  199. }
  200. code.AddNewLine();
  201. }
  202. std::string GetInputFlags(const IpaMode& input_mode) {
  203. const IpaSampleMode sample_mode = input_mode.sampling_mode;
  204. const IpaInterpMode interp_mode = input_mode.interpolation_mode;
  205. std::string out;
  206. switch (interp_mode) {
  207. case IpaInterpMode::Flat:
  208. out += "flat ";
  209. break;
  210. case IpaInterpMode::Linear:
  211. out += "noperspective ";
  212. break;
  213. case IpaInterpMode::Perspective:
  214. // Default, Smooth
  215. break;
  216. default:
  217. UNIMPLEMENTED_MSG("Unhandled IPA interp mode: {}", static_cast<u32>(interp_mode));
  218. }
  219. switch (sample_mode) {
  220. case IpaSampleMode::Centroid:
  221. // It can be implemented with the "centroid " keyword in GLSL
  222. UNIMPLEMENTED_MSG("Unimplemented IPA sampler mode centroid");
  223. break;
  224. case IpaSampleMode::Default:
  225. // Default, n/a
  226. break;
  227. default:
  228. UNIMPLEMENTED_MSG("Unimplemented IPA sampler mode: {}", static_cast<u32>(sample_mode));
  229. }
  230. return out;
  231. }
  232. void DeclareInputAttributes() {
  233. const auto& attributes = ir.GetInputAttributes();
  234. for (const auto element : attributes) {
  235. const Attribute::Index index = element.first;
  236. const IpaMode& input_mode = *element.second.begin();
  237. if (index < Attribute::Index::Attribute_0 || index > Attribute::Index::Attribute_31) {
  238. // Skip when it's not a generic attribute
  239. continue;
  240. }
  241. ASSERT(element.second.size() > 0);
  242. // UNIMPLEMENTED_IF_MSG(element.second.size() > 1,
  243. // "Multiple input flag modes are not supported in GLSL");
  244. // TODO(bunnei): Use proper number of elements for these
  245. u32 idx = static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0);
  246. if (stage != ShaderStage::Vertex) {
  247. // If inputs are varyings, add an offset
  248. idx += GENERIC_VARYING_START_LOCATION;
  249. }
  250. std::string attr = GetInputAttribute(index);
  251. if (stage == ShaderStage::Geometry) {
  252. attr = "gs_" + attr + "[]";
  253. }
  254. code.AddLine("layout (location = " + std::to_string(idx) + ") " +
  255. GetInputFlags(input_mode) + "in vec4 " + attr + ';');
  256. }
  257. if (!attributes.empty())
  258. code.AddNewLine();
  259. }
  260. void DeclareOutputAttributes() {
  261. const auto& attributes = ir.GetOutputAttributes();
  262. for (const auto index : attributes) {
  263. if (index < Attribute::Index::Attribute_0 || index > Attribute::Index::Attribute_31) {
  264. // Skip when it's not a generic attribute
  265. continue;
  266. }
  267. // TODO(bunnei): Use proper number of elements for these
  268. const auto idx = static_cast<u32>(index) -
  269. static_cast<u32>(Attribute::Index::Attribute_0) +
  270. GENERIC_VARYING_START_LOCATION;
  271. code.AddLine("layout (location = " + std::to_string(idx) + ") out vec4 " +
  272. GetOutputAttribute(index) + ';');
  273. }
  274. if (!attributes.empty())
  275. code.AddNewLine();
  276. }
  277. void DeclareConstantBuffers() {
  278. for (const auto& entry : ir.GetConstantBuffers()) {
  279. const auto [index, size] = entry;
  280. code.AddLine("layout (std140) uniform " + GetConstBufferBlock(index) + " {");
  281. code.AddLine(" vec4 " + GetConstBuffer(index) + "[MAX_CONSTBUFFER_ELEMENTS];");
  282. code.AddLine("};");
  283. code.AddNewLine();
  284. }
  285. }
  286. void DeclareSamplers() {
  287. const auto& samplers = ir.GetSamplers();
  288. for (const auto& sampler : samplers) {
  289. std::string sampler_type = [&]() {
  290. switch (sampler.GetType()) {
  291. case Tegra::Shader::TextureType::Texture1D:
  292. return "sampler1D";
  293. case Tegra::Shader::TextureType::Texture2D:
  294. return "sampler2D";
  295. case Tegra::Shader::TextureType::Texture3D:
  296. return "sampler3D";
  297. case Tegra::Shader::TextureType::TextureCube:
  298. return "samplerCube";
  299. default:
  300. UNREACHABLE();
  301. }
  302. }();
  303. if (sampler.IsArray())
  304. sampler_type += "Array";
  305. if (sampler.IsShadow())
  306. sampler_type += "Shadow";
  307. code.AddLine("uniform " + sampler_type + ' ' + GetSampler(sampler) + ';');
  308. }
  309. if (!samplers.empty())
  310. code.AddNewLine();
  311. }
  312. void VisitBasicBlock(const BasicBlock& bb) {
  313. for (const Node node : bb) {
  314. if (const std::string expr = Visit(node); !expr.empty()) {
  315. code.AddLine(expr);
  316. }
  317. }
  318. }
  319. std::string Visit(Node node) {
  320. if (const auto operation = std::get_if<OperationNode>(node)) {
  321. const auto operation_index = static_cast<std::size_t>(operation->GetCode());
  322. const auto decompiler = operation_decompilers[operation_index];
  323. if (decompiler == nullptr) {
  324. UNREACHABLE_MSG("Operation decompiler {} not defined", operation_index);
  325. }
  326. return (this->*decompiler)(*operation);
  327. } else if (const auto gpr = std::get_if<GprNode>(node)) {
  328. const u32 index = gpr->GetIndex();
  329. if (index == RZ) {
  330. return "0";
  331. }
  332. return GetRegister(index);
  333. } else if (const auto immediate = std::get_if<ImmediateNode>(node)) {
  334. const u32 value = immediate->GetValue();
  335. if (value < 10) {
  336. // For eyecandy avoid using hex numbers on single digits
  337. return fmt::format("utof({}u)", immediate->GetValue());
  338. }
  339. return fmt::format("utof(0x{:x}u)", immediate->GetValue());
  340. } else if (const auto predicate = std::get_if<PredicateNode>(node)) {
  341. const auto value = [&]() -> std::string {
  342. switch (const auto index = predicate->GetIndex(); index) {
  343. case Tegra::Shader::Pred::UnusedIndex:
  344. return "true";
  345. case Tegra::Shader::Pred::NeverExecute:
  346. return "false";
  347. default:
  348. return GetPredicate(index);
  349. }
  350. }();
  351. if (predicate->IsNegated()) {
  352. return "!(" + value + ')';
  353. }
  354. return value;
  355. } else if (const auto abuf = std::get_if<AbufNode>(node)) {
  356. const auto attribute = abuf->GetIndex();
  357. const auto element = abuf->GetElement();
  358. switch (attribute) {
  359. case Attribute::Index::Position:
  360. return element == 3 ? "1.0f" : "gl_FragCoord" + GetSwizzle(element);
  361. case Attribute::Index::PointCoord:
  362. switch (element) {
  363. case 0:
  364. return "gl_PointCoord.x";
  365. case 1:
  366. return "gl_PointCoord.y";
  367. case 2:
  368. case 3:
  369. return "0";
  370. }
  371. UNREACHABLE();
  372. return "0";
  373. case Attribute::Index::TessCoordInstanceIDVertexID:
  374. // TODO(Subv): Find out what the values are for the first two elements when inside a
  375. // vertex shader, and what's the value of the fourth element when inside a Tess Eval
  376. // shader.
  377. ASSERT(stage == ShaderStage::Vertex);
  378. switch (element) {
  379. case 2:
  380. // Config pack's first value is instance_id.
  381. return "uintBitsToFloat(config_pack[0])";
  382. case 3:
  383. return "uintBitsToFloat(gl_VertexID)";
  384. }
  385. UNIMPLEMENTED_MSG("Unmanaged TessCoordInstanceIDVertexID element={}", element);
  386. return "0";
  387. case Attribute::Index::FrontFacing:
  388. // TODO(Subv): Find out what the values are for the other elements.
  389. ASSERT(stage == ShaderStage::Fragment);
  390. switch (element) {
  391. case 3:
  392. return "itof(gl_FrontFacing ? -1 : 0)";
  393. }
  394. UNIMPLEMENTED_MSG("Unmanaged FrontFacing element={}", element);
  395. return "0";
  396. default:
  397. if (attribute >= Attribute::Index::Attribute_0 &&
  398. attribute <= Attribute::Index::Attribute_31) {
  399. return GetInputAttribute(attribute) + GetSwizzle(abuf->GetElement());
  400. }
  401. break;
  402. }
  403. UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute));
  404. } else if (const auto cbuf = std::get_if<CbufNode>(node)) {
  405. const Node offset = cbuf->GetOffset();
  406. if (const auto immediate = std::get_if<ImmediateNode>(offset)) {
  407. // Direct access
  408. const u32 offset_imm = immediate->GetValue();
  409. return fmt::format("{}[{}][{}]", GetConstBuffer(cbuf->GetIndex()), offset_imm / 4,
  410. offset_imm % 4);
  411. } else if (std::holds_alternative<OperationNode>(*offset)) {
  412. // Indirect access
  413. const std::string final_offset = code.GenerateTemporal();
  414. code.AddLine("uint " + final_offset + " = (ftou(" + Visit(offset) + ") / 4) & " +
  415. std::to_string(MAX_CONSTBUFFER_ELEMENTS - 1) + ';');
  416. return fmt::format("{}[{} / 4][{} % 4]", GetConstBuffer(cbuf->GetIndex()),
  417. final_offset, final_offset);
  418. } else {
  419. UNREACHABLE_MSG("Unmanaged offset node type");
  420. }
  421. } else if (const auto lmem = std::get_if<LmemNode>(node)) {
  422. return fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress()));
  423. } else if (const auto internal_flag = std::get_if<InternalFlagNode>(node)) {
  424. return GetInternalFlag(internal_flag->GetFlag());
  425. } else if (const auto conditional = std::get_if<ConditionalNode>(node)) {
  426. // It's invalid to call conditional on nested nodes, use an operation instead
  427. code.AddLine("if (" + Visit(conditional->GetCondition()) + ") {");
  428. ++code.scope;
  429. VisitBasicBlock(conditional->GetCode());
  430. --code.scope;
  431. code.AddLine('}');
  432. return {};
  433. } else if (const auto comment = std::get_if<CommentNode>(node)) {
  434. return "// " + comment->GetText();
  435. }
  436. UNREACHABLE();
  437. }
  438. std::string ApplyPrecise(Operation operation, const std::string& value) {
  439. if (!IsPrecise(operation)) {
  440. return value;
  441. }
  442. // There's a bug in NVidia's proprietary drivers that makes precise fail on fragment shaders
  443. const std::string precise = stage != ShaderStage::Fragment ? "precise " : "";
  444. const std::string temporal = code.GenerateTemporal();
  445. code.AddLine(precise + "float " + temporal + " = " + value + ';');
  446. return temporal;
  447. }
  448. std::string VisitOperand(Operation operation, std::size_t operand_index) {
  449. const auto& operand = operation[operand_index];
  450. const bool parent_precise = IsPrecise(operation);
  451. const bool child_precise = IsPrecise(operand);
  452. const bool child_trivial = !std::holds_alternative<OperationNode>(*operand);
  453. if (!parent_precise || child_precise || child_trivial) {
  454. return Visit(operand);
  455. }
  456. const std::string temporal = code.GenerateTemporal();
  457. code.AddLine("float " + temporal + " = " + Visit(operand) + ';');
  458. return temporal;
  459. }
  460. std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) {
  461. std::string value = VisitOperand(operation, operand_index);
  462. switch (type) {
  463. case Type::Bool:
  464. case Type::Float:
  465. return value;
  466. case Type::Int:
  467. return "ftoi(" + value + ')';
  468. case Type::Uint:
  469. return "ftou(" + value + ')';
  470. case Type::HalfFloat:
  471. if (!std::holds_alternative<MetaHalfArithmetic>(operation.GetMeta())) {
  472. value = "toHalf2(" + value + ')';
  473. }
  474. const auto& half_meta = std::get<MetaHalfArithmetic>(operation.GetMeta());
  475. switch (half_meta.types.at(operand_index)) {
  476. case Tegra::Shader::HalfType::H0_H1:
  477. return "toHalf2(" + value + ')';
  478. case Tegra::Shader::HalfType::F32:
  479. return "vec2(" + value + ')';
  480. case Tegra::Shader::HalfType::H0_H0:
  481. return "vec2(toHalf2(" + value + ")[0])";
  482. case Tegra::Shader::HalfType::H1_H1:
  483. return "vec2(toHalf2(" + value + ")[1])";
  484. }
  485. }
  486. UNREACHABLE();
  487. }
  488. std::string BitwiseCastResult(std::string value, Type type, bool needs_parenthesis = false) {
  489. switch (type) {
  490. case Type::Bool:
  491. case Type::Float:
  492. if (needs_parenthesis) {
  493. return '(' + value + ')';
  494. }
  495. return value;
  496. case Type::Int:
  497. return "itof(" + value + ')';
  498. case Type::Uint:
  499. return "utof(" + value + ')';
  500. case Type::HalfFloat:
  501. return "fromHalf2(" + value + ')';
  502. }
  503. UNREACHABLE();
  504. }
  505. std::string GenerateUnary(Operation operation, const std::string& func, Type result_type,
  506. Type type_a, bool needs_parenthesis = true) {
  507. return ApplyPrecise(operation,
  508. BitwiseCastResult(func + '(' + VisitOperand(operation, 0, type_a) + ')',
  509. result_type, needs_parenthesis));
  510. }
  511. std::string GenerateBinaryInfix(Operation operation, const std::string& func, Type result_type,
  512. Type type_a, Type type_b) {
  513. const std::string op_a = VisitOperand(operation, 0, type_a);
  514. const std::string op_b = VisitOperand(operation, 1, type_b);
  515. return ApplyPrecise(
  516. operation, BitwiseCastResult('(' + op_a + ' ' + func + ' ' + op_b + ')', result_type));
  517. }
  518. std::string GenerateBinaryCall(Operation operation, const std::string& func, Type result_type,
  519. Type type_a, Type type_b) {
  520. const std::string op_a = VisitOperand(operation, 0, type_a);
  521. const std::string op_b = VisitOperand(operation, 1, type_b);
  522. return ApplyPrecise(operation,
  523. BitwiseCastResult(func + '(' + op_a + ", " + op_b + ')', result_type));
  524. }
  525. std::string GenerateTernary(Operation operation, const std::string& func, Type result_type,
  526. Type type_a, Type type_b, Type type_c) {
  527. const std::string op_a = VisitOperand(operation, 0, type_a);
  528. const std::string op_b = VisitOperand(operation, 1, type_b);
  529. const std::string op_c = VisitOperand(operation, 2, type_c);
  530. return ApplyPrecise(
  531. operation,
  532. BitwiseCastResult(func + '(' + op_a + ", " + op_b + ", " + op_c + ')', result_type));
  533. }
  534. std::string GenerateQuaternary(Operation operation, const std::string& func, Type result_type,
  535. Type type_a, Type type_b, Type type_c, Type type_d) {
  536. const std::string op_a = VisitOperand(operation, 0, type_a);
  537. const std::string op_b = VisitOperand(operation, 1, type_b);
  538. const std::string op_c = VisitOperand(operation, 2, type_c);
  539. const std::string op_d = VisitOperand(operation, 3, type_d);
  540. return ApplyPrecise(operation, BitwiseCastResult(func + '(' + op_a + ", " + op_b + ", " +
  541. op_c + ", " + op_d + ')',
  542. result_type));
  543. }
  544. std::string GenerateTexture(Operation operation, const std::string& func,
  545. const std::string& extra_cast = "") {
  546. constexpr std::array<const char*, 4> coord_constructors = {"float", "vec2", "vec3", "vec4"};
  547. const auto& meta = std::get<MetaTexture>(operation.GetMeta());
  548. const auto count = static_cast<u32>(operation.GetOperandsCount());
  549. std::string expr = func;
  550. expr += '(';
  551. expr += GetSampler(meta.sampler);
  552. expr += ", ";
  553. expr += coord_constructors[meta.coords_count - 1];
  554. expr += '(';
  555. for (u32 i = 0; i < count; ++i) {
  556. const bool is_extra = i >= meta.coords_count;
  557. const bool do_cast = is_extra && !extra_cast.empty();
  558. if (do_cast) {
  559. expr += extra_cast;
  560. expr += '(';
  561. }
  562. expr += Visit(operation[i]);
  563. if (do_cast) {
  564. expr += ')';
  565. }
  566. if (i + 1 == meta.coords_count) {
  567. expr += ')';
  568. }
  569. if (i + 1 < count) {
  570. expr += ", ";
  571. }
  572. }
  573. expr += ')';
  574. return expr;
  575. }
  576. std::string Assign(Operation operation) {
  577. const Node dest = operation[0];
  578. const Node src = operation[1];
  579. std::string target;
  580. if (const auto gpr = std::get_if<GprNode>(dest)) {
  581. if (gpr->GetIndex() == RZ) {
  582. // Writing to RZ is a no op
  583. return {};
  584. }
  585. target = GetRegister(gpr->GetIndex());
  586. } else if (const auto abuf = std::get_if<AbufNode>(dest)) {
  587. target = [&]() -> std::string {
  588. switch (const auto attribute = abuf->GetIndex(); abuf->GetIndex()) {
  589. case Attribute::Index::Position:
  590. return "position" + GetSwizzle(abuf->GetElement());
  591. case Attribute::Index::PointSize:
  592. return "gl_PointSize";
  593. case Attribute::Index::ClipDistances0123:
  594. return "gl_ClipDistance[" + std::to_string(abuf->GetElement()) + ']';
  595. case Attribute::Index::ClipDistances4567:
  596. return "gl_ClipDistance[" + std::to_string(abuf->GetElement() + 4) + ']';
  597. default:
  598. if (attribute >= Attribute::Index::Attribute_0 &&
  599. attribute <= Attribute::Index::Attribute_31) {
  600. return GetOutputAttribute(attribute) + GetSwizzle(abuf->GetElement());
  601. }
  602. UNIMPLEMENTED_MSG("Unhandled output attribute: {}",
  603. static_cast<u32>(attribute));
  604. }
  605. }();
  606. } else if (const auto lmem = std::get_if<LmemNode>(dest)) {
  607. target = GetLocalMemory() + "[ftou(" + Visit(lmem->GetAddress()) + ") / 4]";
  608. } else {
  609. UNREACHABLE_MSG("Assign called without a proper target");
  610. }
  611. code.AddLine(target + " = " + Visit(src) + ';');
  612. return {};
  613. }
  614. std::string AssignComposite(Operation operation) {
  615. const auto& meta = std::get<MetaComponents>(operation.GetMeta());
  616. const std::string composite = code.GenerateTemporal();
  617. code.AddLine("vec4 " + composite + " = " + Visit(operation[0]) + ';');
  618. constexpr u32 composite_size = 4;
  619. for (u32 i = 0; i < composite_size; ++i) {
  620. const auto gpr = std::get<GprNode>(*operation[i + 1]).GetIndex();
  621. if (gpr == RZ) {
  622. continue;
  623. }
  624. code.AddLine(GetRegister(gpr) + " = " + composite +
  625. GetSwizzle(meta.GetSourceComponent(i)) + ';');
  626. }
  627. return {};
  628. }
  629. std::string Composite(Operation operation) {
  630. std::string value = "vec4(";
  631. for (std::size_t i = 0; i < 4; ++i) {
  632. value += Visit(operation[i]);
  633. if (i < 3)
  634. value += ", ";
  635. }
  636. value += ')';
  637. return value;
  638. }
  639. template <Type type>
  640. std::string Add(Operation operation) {
  641. return GenerateBinaryInfix(operation, "+", type, type, type);
  642. }
  643. template <Type type>
  644. std::string Mul(Operation operation) {
  645. return GenerateBinaryInfix(operation, "*", type, type, type);
  646. }
  647. template <Type type>
  648. std::string Div(Operation operation) {
  649. return GenerateBinaryInfix(operation, "/", type, type, type);
  650. }
  651. std::string FFma(Operation operation) {
  652. return GenerateTernary(operation, "fma", Type::Float, Type::Float, Type::Float,
  653. Type::Float);
  654. }
  655. template <Type type>
  656. std::string Negate(Operation operation) {
  657. return GenerateUnary(operation, "-", type, type, true);
  658. }
  659. template <Type type>
  660. std::string Absolute(Operation operation) {
  661. return GenerateUnary(operation, "abs", type, type, false);
  662. }
  663. std::string FClamp(Operation operation) {
  664. return GenerateTernary(operation, "clamp", Type::Float, Type::Float, Type::Float,
  665. Type::Float);
  666. }
  667. template <Type type>
  668. std::string Min(Operation operation) {
  669. return GenerateBinaryCall(operation, "min", type, type, type);
  670. }
  671. template <Type type>
  672. std::string Max(Operation operation) {
  673. return GenerateBinaryCall(operation, "max", type, type, type);
  674. }
  675. std::string Select(Operation operation) {
  676. const std::string condition = Visit(operation[0]);
  677. const std::string true_case = Visit(operation[1]);
  678. const std::string false_case = Visit(operation[2]);
  679. return ApplyPrecise(operation,
  680. '(' + condition + " ? " + true_case + " : " + false_case + ')');
  681. }
  682. std::string FCos(Operation operation) {
  683. return GenerateUnary(operation, "cos", Type::Float, Type::Float, false);
  684. }
  685. std::string FSin(Operation operation) {
  686. return GenerateUnary(operation, "sin", Type::Float, Type::Float, false);
  687. }
  688. std::string FExp2(Operation operation) {
  689. return GenerateUnary(operation, "exp2", Type::Float, Type::Float, false);
  690. }
  691. std::string FLog2(Operation operation) {
  692. return GenerateUnary(operation, "log2", Type::Float, Type::Float, false);
  693. }
  694. std::string FInverseSqrt(Operation operation) {
  695. return GenerateUnary(operation, "inversesqrt", Type::Float, Type::Float, false);
  696. }
  697. std::string FSqrt(Operation operation) {
  698. return GenerateUnary(operation, "sqrt", Type::Float, Type::Float, false);
  699. }
  700. std::string FRoundEven(Operation operation) {
  701. return GenerateUnary(operation, "roundEven", Type::Float, Type::Float, false);
  702. }
  703. std::string FFloor(Operation operation) {
  704. return GenerateUnary(operation, "floor", Type::Float, Type::Float, false);
  705. }
  706. std::string FCeil(Operation operation) {
  707. return GenerateUnary(operation, "ceil", Type::Float, Type::Float, false);
  708. }
  709. std::string FTrunc(Operation operation) {
  710. return GenerateUnary(operation, "trunc", Type::Float, Type::Float, false);
  711. }
  712. template <Type type>
  713. std::string FCastInteger(Operation operation) {
  714. return GenerateUnary(operation, "float", Type::Float, type, false);
  715. }
  716. std::string ICastFloat(Operation operation) {
  717. return GenerateUnary(operation, "int", Type::Int, Type::Float, false);
  718. }
  719. std::string ICastUnsigned(Operation operation) {
  720. return GenerateUnary(operation, "int", Type::Int, Type::Uint, false);
  721. }
  722. template <Type type>
  723. std::string LogicalShiftLeft(Operation operation) {
  724. return GenerateBinaryInfix(operation, "<<", type, type, Type::Uint);
  725. }
  726. std::string ILogicalShiftRight(Operation operation) {
  727. const std::string op_a = VisitOperand(operation, 0, Type::Uint);
  728. const std::string op_b = VisitOperand(operation, 1, Type::Uint);
  729. return ApplyPrecise(operation,
  730. BitwiseCastResult("int(" + op_a + " >> " + op_b + ')', Type::Int));
  731. }
  732. std::string IArithmeticShiftRight(Operation operation) {
  733. return GenerateBinaryInfix(operation, ">>", Type::Int, Type::Int, Type::Uint);
  734. }
  735. template <Type type>
  736. std::string BitwiseAnd(Operation operation) {
  737. return GenerateBinaryInfix(operation, "&", type, type, type);
  738. }
  739. template <Type type>
  740. std::string BitwiseOr(Operation operation) {
  741. return GenerateBinaryInfix(operation, "|", type, type, type);
  742. }
  743. template <Type type>
  744. std::string BitwiseXor(Operation operation) {
  745. return GenerateBinaryInfix(operation, "^", type, type, type);
  746. }
  747. template <Type type>
  748. std::string BitwiseNot(Operation operation) {
  749. return GenerateUnary(operation, "~", type, type, false);
  750. }
  751. std::string UCastFloat(Operation operation) {
  752. return GenerateUnary(operation, "uint", Type::Uint, Type::Float, false);
  753. }
  754. std::string UCastSigned(Operation operation) {
  755. return GenerateUnary(operation, "uint", Type::Uint, Type::Int, false);
  756. }
  757. std::string UShiftRight(Operation operation) {
  758. return GenerateBinaryInfix(operation, ">>", Type::Uint, Type::Uint, Type::Uint);
  759. }
  760. template <Type type>
  761. std::string BitfieldInsert(Operation operation) {
  762. return GenerateQuaternary(operation, "bitfieldInsert", type, type, type, Type::Int,
  763. Type::Int);
  764. }
  765. std::string HNegate(Operation operation) {
  766. const auto GetNegate = [&](std::size_t index) -> std::string {
  767. if (const auto pred = std::get_if<PredicateNode>(operation[index])) {
  768. if (!pred->IsNegated()) {
  769. switch (pred->GetIndex()) {
  770. case Tegra::Shader::Pred::UnusedIndex:
  771. return "-1";
  772. case Tegra::Shader::Pred::NeverExecute:
  773. return "1";
  774. }
  775. }
  776. }
  777. return VisitOperand(operation, index, Type::Bool) + " ? -1 : 1";
  778. };
  779. const std::string value = '(' + VisitOperand(operation, 0, Type::HalfFloat) + " * vec2(" +
  780. GetNegate(1) + ", " + GetNegate(2) + "))";
  781. return BitwiseCastResult(value, Type::HalfFloat);
  782. }
  783. std::string HMergeF32(Operation operation) {
  784. return "float(toHalf2(" + Visit(operation[0]) + ")[0])";
  785. }
  786. std::string HMergeH0(Operation operation) {
  787. return "fromHalf2(vec2(toHalf2(" + Visit(operation[0]) + ")[1], toHalf2(" +
  788. Visit(operation[1]) + ")[0]))";
  789. }
  790. std::string HMergeH1(Operation operation) {
  791. return "fromHalf2(vec2(toHalf2(" + Visit(operation[0]) + ")[0], toHalf2(" +
  792. Visit(operation[1]) + ")[1]))";
  793. }
  794. template <Type type>
  795. std::string LogicalLessThan(Operation operation) {
  796. return GenerateBinaryInfix(operation, "<", Type::Bool, type, type);
  797. }
  798. template <Type type>
  799. std::string LogicalEqual(Operation operation) {
  800. return GenerateBinaryInfix(operation, "==", Type::Bool, type, type);
  801. }
  802. template <Type type>
  803. std::string LogicalLessEqual(Operation operation) {
  804. return GenerateBinaryInfix(operation, "<=", Type::Bool, type, type);
  805. }
  806. template <Type type>
  807. std::string LogicalGreaterThan(Operation operation) {
  808. return GenerateBinaryInfix(operation, ">", Type::Bool, type, type);
  809. }
  810. template <Type type>
  811. std::string LogicalNotEqual(Operation operation) {
  812. return GenerateBinaryInfix(operation, "!=", Type::Bool, type, type);
  813. }
  814. template <Type type>
  815. std::string LogicalGreaterEqual(Operation operation) {
  816. return GenerateBinaryInfix(operation, ">=", Type::Bool, type, type);
  817. }
  818. std::string LogicalFIsNan(Operation operation) {
  819. return GenerateUnary(operation, "isnan", Type::Bool, Type::Float, false);
  820. }
  821. std::string LogicalAssign(Operation operation) {
  822. const Node dest = operation[0];
  823. const Node src = operation[1];
  824. std::string target;
  825. if (const auto pred = std::get_if<PredicateNode>(dest)) {
  826. ASSERT_MSG(!pred->IsNegated(), "Negating logical assignment");
  827. const auto index = pred->GetIndex();
  828. switch (index) {
  829. case Tegra::Shader::Pred::NeverExecute:
  830. case Tegra::Shader::Pred::UnusedIndex:
  831. // Writing to these predicates is a no-op
  832. return {};
  833. }
  834. target = GetPredicate(index);
  835. } else if (const auto flag = std::get_if<InternalFlagNode>(dest)) {
  836. target = GetInternalFlag(flag->GetFlag());
  837. }
  838. code.AddLine(target + " = " + Visit(src) + ';');
  839. return {};
  840. }
  841. std::string LogicalAnd(Operation operation) {
  842. return GenerateBinaryInfix(operation, "&&", Type::Bool, Type::Bool, Type::Bool);
  843. }
  844. std::string LogicalOr(Operation operation) {
  845. return GenerateBinaryInfix(operation, "||", Type::Bool, Type::Bool, Type::Bool);
  846. }
  847. std::string LogicalXor(Operation operation) {
  848. return GenerateBinaryInfix(operation, "^^", Type::Bool, Type::Bool, Type::Bool);
  849. }
  850. std::string LogicalNegate(Operation operation) {
  851. return GenerateUnary(operation, "!", Type::Bool, Type::Bool, false);
  852. }
  853. std::string LogicalHComparison(Operation operation, const std::string& func) {
  854. const auto& meta = std::get<MetaHalfArithmetic>(operation.GetMeta());
  855. const std::string op_a = VisitOperand(operation, 0, Type::HalfFloat);
  856. const std::string op_b = VisitOperand(operation, 1, Type::HalfFloat);
  857. std::string value = meta.and_comparison ? "all" : "any";
  858. value += '(' + func + '(' + op_a + ", " + op_b + "))";
  859. return value;
  860. }
  861. std::string LogicalHLessThan(Operation operation) {
  862. return LogicalHComparison(operation, "lessThan");
  863. }
  864. std::string LogicalHEqual(Operation operation) {
  865. return LogicalHComparison(operation, "equal");
  866. }
  867. std::string LogicalHLessEqual(Operation operation) {
  868. return LogicalHComparison(operation, "lessThanEqual");
  869. }
  870. std::string LogicalHGreaterThan(Operation operation) {
  871. return LogicalHComparison(operation, "greaterThan");
  872. }
  873. std::string LogicalHNotEqual(Operation operation) {
  874. return LogicalHComparison(operation, "notEqual");
  875. }
  876. std::string LogicalHGreaterEqual(Operation operation) {
  877. return LogicalHComparison(operation, "greaterThanEqual");
  878. }
  879. std::string F4Texture(Operation operation) {
  880. std::string expr = GenerateTexture(operation, "texture");
  881. if (std::get<MetaTexture>(operation.GetMeta()).sampler.IsShadow()) {
  882. expr = "vec4(" + expr + ')';
  883. }
  884. return expr;
  885. }
  886. std::string F4TextureLod(Operation operation) {
  887. std::string expr = GenerateTexture(operation, "textureLod");
  888. if (std::get<MetaTexture>(operation.GetMeta()).sampler.IsShadow()) {
  889. expr = "vec4(" + expr + ')';
  890. }
  891. return expr;
  892. }
  893. std::string F4TextureGather(Operation operation) {
  894. return GenerateTexture(operation, "textureGather", "int");
  895. }
  896. std::string F4TextureQueryDimensions(Operation operation) {
  897. const auto& meta = std::get<MetaTexture>(operation.GetMeta());
  898. const std::string sampler = GetSampler(meta.sampler);
  899. const std::string lod = VisitOperand(operation, 0, Type::Int);
  900. const std::string sizes = code.GenerateTemporal();
  901. code.AddLine("ivec2 " + sizes + " = textureSize(" + sampler + ", " + lod + ");");
  902. const std::string mip_level = "textureQueryLevels(" + sampler + ')';
  903. return "itof(ivec4(" + sizes + ", 0, " + mip_level + "))";
  904. }
  905. std::string F4TextureQueryLod(Operation operation) {
  906. const std::string tmp = code.GenerateTemporal();
  907. code.AddLine("vec2 " + tmp + " = " + GenerateTexture(operation, "textureQueryLod") +
  908. " * vec2(256);");
  909. return "vec4(itof(int(" + tmp + ".y)), utof(uint(" + tmp + ".x)), 0, 0)";
  910. }
  911. std::string Ipa(Operation operation) {
  912. const auto& attribute = operation[0];
  913. // TODO(Rodrigo): Special IPA attribute interactions
  914. return Visit(attribute);
  915. }
  916. std::string Bra(Operation operation) {
  917. const auto target = std::get<ImmediateNode>(*operation[0]);
  918. code.AddLine(fmt::format("jmp_to = 0x{:x}u;", target.GetValue()));
  919. code.AddLine("break;");
  920. return {};
  921. }
  922. std::string PushFlowStack(Operation operation) {
  923. const auto target = std::get<ImmediateNode>(*operation[0]);
  924. code.AddLine(fmt::format("flow_stack[flow_stack_top] = 0x{:x}u;", target.GetValue()));
  925. code.AddLine("flow_stack_top++;");
  926. return {};
  927. }
  928. std::string PopFlowStack(Operation operation) {
  929. code.AddLine("flow_stack_top--;");
  930. code.AddLine("jmp_to = flow_stack[flow_stack_top];");
  931. code.AddLine("break;");
  932. return {};
  933. }
  934. std::string Exit(Operation operation) {
  935. if (stage != ShaderStage::Fragment) {
  936. code.AddLine("return;");
  937. return {};
  938. }
  939. const auto& used_registers = ir.GetRegisters();
  940. const auto SafeGetRegister = [&](u32 reg) -> std::string {
  941. // TODO(Rodrigo): Replace with contains once C++20 releases
  942. if (used_registers.find(reg) != used_registers.end()) {
  943. return GetRegister(reg);
  944. }
  945. return "0.0f";
  946. };
  947. UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, "Sample mask write is unimplemented");
  948. code.AddLine("if (alpha_test[0] != 0) {");
  949. ++code.scope;
  950. // We start on the register containing the alpha value in the first RT.
  951. u32 current_reg = 3;
  952. for (u32 render_target = 0; render_target < Maxwell::NumRenderTargets; ++render_target) {
  953. // TODO(Blinkhawk): verify the behavior of alpha testing on hardware when
  954. // multiple render targets are used.
  955. if (header.ps.IsColorComponentOutputEnabled(render_target, 0) ||
  956. header.ps.IsColorComponentOutputEnabled(render_target, 1) ||
  957. header.ps.IsColorComponentOutputEnabled(render_target, 2) ||
  958. header.ps.IsColorComponentOutputEnabled(render_target, 3)) {
  959. code.AddLine(
  960. fmt::format("if (!AlphaFunc({})) discard;", SafeGetRegister(current_reg)));
  961. current_reg += 4;
  962. }
  963. }
  964. --code.scope;
  965. code.AddLine('}');
  966. // Write the color outputs using the data in the shader registers, disabled
  967. // rendertargets/components are skipped in the register assignment.
  968. current_reg = 0;
  969. for (u32 render_target = 0; render_target < Maxwell::NumRenderTargets; ++render_target) {
  970. // TODO(Subv): Figure out how dual-source blending is configured in the Switch.
  971. for (u32 component = 0; component < 4; ++component) {
  972. if (header.ps.IsColorComponentOutputEnabled(render_target, component)) {
  973. code.AddLine(fmt::format("FragColor{}[{}] = {};", render_target, component,
  974. SafeGetRegister(current_reg)));
  975. ++current_reg;
  976. }
  977. }
  978. }
  979. if (header.ps.omap.depth) {
  980. // The depth output is always 2 registers after the last color output, and current_reg
  981. // already contains one past the last color register.
  982. code.AddLine("gl_FragDepth = " + SafeGetRegister(current_reg + 1) + ';');
  983. }
  984. code.AddLine("return;");
  985. return {};
  986. }
  987. std::string Kil(Operation operation) {
  988. // Enclose "discard" in a conditional, so that GLSL compilation does not complain
  989. // about unexecuted instructions that may follow this.
  990. code.AddLine("if (true) {");
  991. ++code.scope;
  992. code.AddLine("discard;");
  993. --code.scope;
  994. code.AddLine("}");
  995. return {};
  996. }
  997. std::string YNegate(Operation operation) {
  998. // Config pack's third value is Y_NEGATE's state.
  999. return "uintBitsToFloat(config_pack[2])";
  1000. }
  1001. static constexpr OperationDecompilersArray operation_decompilers = {
  1002. &Assign,
  1003. &AssignComposite,
  1004. &Composite,
  1005. &Select,
  1006. &Add<Type::Float>,
  1007. &Mul<Type::Float>,
  1008. &Div<Type::Float>,
  1009. &FFma,
  1010. &Negate<Type::Float>,
  1011. &Absolute<Type::Float>,
  1012. &FClamp,
  1013. &Min<Type::Float>,
  1014. &Max<Type::Float>,
  1015. &FCos,
  1016. &FSin,
  1017. &FExp2,
  1018. &FLog2,
  1019. &FInverseSqrt,
  1020. &FSqrt,
  1021. &FRoundEven,
  1022. &FFloor,
  1023. &FCeil,
  1024. &FTrunc,
  1025. &FCastInteger<Type::Int>,
  1026. &FCastInteger<Type::Uint>,
  1027. &Add<Type::Int>,
  1028. &Mul<Type::Int>,
  1029. &Div<Type::Int>,
  1030. &Negate<Type::Int>,
  1031. &Absolute<Type::Int>,
  1032. &Min<Type::Int>,
  1033. &Max<Type::Int>,
  1034. &ICastFloat,
  1035. &ICastUnsigned,
  1036. &LogicalShiftLeft<Type::Int>,
  1037. &ILogicalShiftRight,
  1038. &IArithmeticShiftRight,
  1039. &BitwiseAnd<Type::Int>,
  1040. &BitwiseOr<Type::Int>,
  1041. &BitwiseXor<Type::Int>,
  1042. &BitwiseNot<Type::Int>,
  1043. &BitfieldInsert<Type::Int>,
  1044. &Add<Type::Uint>,
  1045. &Mul<Type::Uint>,
  1046. &Div<Type::Uint>,
  1047. &Min<Type::Uint>,
  1048. &Max<Type::Uint>,
  1049. &UCastFloat,
  1050. &UCastSigned,
  1051. &LogicalShiftLeft<Type::Uint>,
  1052. &UShiftRight,
  1053. &UShiftRight,
  1054. &BitwiseAnd<Type::Uint>,
  1055. &BitwiseOr<Type::Uint>,
  1056. &BitwiseXor<Type::Uint>,
  1057. &BitwiseNot<Type::Uint>,
  1058. &BitfieldInsert<Type::Uint>,
  1059. &Add<Type::HalfFloat>,
  1060. &Mul<Type::HalfFloat>,
  1061. &Absolute<Type::HalfFloat>,
  1062. &HNegate,
  1063. &HMergeF32,
  1064. &HMergeH0,
  1065. &HMergeH1,
  1066. &LogicalAssign,
  1067. &LogicalAnd,
  1068. &LogicalOr,
  1069. &LogicalXor,
  1070. &LogicalNegate,
  1071. &LogicalLessThan<Type::Float>,
  1072. &LogicalEqual<Type::Float>,
  1073. &LogicalLessEqual<Type::Float>,
  1074. &LogicalGreaterThan<Type::Float>,
  1075. &LogicalNotEqual<Type::Float>,
  1076. &LogicalGreaterEqual<Type::Float>,
  1077. &LogicalFIsNan,
  1078. &LogicalLessThan<Type::Int>,
  1079. &LogicalEqual<Type::Int>,
  1080. &LogicalLessEqual<Type::Int>,
  1081. &LogicalGreaterThan<Type::Int>,
  1082. &LogicalNotEqual<Type::Int>,
  1083. &LogicalGreaterEqual<Type::Int>,
  1084. &LogicalLessThan<Type::Uint>,
  1085. &LogicalEqual<Type::Uint>,
  1086. &LogicalLessEqual<Type::Uint>,
  1087. &LogicalGreaterThan<Type::Uint>,
  1088. &LogicalNotEqual<Type::Uint>,
  1089. &LogicalGreaterEqual<Type::Uint>,
  1090. &LogicalHLessThan,
  1091. &LogicalHEqual,
  1092. &LogicalHLessEqual,
  1093. &LogicalHGreaterThan,
  1094. &LogicalHNotEqual,
  1095. &LogicalHGreaterEqual,
  1096. &F4Texture,
  1097. &F4TextureLod,
  1098. &F4TextureGather,
  1099. &F4TextureQueryDimensions,
  1100. &F4TextureQueryLod,
  1101. &Ipa,
  1102. &Bra,
  1103. &PushFlowStack, // Ssy
  1104. &PushFlowStack, // Brk
  1105. &PopFlowStack, // Sync
  1106. &PopFlowStack, // Brk
  1107. &Exit,
  1108. &Kil,
  1109. &YNegate,
  1110. };
  1111. std::string GetRegister(u32 index) const {
  1112. return GetDeclarationWithSuffix(index, "gpr");
  1113. }
  1114. std::string GetPredicate(Tegra::Shader::Pred pred) const {
  1115. return GetDeclarationWithSuffix(static_cast<u32>(pred), "pred");
  1116. }
  1117. std::string GetInputAttribute(Attribute::Index attribute) const {
  1118. const auto index{static_cast<u32>(attribute) -
  1119. static_cast<u32>(Attribute::Index::Attribute_0)};
  1120. return GetDeclarationWithSuffix(index, "input_attr");
  1121. }
  1122. std::string GetOutputAttribute(Attribute::Index attribute) const {
  1123. const auto index{static_cast<u32>(attribute) -
  1124. static_cast<u32>(Attribute::Index::Attribute_0)};
  1125. return GetDeclarationWithSuffix(index, "output_attr");
  1126. }
  1127. std::string GetConstBuffer(u32 index) const {
  1128. return GetDeclarationWithSuffix(index, "cbuf");
  1129. }
  1130. std::string GetConstBufferBlock(u32 index) const {
  1131. return GetDeclarationWithSuffix(index, "cbuf_block");
  1132. }
  1133. std::string GetLocalMemory() const {
  1134. return "lmem_" + suffix;
  1135. }
  1136. std::string GetInternalFlag(InternalFlag flag) const {
  1137. constexpr std::array<const char*, 4> InternalFlagNames = {"zero_flag", "sign_flag",
  1138. "carry_flag", "overflow_flag"};
  1139. const auto index = static_cast<u32>(flag);
  1140. ASSERT(index < static_cast<u32>(InternalFlag::Amount));
  1141. return std::string(InternalFlagNames[index]) + '_' + suffix;
  1142. }
  1143. std::string GetSampler(const Sampler& sampler) const {
  1144. return GetDeclarationWithSuffix(static_cast<u32>(sampler.GetIndex()), "sampler");
  1145. }
  1146. std::string GetDeclarationWithSuffix(u32 index, const std::string& name) const {
  1147. return name + '_' + std::to_string(index) + '_' + suffix;
  1148. }
  1149. const ShaderIR& ir;
  1150. const ShaderStage stage;
  1151. const std::string suffix;
  1152. const Header header;
  1153. ShaderWriter code;
  1154. };
  1155. std::string GetCommonDeclarations() {
  1156. return "#define MAX_CONSTBUFFER_ELEMENTS " + std::to_string(MAX_CONSTBUFFER_ELEMENTS) +
  1157. "\n"
  1158. "#define ftoi floatBitsToInt\n"
  1159. "#define ftou floatBitsToUint\n"
  1160. "#define itof intBitsToFloat\n"
  1161. "#define utof uintBitsToFloat\n\n"
  1162. "float fromHalf2(vec2 pair) {\n"
  1163. " return utof(packHalf2x16(pair));\n"
  1164. "}\n\n"
  1165. "vec2 toHalf2(float value) {\n"
  1166. " return unpackHalf2x16(ftou(value));\n"
  1167. "}\n\n";
  1168. }
  1169. ProgramResult Decompile(const ShaderIR& ir, Maxwell::ShaderStage stage, const std::string& suffix) {
  1170. GLSLDecompiler decompiler(ir, stage, suffix);
  1171. decompiler.Decompile();
  1172. return {decompiler.GetResult(), decompiler.GetShaderEntries()};
  1173. }
  1174. } // namespace OpenGL::GLShader