glsl_decompiler.cpp 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445
  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. 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. return "sampler2D";
  302. }
  303. }();
  304. if (sampler.IsArray())
  305. sampler_type += "Array";
  306. if (sampler.IsShadow())
  307. sampler_type += "Shadow";
  308. code.AddLine("uniform " + sampler_type + ' ' + GetSampler(sampler) + ';');
  309. }
  310. if (!samplers.empty())
  311. code.AddNewLine();
  312. }
  313. void VisitBasicBlock(const BasicBlock& bb) {
  314. for (const Node node : bb) {
  315. if (const std::string expr = Visit(node); !expr.empty()) {
  316. code.AddLine(expr);
  317. }
  318. }
  319. }
  320. std::string Visit(Node node) {
  321. if (const auto operation = std::get_if<OperationNode>(node)) {
  322. const auto operation_index = static_cast<std::size_t>(operation->GetCode());
  323. const auto decompiler = operation_decompilers[operation_index];
  324. if (decompiler == nullptr) {
  325. UNREACHABLE_MSG("Operation decompiler {} not defined", operation_index);
  326. }
  327. return (this->*decompiler)(*operation);
  328. } else if (const auto gpr = std::get_if<GprNode>(node)) {
  329. const u32 index = gpr->GetIndex();
  330. if (index == RZ) {
  331. return "0";
  332. }
  333. return GetRegister(index);
  334. } else if (const auto immediate = std::get_if<ImmediateNode>(node)) {
  335. const u32 value = immediate->GetValue();
  336. if (value < 10) {
  337. // For eyecandy avoid using hex numbers on single digits
  338. return fmt::format("utof({}u)", immediate->GetValue());
  339. }
  340. return fmt::format("utof(0x{:x}u)", immediate->GetValue());
  341. } else if (const auto predicate = std::get_if<PredicateNode>(node)) {
  342. const auto value = [&]() -> std::string {
  343. switch (const auto index = predicate->GetIndex(); index) {
  344. case Tegra::Shader::Pred::UnusedIndex:
  345. return "true";
  346. case Tegra::Shader::Pred::NeverExecute:
  347. return "false";
  348. default:
  349. return GetPredicate(index);
  350. }
  351. }();
  352. if (predicate->IsNegated()) {
  353. return "!(" + value + ')';
  354. }
  355. return value;
  356. } else if (const auto abuf = std::get_if<AbufNode>(node)) {
  357. const auto attribute = abuf->GetIndex();
  358. const auto element = abuf->GetElement();
  359. switch (attribute) {
  360. case Attribute::Index::Position:
  361. return element == 3 ? "1.0f" : "gl_FragCoord" + GetSwizzle(element);
  362. case Attribute::Index::PointCoord:
  363. switch (element) {
  364. case 0:
  365. return "gl_PointCoord.x";
  366. case 1:
  367. return "gl_PointCoord.y";
  368. case 2:
  369. case 3:
  370. return "0";
  371. }
  372. UNREACHABLE();
  373. return "0";
  374. case Attribute::Index::TessCoordInstanceIDVertexID:
  375. // TODO(Subv): Find out what the values are for the first two elements when inside a
  376. // vertex shader, and what's the value of the fourth element when inside a Tess Eval
  377. // shader.
  378. ASSERT(stage == ShaderStage::Vertex);
  379. switch (element) {
  380. case 2:
  381. // Config pack's first value is instance_id.
  382. return "uintBitsToFloat(config_pack[0])";
  383. case 3:
  384. return "uintBitsToFloat(gl_VertexID)";
  385. }
  386. UNIMPLEMENTED_MSG("Unmanaged TessCoordInstanceIDVertexID element={}", element);
  387. return "0";
  388. case Attribute::Index::FrontFacing:
  389. // TODO(Subv): Find out what the values are for the other elements.
  390. ASSERT(stage == ShaderStage::Fragment);
  391. switch (element) {
  392. case 3:
  393. return "itof(gl_FrontFacing ? -1 : 0)";
  394. }
  395. UNIMPLEMENTED_MSG("Unmanaged FrontFacing element={}", element);
  396. return "0";
  397. default:
  398. if (attribute >= Attribute::Index::Attribute_0 &&
  399. attribute <= Attribute::Index::Attribute_31) {
  400. return GetInputAttribute(attribute) + GetSwizzle(abuf->GetElement());
  401. }
  402. break;
  403. }
  404. UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute));
  405. } else if (const auto cbuf = std::get_if<CbufNode>(node)) {
  406. const Node offset = cbuf->GetOffset();
  407. if (const auto immediate = std::get_if<ImmediateNode>(offset)) {
  408. // Direct access
  409. const u32 offset_imm = immediate->GetValue();
  410. return fmt::format("{}[{}][{}]", GetConstBuffer(cbuf->GetIndex()), offset_imm / 4,
  411. offset_imm % 4);
  412. } else if (std::holds_alternative<OperationNode>(*offset)) {
  413. // Indirect access
  414. const std::string final_offset = code.GenerateTemporal();
  415. code.AddLine("uint " + final_offset + " = (ftou(" + Visit(offset) + ") / 4) & " +
  416. std::to_string(MAX_CONSTBUFFER_ELEMENTS - 1) + ';');
  417. return fmt::format("{}[{} / 4][{} % 4]", GetConstBuffer(cbuf->GetIndex()),
  418. final_offset, final_offset);
  419. } else {
  420. UNREACHABLE_MSG("Unmanaged offset node type");
  421. }
  422. } else if (const auto lmem = std::get_if<LmemNode>(node)) {
  423. return fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress()));
  424. } else if (const auto internal_flag = std::get_if<InternalFlagNode>(node)) {
  425. return GetInternalFlag(internal_flag->GetFlag());
  426. } else if (const auto conditional = std::get_if<ConditionalNode>(node)) {
  427. // It's invalid to call conditional on nested nodes, use an operation instead
  428. code.AddLine("if (" + Visit(conditional->GetCondition()) + ") {");
  429. ++code.scope;
  430. VisitBasicBlock(conditional->GetCode());
  431. --code.scope;
  432. code.AddLine('}');
  433. return {};
  434. } else if (const auto comment = std::get_if<CommentNode>(node)) {
  435. return "// " + comment->GetText();
  436. }
  437. UNREACHABLE();
  438. return {};
  439. }
  440. std::string ApplyPrecise(Operation operation, const std::string& value) {
  441. if (!IsPrecise(operation)) {
  442. return value;
  443. }
  444. // There's a bug in NVidia's proprietary drivers that makes precise fail on fragment shaders
  445. const std::string precise = stage != ShaderStage::Fragment ? "precise " : "";
  446. const std::string temporal = code.GenerateTemporal();
  447. code.AddLine(precise + "float " + temporal + " = " + value + ';');
  448. return temporal;
  449. }
  450. std::string VisitOperand(Operation operation, std::size_t operand_index) {
  451. const auto& operand = operation[operand_index];
  452. const bool parent_precise = IsPrecise(operation);
  453. const bool child_precise = IsPrecise(operand);
  454. const bool child_trivial = !std::holds_alternative<OperationNode>(*operand);
  455. if (!parent_precise || child_precise || child_trivial) {
  456. return Visit(operand);
  457. }
  458. const std::string temporal = code.GenerateTemporal();
  459. code.AddLine("float " + temporal + " = " + Visit(operand) + ';');
  460. return temporal;
  461. }
  462. std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) {
  463. std::string value = VisitOperand(operation, operand_index);
  464. switch (type) {
  465. case Type::Bool:
  466. case Type::Bool2:
  467. case Type::Float:
  468. return value;
  469. case Type::Int:
  470. return "ftoi(" + value + ')';
  471. case Type::Uint:
  472. return "ftou(" + value + ')';
  473. case Type::HalfFloat:
  474. if (!std::holds_alternative<MetaHalfArithmetic>(operation.GetMeta())) {
  475. value = "toHalf2(" + value + ')';
  476. }
  477. const auto& half_meta = std::get<MetaHalfArithmetic>(operation.GetMeta());
  478. switch (half_meta.types.at(operand_index)) {
  479. case Tegra::Shader::HalfType::H0_H1:
  480. return "toHalf2(" + value + ')';
  481. case Tegra::Shader::HalfType::F32:
  482. return "vec2(" + value + ')';
  483. case Tegra::Shader::HalfType::H0_H0:
  484. return "vec2(toHalf2(" + value + ")[0])";
  485. case Tegra::Shader::HalfType::H1_H1:
  486. return "vec2(toHalf2(" + value + ")[1])";
  487. }
  488. }
  489. UNREACHABLE();
  490. return value;
  491. }
  492. std::string BitwiseCastResult(std::string value, Type type, bool needs_parenthesis = false) {
  493. switch (type) {
  494. case Type::Bool:
  495. case Type::Float:
  496. if (needs_parenthesis) {
  497. return '(' + value + ')';
  498. }
  499. return value;
  500. case Type::Int:
  501. return "itof(" + value + ')';
  502. case Type::Uint:
  503. return "utof(" + value + ')';
  504. case Type::HalfFloat:
  505. return "fromHalf2(" + value + ')';
  506. }
  507. UNREACHABLE();
  508. return value;
  509. }
  510. std::string GenerateUnary(Operation operation, const std::string& func, Type result_type,
  511. Type type_a, bool needs_parenthesis = true) {
  512. return ApplyPrecise(operation,
  513. BitwiseCastResult(func + '(' + VisitOperand(operation, 0, type_a) + ')',
  514. result_type, needs_parenthesis));
  515. }
  516. std::string GenerateBinaryInfix(Operation operation, const std::string& func, Type result_type,
  517. Type type_a, Type type_b) {
  518. const std::string op_a = VisitOperand(operation, 0, type_a);
  519. const std::string op_b = VisitOperand(operation, 1, type_b);
  520. return ApplyPrecise(
  521. operation, BitwiseCastResult('(' + op_a + ' ' + func + ' ' + op_b + ')', result_type));
  522. }
  523. std::string GenerateBinaryCall(Operation operation, const std::string& func, Type result_type,
  524. Type type_a, Type type_b) {
  525. const std::string op_a = VisitOperand(operation, 0, type_a);
  526. const std::string op_b = VisitOperand(operation, 1, type_b);
  527. return ApplyPrecise(operation,
  528. BitwiseCastResult(func + '(' + op_a + ", " + op_b + ')', result_type));
  529. }
  530. std::string GenerateTernary(Operation operation, const std::string& func, Type result_type,
  531. Type type_a, Type type_b, Type type_c) {
  532. const std::string op_a = VisitOperand(operation, 0, type_a);
  533. const std::string op_b = VisitOperand(operation, 1, type_b);
  534. const std::string op_c = VisitOperand(operation, 2, type_c);
  535. return ApplyPrecise(
  536. operation,
  537. BitwiseCastResult(func + '(' + op_a + ", " + op_b + ", " + op_c + ')', result_type));
  538. }
  539. std::string GenerateQuaternary(Operation operation, const std::string& func, Type result_type,
  540. Type type_a, Type type_b, Type type_c, Type type_d) {
  541. const std::string op_a = VisitOperand(operation, 0, type_a);
  542. const std::string op_b = VisitOperand(operation, 1, type_b);
  543. const std::string op_c = VisitOperand(operation, 2, type_c);
  544. const std::string op_d = VisitOperand(operation, 3, type_d);
  545. return ApplyPrecise(operation, BitwiseCastResult(func + '(' + op_a + ", " + op_b + ", " +
  546. op_c + ", " + op_d + ')',
  547. result_type));
  548. }
  549. std::string GenerateTexture(Operation operation, const std::string& func,
  550. std::string extra_cast(std::string) = nullptr) {
  551. constexpr std::array<const char*, 4> coord_constructors = {"float", "vec2", "vec3", "vec4"};
  552. const auto& meta = std::get<MetaTexture>(operation.GetMeta());
  553. const auto count = static_cast<u32>(operation.GetOperandsCount());
  554. std::string expr = func;
  555. expr += '(';
  556. expr += GetSampler(meta.sampler);
  557. expr += ", ";
  558. expr += coord_constructors[meta.coords_count - 1];
  559. expr += '(';
  560. for (u32 i = 0; i < count; ++i) {
  561. const bool is_extra = i >= meta.coords_count;
  562. const bool is_array = i == meta.array_index;
  563. std::string operand = Visit(operation[i]);
  564. if (is_extra && extra_cast != nullptr) {
  565. operand = extra_cast(operand);
  566. }
  567. if (is_array) {
  568. ASSERT(!is_extra);
  569. operand = "float(ftoi(" + operand + "))";
  570. }
  571. expr += operand;
  572. if (i + 1 == meta.coords_count) {
  573. expr += ')';
  574. }
  575. if (i + 1 < count) {
  576. expr += ", ";
  577. }
  578. }
  579. expr += ')';
  580. return expr;
  581. }
  582. std::string Assign(Operation operation) {
  583. const Node dest = operation[0];
  584. const Node src = operation[1];
  585. std::string target;
  586. if (const auto gpr = std::get_if<GprNode>(dest)) {
  587. if (gpr->GetIndex() == RZ) {
  588. // Writing to RZ is a no op
  589. return {};
  590. }
  591. target = GetRegister(gpr->GetIndex());
  592. } else if (const auto abuf = std::get_if<AbufNode>(dest)) {
  593. target = [&]() -> std::string {
  594. switch (const auto attribute = abuf->GetIndex(); abuf->GetIndex()) {
  595. case Attribute::Index::Position:
  596. return "position" + GetSwizzle(abuf->GetElement());
  597. case Attribute::Index::PointSize:
  598. return "gl_PointSize";
  599. case Attribute::Index::ClipDistances0123:
  600. return "gl_ClipDistance[" + std::to_string(abuf->GetElement()) + ']';
  601. case Attribute::Index::ClipDistances4567:
  602. return "gl_ClipDistance[" + std::to_string(abuf->GetElement() + 4) + ']';
  603. default:
  604. if (attribute >= Attribute::Index::Attribute_0 &&
  605. attribute <= Attribute::Index::Attribute_31) {
  606. return GetOutputAttribute(attribute) + GetSwizzle(abuf->GetElement());
  607. }
  608. UNIMPLEMENTED_MSG("Unhandled output attribute: {}",
  609. static_cast<u32>(attribute));
  610. return "0";
  611. }
  612. }();
  613. } else if (const auto lmem = std::get_if<LmemNode>(dest)) {
  614. target = GetLocalMemory() + "[ftou(" + Visit(lmem->GetAddress()) + ") / 4]";
  615. } else {
  616. UNREACHABLE_MSG("Assign called without a proper target");
  617. }
  618. code.AddLine(target + " = " + Visit(src) + ';');
  619. return {};
  620. }
  621. std::string AssignComposite(Operation operation) {
  622. const auto& meta = std::get<MetaComponents>(operation.GetMeta());
  623. const std::string composite = code.GenerateTemporal();
  624. code.AddLine("vec4 " + composite + " = " + Visit(operation[0]) + ';');
  625. constexpr u32 composite_size = 4;
  626. for (u32 i = 0; i < composite_size; ++i) {
  627. const auto gpr = std::get<GprNode>(*operation[i + 1]).GetIndex();
  628. if (gpr == RZ) {
  629. continue;
  630. }
  631. code.AddLine(GetRegister(gpr) + " = " + composite +
  632. GetSwizzle(meta.GetSourceComponent(i)) + ';');
  633. }
  634. return {};
  635. }
  636. std::string Composite(Operation operation) {
  637. std::string value = "vec4(";
  638. for (std::size_t i = 0; i < 4; ++i) {
  639. value += Visit(operation[i]);
  640. if (i < 3)
  641. value += ", ";
  642. }
  643. value += ')';
  644. return value;
  645. }
  646. template <Type type>
  647. std::string Add(Operation operation) {
  648. return GenerateBinaryInfix(operation, "+", type, type, type);
  649. }
  650. template <Type type>
  651. std::string Mul(Operation operation) {
  652. return GenerateBinaryInfix(operation, "*", type, type, type);
  653. }
  654. template <Type type>
  655. std::string Div(Operation operation) {
  656. return GenerateBinaryInfix(operation, "/", type, type, type);
  657. }
  658. template <Type type>
  659. std::string Fma(Operation operation) {
  660. return GenerateTernary(operation, "fma", type, type, type, type);
  661. }
  662. template <Type type>
  663. std::string Negate(Operation operation) {
  664. return GenerateUnary(operation, "-", type, type, true);
  665. }
  666. template <Type type>
  667. std::string Absolute(Operation operation) {
  668. return GenerateUnary(operation, "abs", type, type, false);
  669. }
  670. std::string FClamp(Operation operation) {
  671. return GenerateTernary(operation, "clamp", Type::Float, Type::Float, Type::Float,
  672. Type::Float);
  673. }
  674. template <Type type>
  675. std::string Min(Operation operation) {
  676. return GenerateBinaryCall(operation, "min", type, type, type);
  677. }
  678. template <Type type>
  679. std::string Max(Operation operation) {
  680. return GenerateBinaryCall(operation, "max", type, type, type);
  681. }
  682. std::string Select(Operation operation) {
  683. const std::string condition = Visit(operation[0]);
  684. const std::string true_case = Visit(operation[1]);
  685. const std::string false_case = Visit(operation[2]);
  686. return ApplyPrecise(operation,
  687. '(' + condition + " ? " + true_case + " : " + false_case + ')');
  688. }
  689. std::string FCos(Operation operation) {
  690. return GenerateUnary(operation, "cos", Type::Float, Type::Float, false);
  691. }
  692. std::string FSin(Operation operation) {
  693. return GenerateUnary(operation, "sin", Type::Float, Type::Float, false);
  694. }
  695. std::string FExp2(Operation operation) {
  696. return GenerateUnary(operation, "exp2", Type::Float, Type::Float, false);
  697. }
  698. std::string FLog2(Operation operation) {
  699. return GenerateUnary(operation, "log2", Type::Float, Type::Float, false);
  700. }
  701. std::string FInverseSqrt(Operation operation) {
  702. return GenerateUnary(operation, "inversesqrt", Type::Float, Type::Float, false);
  703. }
  704. std::string FSqrt(Operation operation) {
  705. return GenerateUnary(operation, "sqrt", Type::Float, Type::Float, false);
  706. }
  707. std::string FRoundEven(Operation operation) {
  708. return GenerateUnary(operation, "roundEven", Type::Float, Type::Float, false);
  709. }
  710. std::string FFloor(Operation operation) {
  711. return GenerateUnary(operation, "floor", Type::Float, Type::Float, false);
  712. }
  713. std::string FCeil(Operation operation) {
  714. return GenerateUnary(operation, "ceil", Type::Float, Type::Float, false);
  715. }
  716. std::string FTrunc(Operation operation) {
  717. return GenerateUnary(operation, "trunc", Type::Float, Type::Float, false);
  718. }
  719. template <Type type>
  720. std::string FCastInteger(Operation operation) {
  721. return GenerateUnary(operation, "float", Type::Float, type, false);
  722. }
  723. std::string ICastFloat(Operation operation) {
  724. return GenerateUnary(operation, "int", Type::Int, Type::Float, false);
  725. }
  726. std::string ICastUnsigned(Operation operation) {
  727. return GenerateUnary(operation, "int", Type::Int, Type::Uint, false);
  728. }
  729. template <Type type>
  730. std::string LogicalShiftLeft(Operation operation) {
  731. return GenerateBinaryInfix(operation, "<<", type, type, Type::Uint);
  732. }
  733. std::string ILogicalShiftRight(Operation operation) {
  734. const std::string op_a = VisitOperand(operation, 0, Type::Uint);
  735. const std::string op_b = VisitOperand(operation, 1, Type::Uint);
  736. return ApplyPrecise(operation,
  737. BitwiseCastResult("int(" + op_a + " >> " + op_b + ')', Type::Int));
  738. }
  739. std::string IArithmeticShiftRight(Operation operation) {
  740. return GenerateBinaryInfix(operation, ">>", Type::Int, Type::Int, Type::Uint);
  741. }
  742. template <Type type>
  743. std::string BitwiseAnd(Operation operation) {
  744. return GenerateBinaryInfix(operation, "&", type, type, type);
  745. }
  746. template <Type type>
  747. std::string BitwiseOr(Operation operation) {
  748. return GenerateBinaryInfix(operation, "|", type, type, type);
  749. }
  750. template <Type type>
  751. std::string BitwiseXor(Operation operation) {
  752. return GenerateBinaryInfix(operation, "^", type, type, type);
  753. }
  754. template <Type type>
  755. std::string BitwiseNot(Operation operation) {
  756. return GenerateUnary(operation, "~", type, type, false);
  757. }
  758. std::string UCastFloat(Operation operation) {
  759. return GenerateUnary(operation, "uint", Type::Uint, Type::Float, false);
  760. }
  761. std::string UCastSigned(Operation operation) {
  762. return GenerateUnary(operation, "uint", Type::Uint, Type::Int, false);
  763. }
  764. std::string UShiftRight(Operation operation) {
  765. return GenerateBinaryInfix(operation, ">>", Type::Uint, Type::Uint, Type::Uint);
  766. }
  767. template <Type type>
  768. std::string BitfieldInsert(Operation operation) {
  769. return GenerateQuaternary(operation, "bitfieldInsert", type, type, type, Type::Int,
  770. Type::Int);
  771. }
  772. template <Type type>
  773. std::string BitCount(Operation operation) {
  774. return GenerateUnary(operation, "bitCount", type, type, false);
  775. }
  776. std::string HNegate(Operation operation) {
  777. const auto GetNegate = [&](std::size_t index) -> std::string {
  778. return VisitOperand(operation, index, Type::Bool) + " ? -1 : 1";
  779. };
  780. const std::string value = '(' + VisitOperand(operation, 0, Type::HalfFloat) + " * vec2(" +
  781. GetNegate(1) + ", " + GetNegate(2) + "))";
  782. return BitwiseCastResult(value, Type::HalfFloat);
  783. }
  784. std::string HMergeF32(Operation operation) {
  785. return "float(toHalf2(" + Visit(operation[0]) + ")[0])";
  786. }
  787. std::string HMergeH0(Operation operation) {
  788. return "fromHalf2(vec2(toHalf2(" + Visit(operation[0]) + ")[1], toHalf2(" +
  789. Visit(operation[1]) + ")[0]))";
  790. }
  791. std::string HMergeH1(Operation operation) {
  792. return "fromHalf2(vec2(toHalf2(" + Visit(operation[0]) + ")[0], toHalf2(" +
  793. Visit(operation[1]) + ")[1]))";
  794. }
  795. template <Type type>
  796. std::string LogicalLessThan(Operation operation) {
  797. return GenerateBinaryInfix(operation, "<", Type::Bool, type, type);
  798. }
  799. template <Type type>
  800. std::string LogicalEqual(Operation operation) {
  801. return GenerateBinaryInfix(operation, "==", Type::Bool, type, type);
  802. }
  803. template <Type type>
  804. std::string LogicalLessEqual(Operation operation) {
  805. return GenerateBinaryInfix(operation, "<=", Type::Bool, type, type);
  806. }
  807. template <Type type>
  808. std::string LogicalGreaterThan(Operation operation) {
  809. return GenerateBinaryInfix(operation, ">", Type::Bool, type, type);
  810. }
  811. template <Type type>
  812. std::string LogicalNotEqual(Operation operation) {
  813. return GenerateBinaryInfix(operation, "!=", Type::Bool, type, type);
  814. }
  815. template <Type type>
  816. std::string LogicalGreaterEqual(Operation operation) {
  817. return GenerateBinaryInfix(operation, ">=", Type::Bool, type, type);
  818. }
  819. std::string LogicalFIsNan(Operation operation) {
  820. return GenerateUnary(operation, "isnan", Type::Bool, Type::Float, false);
  821. }
  822. std::string LogicalAssign(Operation operation) {
  823. const Node dest = operation[0];
  824. const Node src = operation[1];
  825. std::string target;
  826. if (const auto pred = std::get_if<PredicateNode>(dest)) {
  827. ASSERT_MSG(!pred->IsNegated(), "Negating logical assignment");
  828. const auto index = pred->GetIndex();
  829. switch (index) {
  830. case Tegra::Shader::Pred::NeverExecute:
  831. case Tegra::Shader::Pred::UnusedIndex:
  832. // Writing to these predicates is a no-op
  833. return {};
  834. }
  835. target = GetPredicate(index);
  836. } else if (const auto flag = std::get_if<InternalFlagNode>(dest)) {
  837. target = GetInternalFlag(flag->GetFlag());
  838. }
  839. code.AddLine(target + " = " + Visit(src) + ';');
  840. return {};
  841. }
  842. std::string LogicalAnd(Operation operation) {
  843. return GenerateBinaryInfix(operation, "&&", Type::Bool, Type::Bool, Type::Bool);
  844. }
  845. std::string LogicalOr(Operation operation) {
  846. return GenerateBinaryInfix(operation, "||", Type::Bool, Type::Bool, Type::Bool);
  847. }
  848. std::string LogicalXor(Operation operation) {
  849. return GenerateBinaryInfix(operation, "^^", Type::Bool, Type::Bool, Type::Bool);
  850. }
  851. std::string LogicalNegate(Operation operation) {
  852. return GenerateUnary(operation, "!", Type::Bool, Type::Bool, false);
  853. }
  854. std::string LogicalPick2(Operation operation) {
  855. const std::string pair = VisitOperand(operation, 0, Type::Bool2);
  856. return pair + '[' + VisitOperand(operation, 1, Type::Uint) + ']';
  857. }
  858. std::string LogicalAll2(Operation operation) {
  859. return GenerateUnary(operation, "all", Type::Bool, Type::Bool2);
  860. }
  861. std::string LogicalAny2(Operation operation) {
  862. return GenerateUnary(operation, "any", Type::Bool, Type::Bool2);
  863. }
  864. std::string Logical2HLessThan(Operation operation) {
  865. return GenerateBinaryCall(operation, "lessThan", Type::Bool2, Type::HalfFloat,
  866. Type::HalfFloat);
  867. }
  868. std::string Logical2HEqual(Operation operation) {
  869. return GenerateBinaryCall(operation, "equal", Type::Bool2, Type::HalfFloat,
  870. Type::HalfFloat);
  871. }
  872. std::string Logical2HLessEqual(Operation operation) {
  873. return GenerateBinaryCall(operation, "lessThanEqual", Type::Bool2, Type::HalfFloat,
  874. Type::HalfFloat);
  875. }
  876. std::string Logical2HGreaterThan(Operation operation) {
  877. return GenerateBinaryCall(operation, "greaterThan", Type::Bool2, Type::HalfFloat,
  878. Type::HalfFloat);
  879. }
  880. std::string Logical2HNotEqual(Operation operation) {
  881. return GenerateBinaryCall(operation, "notEqual", Type::Bool2, Type::HalfFloat,
  882. Type::HalfFloat);
  883. }
  884. std::string Logical2HGreaterEqual(Operation operation) {
  885. return GenerateBinaryCall(operation, "greaterThanEqual", Type::Bool2, Type::HalfFloat,
  886. Type::HalfFloat);
  887. }
  888. std::string F4Texture(Operation operation) {
  889. std::string expr = GenerateTexture(operation, "texture");
  890. if (std::get<MetaTexture>(operation.GetMeta()).sampler.IsShadow()) {
  891. expr = "vec4(" + expr + ')';
  892. }
  893. return expr;
  894. }
  895. std::string F4TextureLod(Operation operation) {
  896. std::string expr = GenerateTexture(operation, "textureLod");
  897. if (std::get<MetaTexture>(operation.GetMeta()).sampler.IsShadow()) {
  898. expr = "vec4(" + expr + ')';
  899. }
  900. return expr;
  901. }
  902. std::string F4TextureGather(Operation operation) {
  903. const bool is_shadow = std::get<MetaTexture>(operation.GetMeta()).sampler.IsShadow();
  904. if (is_shadow) {
  905. return GenerateTexture(operation, "textureGather",
  906. [](std::string ref_z) { return ref_z; });
  907. } else {
  908. return GenerateTexture(operation, "textureGather",
  909. [](std::string comp) { return "ftoi(" + comp + ')'; });
  910. }
  911. }
  912. std::string F4TextureQueryDimensions(Operation operation) {
  913. const auto& meta = std::get<MetaTexture>(operation.GetMeta());
  914. const std::string sampler = GetSampler(meta.sampler);
  915. const std::string lod = VisitOperand(operation, 0, Type::Int);
  916. const std::string sizes = code.GenerateTemporal();
  917. code.AddLine("ivec2 " + sizes + " = textureSize(" + sampler + ", " + lod + ");");
  918. const std::string mip_level = "textureQueryLevels(" + sampler + ')';
  919. return "itof(ivec4(" + sizes + ", 0, " + mip_level + "))";
  920. }
  921. std::string F4TextureQueryLod(Operation operation) {
  922. const std::string tmp = code.GenerateTemporal();
  923. code.AddLine("vec2 " + tmp + " = " + GenerateTexture(operation, "textureQueryLod") +
  924. " * vec2(256);");
  925. return "vec4(itof(int(" + tmp + ".y)), utof(uint(" + tmp + ".x)), 0, 0)";
  926. }
  927. std::string F4TexelFetch(Operation operation) {
  928. constexpr std::array<const char*, 4> constructors = {"int", "ivec2", "ivec3", "ivec4"};
  929. const auto& meta = std::get<MetaTexture>(operation.GetMeta());
  930. const auto count = static_cast<u32>(operation.GetOperandsCount());
  931. std::string expr = "texelFetch(";
  932. expr += GetSampler(meta.sampler);
  933. expr += ", ";
  934. expr += constructors[meta.coords_count - 1];
  935. expr += '(';
  936. for (u32 i = 0; i < count; ++i) {
  937. expr += VisitOperand(operation, i, Type::Int);
  938. expr += ", ";
  939. if (i + 1 == meta.coords_count) {
  940. expr += ')';
  941. }
  942. if (i + 1 < count) {
  943. expr += ", ";
  944. }
  945. }
  946. expr += ')';
  947. return expr;
  948. }
  949. std::string Ipa(Operation operation) {
  950. const auto& attribute = operation[0];
  951. // TODO(Rodrigo): Special IPA attribute interactions
  952. return Visit(attribute);
  953. }
  954. std::string Bra(Operation operation) {
  955. const auto target = std::get<ImmediateNode>(*operation[0]);
  956. code.AddLine(fmt::format("jmp_to = 0x{:x}u;", target.GetValue()));
  957. code.AddLine("break;");
  958. return {};
  959. }
  960. std::string PushFlowStack(Operation operation) {
  961. const auto target = std::get<ImmediateNode>(*operation[0]);
  962. code.AddLine(fmt::format("flow_stack[flow_stack_top] = 0x{:x}u;", target.GetValue()));
  963. code.AddLine("flow_stack_top++;");
  964. return {};
  965. }
  966. std::string PopFlowStack(Operation operation) {
  967. code.AddLine("flow_stack_top--;");
  968. code.AddLine("jmp_to = flow_stack[flow_stack_top];");
  969. code.AddLine("break;");
  970. return {};
  971. }
  972. std::string Exit(Operation operation) {
  973. if (stage != ShaderStage::Fragment) {
  974. code.AddLine("return;");
  975. return {};
  976. }
  977. const auto& used_registers = ir.GetRegisters();
  978. const auto SafeGetRegister = [&](u32 reg) -> std::string {
  979. // TODO(Rodrigo): Replace with contains once C++20 releases
  980. if (used_registers.find(reg) != used_registers.end()) {
  981. return GetRegister(reg);
  982. }
  983. return "0.0f";
  984. };
  985. UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, "Sample mask write is unimplemented");
  986. code.AddLine("if (alpha_test[0] != 0) {");
  987. ++code.scope;
  988. // We start on the register containing the alpha value in the first RT.
  989. u32 current_reg = 3;
  990. for (u32 render_target = 0; render_target < Maxwell::NumRenderTargets; ++render_target) {
  991. // TODO(Blinkhawk): verify the behavior of alpha testing on hardware when
  992. // multiple render targets are used.
  993. if (header.ps.IsColorComponentOutputEnabled(render_target, 0) ||
  994. header.ps.IsColorComponentOutputEnabled(render_target, 1) ||
  995. header.ps.IsColorComponentOutputEnabled(render_target, 2) ||
  996. header.ps.IsColorComponentOutputEnabled(render_target, 3)) {
  997. code.AddLine(
  998. fmt::format("if (!AlphaFunc({})) discard;", SafeGetRegister(current_reg)));
  999. current_reg += 4;
  1000. }
  1001. }
  1002. --code.scope;
  1003. code.AddLine('}');
  1004. // Write the color outputs using the data in the shader registers, disabled
  1005. // rendertargets/components are skipped in the register assignment.
  1006. current_reg = 0;
  1007. for (u32 render_target = 0; render_target < Maxwell::NumRenderTargets; ++render_target) {
  1008. // TODO(Subv): Figure out how dual-source blending is configured in the Switch.
  1009. for (u32 component = 0; component < 4; ++component) {
  1010. if (header.ps.IsColorComponentOutputEnabled(render_target, component)) {
  1011. code.AddLine(fmt::format("FragColor{}[{}] = {};", render_target, component,
  1012. SafeGetRegister(current_reg)));
  1013. ++current_reg;
  1014. }
  1015. }
  1016. }
  1017. if (header.ps.omap.depth) {
  1018. // The depth output is always 2 registers after the last color output, and current_reg
  1019. // already contains one past the last color register.
  1020. code.AddLine("gl_FragDepth = " + SafeGetRegister(current_reg + 1) + ';');
  1021. }
  1022. code.AddLine("return;");
  1023. return {};
  1024. }
  1025. std::string Kil(Operation operation) {
  1026. // Enclose "discard" in a conditional, so that GLSL compilation does not complain
  1027. // about unexecuted instructions that may follow this.
  1028. code.AddLine("if (true) {");
  1029. ++code.scope;
  1030. code.AddLine("discard;");
  1031. --code.scope;
  1032. code.AddLine("}");
  1033. return {};
  1034. }
  1035. std::string YNegate(Operation operation) {
  1036. // Config pack's third value is Y_NEGATE's state.
  1037. return "uintBitsToFloat(config_pack[2])";
  1038. }
  1039. static constexpr OperationDecompilersArray operation_decompilers = {
  1040. &Assign,
  1041. &AssignComposite,
  1042. &Composite,
  1043. &Select,
  1044. &Add<Type::Float>,
  1045. &Mul<Type::Float>,
  1046. &Div<Type::Float>,
  1047. &Fma<Type::Float>,
  1048. &Negate<Type::Float>,
  1049. &Absolute<Type::Float>,
  1050. &FClamp,
  1051. &Min<Type::Float>,
  1052. &Max<Type::Float>,
  1053. &FCos,
  1054. &FSin,
  1055. &FExp2,
  1056. &FLog2,
  1057. &FInverseSqrt,
  1058. &FSqrt,
  1059. &FRoundEven,
  1060. &FFloor,
  1061. &FCeil,
  1062. &FTrunc,
  1063. &FCastInteger<Type::Int>,
  1064. &FCastInteger<Type::Uint>,
  1065. &Add<Type::Int>,
  1066. &Mul<Type::Int>,
  1067. &Div<Type::Int>,
  1068. &Negate<Type::Int>,
  1069. &Absolute<Type::Int>,
  1070. &Min<Type::Int>,
  1071. &Max<Type::Int>,
  1072. &ICastFloat,
  1073. &ICastUnsigned,
  1074. &LogicalShiftLeft<Type::Int>,
  1075. &ILogicalShiftRight,
  1076. &IArithmeticShiftRight,
  1077. &BitwiseAnd<Type::Int>,
  1078. &BitwiseOr<Type::Int>,
  1079. &BitwiseXor<Type::Int>,
  1080. &BitwiseNot<Type::Int>,
  1081. &BitfieldInsert<Type::Int>,
  1082. &BitCount<Type::Int>,
  1083. &Add<Type::Uint>,
  1084. &Mul<Type::Uint>,
  1085. &Div<Type::Uint>,
  1086. &Min<Type::Uint>,
  1087. &Max<Type::Uint>,
  1088. &UCastFloat,
  1089. &UCastSigned,
  1090. &LogicalShiftLeft<Type::Uint>,
  1091. &UShiftRight,
  1092. &UShiftRight,
  1093. &BitwiseAnd<Type::Uint>,
  1094. &BitwiseOr<Type::Uint>,
  1095. &BitwiseXor<Type::Uint>,
  1096. &BitwiseNot<Type::Uint>,
  1097. &BitfieldInsert<Type::Uint>,
  1098. &BitCount<Type::Uint>,
  1099. &Add<Type::HalfFloat>,
  1100. &Mul<Type::HalfFloat>,
  1101. &Fma<Type::HalfFloat>,
  1102. &Absolute<Type::HalfFloat>,
  1103. &HNegate,
  1104. &HMergeF32,
  1105. &HMergeH0,
  1106. &HMergeH1,
  1107. &LogicalAssign,
  1108. &LogicalAnd,
  1109. &LogicalOr,
  1110. &LogicalXor,
  1111. &LogicalNegate,
  1112. &LogicalPick2,
  1113. &LogicalAll2,
  1114. &LogicalAny2,
  1115. &LogicalLessThan<Type::Float>,
  1116. &LogicalEqual<Type::Float>,
  1117. &LogicalLessEqual<Type::Float>,
  1118. &LogicalGreaterThan<Type::Float>,
  1119. &LogicalNotEqual<Type::Float>,
  1120. &LogicalGreaterEqual<Type::Float>,
  1121. &LogicalFIsNan,
  1122. &LogicalLessThan<Type::Int>,
  1123. &LogicalEqual<Type::Int>,
  1124. &LogicalLessEqual<Type::Int>,
  1125. &LogicalGreaterThan<Type::Int>,
  1126. &LogicalNotEqual<Type::Int>,
  1127. &LogicalGreaterEqual<Type::Int>,
  1128. &LogicalLessThan<Type::Uint>,
  1129. &LogicalEqual<Type::Uint>,
  1130. &LogicalLessEqual<Type::Uint>,
  1131. &LogicalGreaterThan<Type::Uint>,
  1132. &LogicalNotEqual<Type::Uint>,
  1133. &LogicalGreaterEqual<Type::Uint>,
  1134. &Logical2HLessThan,
  1135. &Logical2HEqual,
  1136. &Logical2HLessEqual,
  1137. &Logical2HGreaterThan,
  1138. &Logical2HNotEqual,
  1139. &Logical2HGreaterEqual,
  1140. &F4Texture,
  1141. &F4TextureLod,
  1142. &F4TextureGather,
  1143. &F4TextureQueryDimensions,
  1144. &F4TextureQueryLod,
  1145. &F4TexelFetch,
  1146. &Ipa,
  1147. &Bra,
  1148. &PushFlowStack, // Ssy
  1149. &PushFlowStack, // Brk
  1150. &PopFlowStack, // Sync
  1151. &PopFlowStack, // Brk
  1152. &Exit,
  1153. &Kil,
  1154. &YNegate,
  1155. };
  1156. std::string GetRegister(u32 index) const {
  1157. return GetDeclarationWithSuffix(index, "gpr");
  1158. }
  1159. std::string GetPredicate(Tegra::Shader::Pred pred) const {
  1160. return GetDeclarationWithSuffix(static_cast<u32>(pred), "pred");
  1161. }
  1162. std::string GetInputAttribute(Attribute::Index attribute) const {
  1163. const auto index{static_cast<u32>(attribute) -
  1164. static_cast<u32>(Attribute::Index::Attribute_0)};
  1165. return GetDeclarationWithSuffix(index, "input_attr");
  1166. }
  1167. std::string GetOutputAttribute(Attribute::Index attribute) const {
  1168. const auto index{static_cast<u32>(attribute) -
  1169. static_cast<u32>(Attribute::Index::Attribute_0)};
  1170. return GetDeclarationWithSuffix(index, "output_attr");
  1171. }
  1172. std::string GetConstBuffer(u32 index) const {
  1173. return GetDeclarationWithSuffix(index, "cbuf");
  1174. }
  1175. std::string GetConstBufferBlock(u32 index) const {
  1176. return GetDeclarationWithSuffix(index, "cbuf_block");
  1177. }
  1178. std::string GetLocalMemory() const {
  1179. return "lmem_" + suffix;
  1180. }
  1181. std::string GetInternalFlag(InternalFlag flag) const {
  1182. constexpr std::array<const char*, 4> InternalFlagNames = {"zero_flag", "sign_flag",
  1183. "carry_flag", "overflow_flag"};
  1184. const auto index = static_cast<u32>(flag);
  1185. ASSERT(index < static_cast<u32>(InternalFlag::Amount));
  1186. return std::string(InternalFlagNames[index]) + '_' + suffix;
  1187. }
  1188. std::string GetSampler(const Sampler& sampler) const {
  1189. return GetDeclarationWithSuffix(static_cast<u32>(sampler.GetIndex()), "sampler");
  1190. }
  1191. std::string GetDeclarationWithSuffix(u32 index, const std::string& name) const {
  1192. return name + '_' + std::to_string(index) + '_' + suffix;
  1193. }
  1194. const ShaderIR& ir;
  1195. const ShaderStage stage;
  1196. const std::string suffix;
  1197. const Header header;
  1198. ShaderWriter code;
  1199. };
  1200. std::string GetCommonDeclarations() {
  1201. return "#define MAX_CONSTBUFFER_ELEMENTS " + std::to_string(MAX_CONSTBUFFER_ELEMENTS) +
  1202. "\n"
  1203. "#define ftoi floatBitsToInt\n"
  1204. "#define ftou floatBitsToUint\n"
  1205. "#define itof intBitsToFloat\n"
  1206. "#define utof uintBitsToFloat\n\n"
  1207. "float fromHalf2(vec2 pair) {\n"
  1208. " return utof(packHalf2x16(pair));\n"
  1209. "}\n\n"
  1210. "vec2 toHalf2(float value) {\n"
  1211. " return unpackHalf2x16(ftou(value));\n"
  1212. "}\n\n";
  1213. }
  1214. ProgramResult Decompile(const ShaderIR& ir, Maxwell::ShaderStage stage, const std::string& suffix) {
  1215. GLSLDecompiler decompiler(ir, stage, suffix);
  1216. decompiler.Decompile();
  1217. return {decompiler.GetResult(), decompiler.GetShaderEntries()};
  1218. }
  1219. } // namespace OpenGL::GLShader