glsl_decompiler.cpp 55 KB

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