emit_glsl_special.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <string_view>
  5. #include "shader_recompiler/backend/glsl/emit_context.h"
  6. #include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
  7. #include "shader_recompiler/frontend/ir/program.h"
  8. #include "shader_recompiler/frontend/ir/value.h"
  9. #include "shader_recompiler/profile.h"
  10. namespace Shader::Backend::GLSL {
  11. namespace {
  12. std::string_view OutputVertexIndex(EmitContext& ctx) {
  13. return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : "";
  14. }
  15. void InitializeOutputVaryings(EmitContext& ctx) {
  16. if (ctx.uses_geometry_passthrough) {
  17. return;
  18. }
  19. if (ctx.stage == Stage::VertexB || ctx.stage == Stage::Geometry) {
  20. ctx.Add("gl_Position=vec4(0,0,0,1);");
  21. }
  22. for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
  23. if (!ctx.info.stores.Generic(index)) {
  24. continue;
  25. }
  26. const auto& info_array{ctx.output_generics.at(index)};
  27. const auto output_decorator{OutputVertexIndex(ctx)};
  28. size_t element{};
  29. while (element < info_array.size()) {
  30. const auto& info{info_array.at(element)};
  31. const auto varying_name{fmt::format("{}{}", info.name, output_decorator)};
  32. switch (info.num_components) {
  33. case 1: {
  34. const char value{element == 3 ? '1' : '0'};
  35. ctx.Add("{}={}.f;", varying_name, value);
  36. break;
  37. }
  38. case 2:
  39. case 3:
  40. if (element + info.num_components < 4) {
  41. ctx.Add("{}=vec{}(0);", varying_name, info.num_components);
  42. } else {
  43. // last element is the w component, must be initialized to 1
  44. const auto zeros{info.num_components == 3 ? "0,0," : "0,"};
  45. ctx.Add("{}=vec{}({}1);", varying_name, info.num_components, zeros);
  46. }
  47. break;
  48. case 4:
  49. ctx.Add("{}=vec4(0,0,0,1);", varying_name);
  50. break;
  51. default:
  52. break;
  53. }
  54. element += info.num_components;
  55. }
  56. }
  57. }
  58. } // Anonymous namespace
  59. void EmitPhi(EmitContext& ctx, IR::Inst& phi) {
  60. const size_t num_args{phi.NumArgs()};
  61. for (size_t i = 0; i < num_args; ++i) {
  62. ctx.var_alloc.Consume(phi.Arg(i));
  63. }
  64. if (!phi.Definition<Id>().is_valid) {
  65. // The phi node wasn't forward defined
  66. ctx.var_alloc.PhiDefine(phi, phi.Arg(0).Type());
  67. }
  68. }
  69. void EmitVoid(EmitContext&) {}
  70. void EmitReference(EmitContext& ctx, const IR::Value& value) {
  71. ctx.var_alloc.Consume(value);
  72. }
  73. void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) {
  74. IR::Inst& phi{*phi_value.InstRecursive()};
  75. const auto phi_type{phi.Arg(0).Type()};
  76. if (!phi.Definition<Id>().is_valid) {
  77. // The phi node wasn't forward defined
  78. ctx.var_alloc.PhiDefine(phi, phi_type);
  79. }
  80. const auto phi_reg{ctx.var_alloc.Consume(IR::Value{&phi})};
  81. const auto val_reg{ctx.var_alloc.Consume(value)};
  82. if (phi_reg == val_reg) {
  83. return;
  84. }
  85. ctx.Add("{}={};", phi_reg, val_reg);
  86. }
  87. void EmitPrologue(EmitContext& ctx) {
  88. InitializeOutputVaryings(ctx);
  89. }
  90. void EmitEpilogue(EmitContext&) {}
  91. void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) {
  92. ctx.Add("EmitStreamVertex(int({}));", ctx.var_alloc.Consume(stream));
  93. InitializeOutputVaryings(ctx);
  94. }
  95. void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) {
  96. ctx.Add("EndStreamPrimitive(int({}));", ctx.var_alloc.Consume(stream));
  97. }
  98. } // namespace Shader::Backend::GLSL