summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-03-02 18:55:39 -0300
committerGravatar ReinUsesLisp2020-03-13 18:33:04 -0300
commit4d711dface5dfc76d5ae0d62c635ec9ba6bd4293 (patch)
treed17ce1cda84d67e53e3ced539a2de94c5ad7c24d /src
parentshader/transform_feedback: Add host API friendly TFB builder (diff)
downloadyuzu-4d711dface5dfc76d5ae0d62c635ec9ba6bd4293.tar.gz
yuzu-4d711dface5dfc76d5ae0d62c635ec9ba6bd4293.tar.xz
yuzu-4d711dface5dfc76d5ae0d62c635ec9ba6bd4293.zip
gl_shader_decompiler: Decorate output attributes with XFB layout
We sometimes have to slice attributes in different parts. This is needed for example in instances where the game feedbacks 3 components but writes 4 from the shader (something that is possible with GL_NV_transform_feedback).
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp134
1 files changed, 105 insertions, 29 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 19d6f3dcb..021edf1f6 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -23,6 +23,7 @@
23#include "video_core/shader/ast.h" 23#include "video_core/shader/ast.h"
24#include "video_core/shader/node.h" 24#include "video_core/shader/node.h"
25#include "video_core/shader/shader_ir.h" 25#include "video_core/shader/shader_ir.h"
26#include "video_core/shader/transform_feedback.h"
26 27
27namespace OpenGL { 28namespace OpenGL {
28 29
@@ -36,6 +37,7 @@ using Tegra::Shader::IpaInterpMode;
36using Tegra::Shader::IpaMode; 37using Tegra::Shader::IpaMode;
37using Tegra::Shader::IpaSampleMode; 38using Tegra::Shader::IpaSampleMode;
38using Tegra::Shader::Register; 39using Tegra::Shader::Register;
40using VideoCommon::Shader::BuildTransformFeedback;
39using VideoCommon::Shader::Registry; 41using VideoCommon::Shader::Registry;
40 42
41using namespace std::string_literals; 43using namespace std::string_literals;
@@ -49,6 +51,11 @@ class ExprDecompiler;
49 51
50enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat }; 52enum class Type { Void, Bool, Bool2, Float, Int, Uint, HalfFloat };
51 53
54constexpr std::array FLOAT_TYPES{"float", "vec2", "vec3", "vec4"};
55
56constexpr std::string_view INPUT_ATTRIBUTE_NAME = "in_attr";
57constexpr std::string_view OUTPUT_ATTRIBUTE_NAME = "out_attr";
58
52struct TextureOffset {}; 59struct TextureOffset {};
53struct TextureDerivates {}; 60struct TextureDerivates {};
54using TextureArgument = std::pair<Type, Node>; 61using TextureArgument = std::pair<Type, Node>;
@@ -390,12 +397,19 @@ std::string FlowStackTopName(MetaStackClass stack) {
390 return stage == ShaderType::Vertex; 397 return stage == ShaderType::Vertex;
391} 398}
392 399
400struct GenericVaryingDescription {
401 std::string name;
402 u8 first_element = 0;
403 bool is_scalar = false;
404};
405
393class GLSLDecompiler final { 406class GLSLDecompiler final {
394public: 407public:
395 explicit GLSLDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry, 408 explicit GLSLDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry,
396 ShaderType stage, std::string_view identifier, std::string_view suffix) 409 ShaderType stage, std::string_view identifier, std::string_view suffix)
397 : device{device}, ir{ir}, registry{registry}, stage{stage}, 410 : device{device}, ir{ir}, registry{registry}, stage{stage},
398 identifier{identifier}, suffix{suffix}, header{ir.GetHeader()} {} 411 identifier{identifier}, suffix{suffix}, header{ir.GetHeader()},
412 transform_feedback{BuildTransformFeedback(registry.GetGraphicsInfo())} {}
399 413
400 void Decompile() { 414 void Decompile() {
401 DeclareHeader(); 415 DeclareHeader();
@@ -403,17 +417,17 @@ public:
403 DeclareGeometry(); 417 DeclareGeometry();
404 DeclareFragment(); 418 DeclareFragment();
405 DeclareCompute(); 419 DeclareCompute();
406 DeclareRegisters();
407 DeclareCustomVariables();
408 DeclarePredicates();
409 DeclareLocalMemory();
410 DeclareInternalFlags();
411 DeclareInputAttributes(); 420 DeclareInputAttributes();
412 DeclareOutputAttributes(); 421 DeclareOutputAttributes();
413 DeclareConstantBuffers();
414 DeclareGlobalMemory();
415 DeclareSamplers();
416 DeclareImages(); 422 DeclareImages();
423 DeclareSamplers();
424 DeclareGlobalMemory();
425 DeclareConstantBuffers();
426 DeclareLocalMemory();
427 DeclareRegisters();
428 DeclarePredicates();
429 DeclareInternalFlags();
430 DeclareCustomVariables();
417 DeclarePhysicalAttributeReader(); 431 DeclarePhysicalAttributeReader();
418 432
419 code.AddLine("void main() {{"); 433 code.AddLine("void main() {{");
@@ -485,7 +499,7 @@ private:
485 if (!identifier.empty()) { 499 if (!identifier.empty()) {
486 code.AddLine("// {}", identifier); 500 code.AddLine("// {}", identifier);
487 } 501 }
488 code.AddLine("#version 430 core"); 502 code.AddLine("#version 440 core");
489 code.AddLine("#extension GL_ARB_separate_shader_objects : enable"); 503 code.AddLine("#extension GL_ARB_separate_shader_objects : enable");
490 if (device.HasShaderBallot()) { 504 if (device.HasShaderBallot()) {
491 code.AddLine("#extension GL_ARB_shader_ballot : require"); 505 code.AddLine("#extension GL_ARB_shader_ballot : require");
@@ -570,7 +584,13 @@ private:
570 code.AddLine("out gl_PerVertex {{"); 584 code.AddLine("out gl_PerVertex {{");
571 ++code.scope; 585 ++code.scope;
572 586
573 code.AddLine("vec4 gl_Position;"); 587 auto pos_xfb = GetTransformFeedbackDecoration(Attribute::Index::Position);
588 if (!pos_xfb.empty()) {
589 pos_xfb = fmt::format("layout ({}) ", pos_xfb);
590 }
591 const char* pos_type =
592 FLOAT_TYPES.at(GetNumComponents(Attribute::Index::Position).value_or(4) - 1);
593 code.AddLine("{}{} gl_Position;", pos_xfb, pos_type);
574 594
575 for (const auto attribute : ir.GetOutputAttributes()) { 595 for (const auto attribute : ir.GetOutputAttributes()) {
576 if (attribute == Attribute::Index::ClipDistances0123 || 596 if (attribute == Attribute::Index::ClipDistances0123 ||
@@ -703,7 +723,7 @@ private:
703 void DeclareInputAttribute(Attribute::Index index, bool skip_unused) { 723 void DeclareInputAttribute(Attribute::Index index, bool skip_unused) {
704 const u32 location{GetGenericAttributeIndex(index)}; 724 const u32 location{GetGenericAttributeIndex(index)};
705 725
706 std::string name{GetInputAttribute(index)}; 726 std::string name{GetGenericInputAttribute(index)};
707 if (stage == ShaderType::Geometry) { 727 if (stage == ShaderType::Geometry) {
708 name = "gs_" + name + "[]"; 728 name = "gs_" + name + "[]";
709 } 729 }
@@ -740,9 +760,58 @@ private:
740 } 760 }
741 } 761 }
742 762
763 std::optional<std::size_t> GetNumComponents(Attribute::Index index, u8 element = 0) const {
764 const u8 location = static_cast<u8>(index) * 4 + element;
765 const auto it = transform_feedback.find(location);
766 if (it == transform_feedback.end()) {
767 return {};
768 }
769 return it->second.components;
770 }
771
772 std::string GetTransformFeedbackDecoration(Attribute::Index index, u8 element = 0) const {
773 const u8 location = static_cast<u8>(index) * 4 + element;
774 const auto it = transform_feedback.find(location);
775 if (it == transform_feedback.end()) {
776 return {};
777 }
778
779 const VaryingTFB& tfb = it->second;
780 return fmt::format("xfb_buffer = {}, xfb_offset = {}", tfb.buffer, tfb.offset);
781 }
782
743 void DeclareOutputAttribute(Attribute::Index index) { 783 void DeclareOutputAttribute(Attribute::Index index) {
744 const u32 location{GetGenericAttributeIndex(index)}; 784 static constexpr std::string_view swizzle = "xyzw";
745 code.AddLine("layout (location = {}) out vec4 {};", location, GetOutputAttribute(index)); 785 u8 element = 0;
786 while (element < 4) {
787 auto xfb = GetTransformFeedbackDecoration(index, element);
788 if (!xfb.empty()) {
789 xfb = fmt::format(", {}", xfb);
790 }
791 const std::size_t remainder = 4 - element;
792 const std::size_t num_components = GetNumComponents(index, element).value_or(remainder);
793 const char* const type = FLOAT_TYPES.at(num_components - 1);
794
795 const u32 location = GetGenericAttributeIndex(index);
796
797 GenericVaryingDescription description;
798 description.first_element = static_cast<u8>(element);
799 description.is_scalar = num_components == 1;
800 description.name = AppendSuffix(location, OUTPUT_ATTRIBUTE_NAME);
801 if (element != 0 || num_components != 4) {
802 const std::string_view name_swizzle = swizzle.substr(element, num_components);
803 description.name = fmt::format("{}_{}", description.name, name_swizzle);
804 }
805 for (std::size_t i = 0; i < num_components; ++i) {
806 const u8 offset = static_cast<u8>(location * 4 + element + i);
807 varying_description.insert({offset, description});
808 }
809
810 code.AddLine("layout (location = {}, component = {}{}) out {} {};", location, element,
811 xfb, type, description.name);
812
813 element += static_cast<u8>(num_components);
814 }
746 } 815 }
747 816
748 void DeclareConstantBuffers() { 817 void DeclareConstantBuffers() {
@@ -1095,7 +1164,7 @@ private:
1095 return {"0", Type::Int}; 1164 return {"0", Type::Int};
1096 default: 1165 default:
1097 if (IsGenericAttribute(attribute)) { 1166 if (IsGenericAttribute(attribute)) {
1098 return {GeometryPass(GetInputAttribute(attribute)) + GetSwizzle(element), 1167 return {GeometryPass(GetGenericInputAttribute(attribute)) + GetSwizzle(element),
1099 Type::Float}; 1168 Type::Float};
1100 } 1169 }
1101 break; 1170 break;
@@ -1164,8 +1233,7 @@ private:
1164 return {{fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4), Type::Float}}; 1233 return {{fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4), Type::Float}};
1165 default: 1234 default:
1166 if (IsGenericAttribute(attribute)) { 1235 if (IsGenericAttribute(attribute)) {
1167 return { 1236 return {{GetGenericOutputAttribute(attribute, abuf->GetElement()), Type::Float}};
1168 {GetOutputAttribute(attribute) + GetSwizzle(abuf->GetElement()), Type::Float}};
1169 } 1237 }
1170 UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute)); 1238 UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute));
1171 return {}; 1239 return {};
@@ -2376,27 +2444,34 @@ private:
2376 static_assert(operation_decompilers.size() == static_cast<std::size_t>(OperationCode::Amount)); 2444 static_assert(operation_decompilers.size() == static_cast<std::size_t>(OperationCode::Amount));
2377 2445
2378 std::string GetRegister(u32 index) const { 2446 std::string GetRegister(u32 index) const {
2379 return GetDeclarationWithSuffix(index, "gpr"); 2447 return AppendSuffix(index, "gpr");
2380 } 2448 }
2381 2449
2382 std::string GetCustomVariable(u32 index) const { 2450 std::string GetCustomVariable(u32 index) const {
2383 return GetDeclarationWithSuffix(index, "custom_var"); 2451 return AppendSuffix(index, "custom_var");
2384 } 2452 }
2385 2453
2386 std::string GetPredicate(Tegra::Shader::Pred pred) const { 2454 std::string GetPredicate(Tegra::Shader::Pred pred) const {
2387 return GetDeclarationWithSuffix(static_cast<u32>(pred), "pred"); 2455 return AppendSuffix(static_cast<u32>(pred), "pred");
2388 } 2456 }
2389 2457
2390 std::string GetInputAttribute(Attribute::Index attribute) const { 2458 std::string GetGenericInputAttribute(Attribute::Index attribute) const {
2391 return GetDeclarationWithSuffix(GetGenericAttributeIndex(attribute), "input_attr"); 2459 return AppendSuffix(GetGenericAttributeIndex(attribute), INPUT_ATTRIBUTE_NAME);
2392 } 2460 }
2393 2461
2394 std::string GetOutputAttribute(Attribute::Index attribute) const { 2462 std::unordered_map<u8, GenericVaryingDescription> varying_description;
2395 return GetDeclarationWithSuffix(GetGenericAttributeIndex(attribute), "output_attr"); 2463
2464 std::string GetGenericOutputAttribute(Attribute::Index attribute, std::size_t element) const {
2465 const u8 offset = static_cast<u8>(GetGenericAttributeIndex(attribute) * 4 + element);
2466 const auto& description = varying_description.at(offset);
2467 if (description.is_scalar) {
2468 return description.name;
2469 }
2470 return fmt::format("{}[{}]", description.name, element - description.first_element);
2396 } 2471 }
2397 2472
2398 std::string GetConstBuffer(u32 index) const { 2473 std::string GetConstBuffer(u32 index) const {
2399 return GetDeclarationWithSuffix(index, "cbuf"); 2474 return AppendSuffix(index, "cbuf");
2400 } 2475 }
2401 2476
2402 std::string GetGlobalMemory(const GlobalMemoryBase& descriptor) const { 2477 std::string GetGlobalMemory(const GlobalMemoryBase& descriptor) const {
@@ -2409,7 +2484,7 @@ private:
2409 } 2484 }
2410 2485
2411 std::string GetConstBufferBlock(u32 index) const { 2486 std::string GetConstBufferBlock(u32 index) const {
2412 return GetDeclarationWithSuffix(index, "cbuf_block"); 2487 return AppendSuffix(index, "cbuf_block");
2413 } 2488 }
2414 2489
2415 std::string GetLocalMemory() const { 2490 std::string GetLocalMemory() const {
@@ -2434,14 +2509,14 @@ private:
2434 } 2509 }
2435 2510
2436 std::string GetSampler(const Sampler& sampler) const { 2511 std::string GetSampler(const Sampler& sampler) const {
2437 return GetDeclarationWithSuffix(static_cast<u32>(sampler.GetIndex()), "sampler"); 2512 return AppendSuffix(static_cast<u32>(sampler.GetIndex()), "sampler");
2438 } 2513 }
2439 2514
2440 std::string GetImage(const Image& image) const { 2515 std::string GetImage(const Image& image) const {
2441 return GetDeclarationWithSuffix(static_cast<u32>(image.GetIndex()), "image"); 2516 return AppendSuffix(static_cast<u32>(image.GetIndex()), "image");
2442 } 2517 }
2443 2518
2444 std::string GetDeclarationWithSuffix(u32 index, std::string_view name) const { 2519 std::string AppendSuffix(u32 index, std::string_view name) const {
2445 if (suffix.empty()) { 2520 if (suffix.empty()) {
2446 return fmt::format("{}{}", name, index); 2521 return fmt::format("{}{}", name, index);
2447 } else { 2522 } else {
@@ -2477,6 +2552,7 @@ private:
2477 const std::string_view identifier; 2552 const std::string_view identifier;
2478 const std::string_view suffix; 2553 const std::string_view suffix;
2479 const Header header; 2554 const Header header;
2555 const std::unordered_map<u8, VaryingTFB> transform_feedback;
2480 2556
2481 ShaderWriter code; 2557 ShaderWriter code;
2482 2558