From 7632a7d6d2cd1fca58dcc714fccac01ec2753547 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 29 Apr 2019 23:27:15 -0300 Subject: shader_bytecode: Add AL2P decoding --- src/video_core/engines/shader_bytecode.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index e5b4eadea..766bb4f79 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -499,6 +499,11 @@ enum class SystemVariable : u64 { CircularQueueEntryAddressHigh = 0x63, }; +enum class PhysicalAttributeDirection : u64 { + Input = 0, + Output = 1, +}; + union Instruction { Instruction& operator=(const Instruction& instr) { value = instr.value; @@ -811,6 +816,12 @@ union Instruction { BitField<20, 24, s64> immediate_offset; } stg; + union { + BitField<32, 1, PhysicalAttributeDirection> direction; + BitField<47, 3, AttributeSize> size; + BitField<20, 11, u64> address; + } al2p; + union { BitField<0, 3, u64> pred0; BitField<3, 3, u64> pred3; @@ -1374,8 +1385,9 @@ public: ST_A, ST_L, ST_S, - LDG, // Load from global memory - STG, // Store in global memory + LDG, // Load from global memory + STG, // Store in global memory + AL2P, // Transforms attribute memory into physical memory TEX, TEX_B, // Texture Load Bindless TXQ, // Texture Query @@ -1646,6 +1658,7 @@ private: INST("1110111101010---", Id::ST_L, Type::Memory, "ST_L"), INST("1110111011010---", Id::LDG, Type::Memory, "LDG"), INST("1110111011011---", Id::STG, Type::Memory, "STG"), + INST("1110111110100---", Id::AL2P, Type::Memory, "AL2P"), INST("110000----111---", Id::TEX, Type::Texture, "TEX"), INST("1101111010111---", Id::TEX_B, Type::Texture, "TEX_B"), INST("1101111101001---", Id::TXQ, Type::Texture, "TXQ"), -- cgit v1.2.3 From bd81a03d9d4b3e7d69eb8377b13278944bc5ab0b Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 30 Apr 2019 00:09:51 -0300 Subject: gl_shader_decompiler: Declare all possible varyings on physical attribute usage --- src/video_core/engines/maxwell_3d.h | 1 + src/video_core/renderer_opengl/gl_device.cpp | 9 +++ src/video_core/renderer_opengl/gl_device.h | 14 +++- .../renderer_opengl/gl_shader_decompiler.cpp | 91 +++++++++++++++------- 4 files changed, 88 insertions(+), 27 deletions(-) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 85d309d9b..b1e640dd1 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -51,6 +51,7 @@ public: static constexpr std::size_t NumCBData = 16; static constexpr std::size_t NumVertexArrays = 32; static constexpr std::size_t NumVertexAttributes = 32; + static constexpr std::size_t NumVaryings = 31; static constexpr std::size_t NumTextureSamplers = 32; static constexpr std::size_t NumClipDistances = 8; static constexpr std::size_t MaxShaderProgram = 6; diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index b6d9e0ddb..38497678a 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -21,9 +21,18 @@ T GetInteger(GLenum pname) { Device::Device() { uniform_buffer_alignment = GetInteger(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT); + max_vertex_attributes = GetInteger(GL_MAX_VERTEX_ATTRIBS); + max_varyings = GetInteger(GL_MAX_VARYING_VECTORS); has_variable_aoffi = TestVariableAoffi(); } +Device::Device(std::nullptr_t) { + uniform_buffer_alignment = 0; + max_vertex_attributes = 16; + max_varyings = 15; + has_variable_aoffi = true; +} + bool Device::TestVariableAoffi() { const GLchar* AOFFI_TEST = R"(#version 430 core uniform sampler2D tex; diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index 78ff5ee58..de8490682 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h @@ -5,17 +5,27 @@ #pragma once #include +#include "common/common_types.h" namespace OpenGL { class Device { public: - Device(); + explicit Device(); + explicit Device(std::nullptr_t); std::size_t GetUniformBufferAlignment() const { return uniform_buffer_alignment; } + u32 GetMaxVertexAttributes() const { + return max_vertex_attributes; + } + + u32 GetMaxVaryings() const { + return max_varyings; + } + bool HasVariableAoffi() const { return has_variable_aoffi; } @@ -24,6 +34,8 @@ private: static bool TestVariableAoffi(); std::size_t uniform_buffer_alignment{}; + u32 max_vertex_attributes{}; + u32 max_varyings{}; bool has_variable_aoffi{}; }; diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 33c0edca9..8df91a4c6 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -316,55 +316,85 @@ private: } void DeclareInputAttributes() { + if (ir.HasPhysicalAttributes()) { + const u32 num_inputs{stage == ShaderStage::Vertex ? GetNumPhysicalAttributes() + : GetNumPhysicalVaryings()}; + for (u32 i = 0; i < num_inputs; ++i) { + constexpr auto generic_base{static_cast(Attribute::Index::Attribute_0)}; + const auto index{static_cast(generic_base + i)}; + DeclareInputAttribute(index); + } + code.AddNewLine(); + return; + } + const auto& attributes = ir.GetInputAttributes(); for (const auto index : attributes) { if (index < Attribute::Index::Attribute_0 || index > Attribute::Index::Attribute_31) { // Skip when it's not a generic attribute continue; } - - // TODO(bunnei): Use proper number of elements for these - u32 idx = static_cast(index) - static_cast(Attribute::Index::Attribute_0); - if (stage != ShaderStage::Vertex) { - // If inputs are varyings, add an offset - idx += GENERIC_VARYING_START_LOCATION; - } - - std::string attr = GetInputAttribute(index); - if (stage == ShaderStage::Geometry) { - attr = "gs_" + attr + "[]"; - } - std::string suffix; - if (stage == ShaderStage::Fragment) { - const auto input_mode = - header.ps.GetAttributeUse(idx - GENERIC_VARYING_START_LOCATION); - suffix = GetInputFlags(input_mode); - } - code.AddLine("layout (location = " + std::to_string(idx) + ") " + suffix + "in vec4 " + - attr + ';'); + DeclareInputAttribute(index); } if (!attributes.empty()) code.AddNewLine(); } + void DeclareInputAttribute(Attribute::Index index) { + const u32 generic_index{static_cast(index) - + static_cast(Attribute::Index::Attribute_0)}; + + std::string name{GetInputAttribute(index)}; + if (stage == ShaderStage::Geometry) { + name = "gs_" + name + "[]"; + } + std::string suffix; + if (stage == ShaderStage::Fragment) { + const auto input_mode{header.ps.GetAttributeUse(generic_index)}; + suffix = GetInputFlags(input_mode); + } + + u32 location = generic_index; + if (stage != ShaderStage::Vertex) { + // If inputs are varyings, add an offset + location += GENERIC_VARYING_START_LOCATION; + } + + code.AddLine("layout (location = " + std::to_string(location) + ") " + suffix + "in vec4 " + + name + ';'); + } + void DeclareOutputAttributes() { + if (ir.HasPhysicalAttributes()) { + for (u32 i = 0; i < GetNumPhysicalVaryings(); ++i) { + constexpr auto generic_base{static_cast(Attribute::Index::Attribute_0)}; + const auto index{static_cast(generic_base + i)}; + DeclareOutputAttribute(index); + } + code.AddNewLine(); + return; + } + const auto& attributes = ir.GetOutputAttributes(); for (const auto index : attributes) { if (index < Attribute::Index::Attribute_0 || index > Attribute::Index::Attribute_31) { // Skip when it's not a generic attribute continue; } - // TODO(bunnei): Use proper number of elements for these - const auto idx = static_cast(index) - - static_cast(Attribute::Index::Attribute_0) + - GENERIC_VARYING_START_LOCATION; - code.AddLine("layout (location = " + std::to_string(idx) + ") out vec4 " + - GetOutputAttribute(index) + ';'); + DeclareOutputAttribute(index); } if (!attributes.empty()) code.AddNewLine(); } + void DeclareOutputAttribute(Attribute::Index index) { + const auto location{static_cast(index) - + static_cast(Attribute::Index::Attribute_0) + + GENERIC_VARYING_START_LOCATION}; + code.AddLine("layout (location = " + std::to_string(location) + ") out vec4 " + + GetOutputAttribute(index) + ';'); + } + void DeclareConstantBuffers() { for (const auto& entry : ir.GetConstantBuffers()) { const auto [index, size] = entry; @@ -1650,6 +1680,15 @@ private: return name + '_' + std::to_string(index) + '_' + suffix; } + u32 GetNumPhysicalAttributes() const { + return std::min(device.GetMaxVertexAttributes(), Maxwell::NumVertexAttributes); + } + + u32 GetNumPhysicalVaryings() const { + return std::min(device.GetMaxVaryings() - GENERIC_VARYING_START_LOCATION, + Maxwell::NumVaryings); + } + const Device& device; const ShaderIR& ir; const ShaderStage stage; -- cgit v1.2.3 From 71aa9d08772eb07ccae7b141e032e6e7e57871a1 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 30 Apr 2019 18:12:30 -0300 Subject: shader_ir/memory: Implement physical input attributes --- src/video_core/engines/shader_bytecode.h | 4 ++++ src/video_core/shader/decode/memory.cpp | 9 ++++++--- src/video_core/shader/shader_ir.cpp | 5 +++++ src/video_core/shader/shader_ir.h | 20 +++++++++++++++++--- 4 files changed, 32 insertions(+), 6 deletions(-) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 766bb4f79..e4a9471b8 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -98,6 +98,10 @@ union Attribute { BitField<22, 2, u64> element; BitField<24, 6, Index> index; BitField<47, 3, AttributeSize> size; + + bool IsPhysical() const { + return element == 0 && static_cast(index.Value()) == 0; + } } fmt20; union { diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index 84db4d4dc..339692295 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp @@ -50,13 +50,16 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0, "Unaligned attribute loads are not supported"); + const Node buffer{GetRegister(instr.gpr39)}; + u64 next_element = instr.attribute.fmt20.element; auto next_index = static_cast(instr.attribute.fmt20.index.Value()); const auto LoadNextElement = [&](u32 reg_offset) { - const Node buffer = GetRegister(instr.gpr39); - const Node attribute = - GetInputAttribute(static_cast(next_index), next_element, buffer); + const Node attribute{instr.attribute.fmt20.IsPhysical() + ? GetPhysicalInputAttribute(instr.gpr8, buffer) + : GetInputAttribute(static_cast(next_index), + next_element, buffer)}; SetRegister(bb, instr.gpr0.Value() + reg_offset, attribute); diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 0307ae5b0..947a372a2 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -94,6 +94,11 @@ Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffe return StoreNode(AbufNode(index, static_cast(element), buffer)); } +Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_address, Node buffer) { + use_physical_attributes = true; + return StoreNode(AbufNode(GetRegister(physical_address), buffer)); +} + Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { if (index == Attribute::Index::ClipDistances0123 || index == Attribute::Index::ClipDistances4567) { diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 6aff64394..3a1164d4f 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -469,6 +469,9 @@ public: Node buffer = {}) : buffer{buffer}, index{index}, element{element} {} + explicit constexpr AbufNode(Node physical_address, Node buffer = {}) + : physical_address{physical_address}, buffer{buffer} {} + Tegra::Shader::Attribute::Index GetIndex() const { return index; } @@ -481,10 +484,19 @@ public: return buffer; } + bool IsPhysicalBuffer() const { + return physical_address != nullptr; + } + + Node GetPhysicalAddress() const { + return physical_address; + } + private: - const Node buffer; - const Tegra::Shader::Attribute::Index index; - const u32 element; + Node physical_address{}; + Node buffer{}; + Tegra::Shader::Attribute::Index index{}; + u32 element{}; }; /// Constant buffer node, usually mapped to uniform buffers in GLSL @@ -691,6 +703,8 @@ private: Node GetPredicate(bool immediate); /// Generates a node representing an input attribute. Keeps track of used attributes. Node GetInputAttribute(Tegra::Shader::Attribute::Index index, u64 element, Node buffer = {}); + /// Generates a node representing a physical input attribute. + Node GetPhysicalInputAttribute(Tegra::Shader::Register physical_address, Node buffer = {}); /// Generates a node representing an output attribute. Keeps track of used attributes. Node GetOutputAttribute(Tegra::Shader::Attribute::Index index, u64 element, Node buffer); /// Generates a node representing an internal flag -- cgit v1.2.3 From d4df803b2b6bab96321ca69651e4132545b433eb Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 2 May 2019 21:45:53 -0300 Subject: shader_ir/other: Implement IPA.IDX --- src/video_core/engines/shader_bytecode.h | 1 + src/video_core/shader/decode/other.cpp | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index e4a9471b8..7bbc556da 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -596,6 +596,7 @@ union Instruction { } alu; union { + BitField<38, 1, u64> idx; BitField<51, 1, u64> saturate; BitField<52, 2, IpaSampleMode> sample_mode; BitField<54, 2, IpaInterpMode> interp_mode; diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index 776bdb931..fa17c45b5 100644 --- a/src/video_core/shader/decode/other.cpp +++ b/src/video_core/shader/decode/other.cpp @@ -130,15 +130,18 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { break; } case OpCode::Id::IPA: { - const auto& attribute = instr.attribute.fmt28; + const bool is_physical = instr.ipa.idx && instr.gpr8.Value() != 0xff; + + const auto attribute = instr.attribute.fmt28; const Tegra::Shader::IpaMode input_mode{instr.ipa.interp_mode.Value(), instr.ipa.sample_mode.Value()}; - const Node attr = GetInputAttribute(attribute.index, attribute.element); - Node value = attr; + Node value = is_physical ? GetPhysicalInputAttribute(instr.gpr8) + : GetInputAttribute(attribute.index, attribute.element); const Tegra::Shader::Attribute::Index index = attribute.index.Value(); - if (index >= Tegra::Shader::Attribute::Index::Attribute_0 && - index <= Tegra::Shader::Attribute::Index::Attribute_31) { + const bool is_generic = index >= Tegra::Shader::Attribute::Index::Attribute_0 && + index <= Tegra::Shader::Attribute::Index::Attribute_31; + if (is_generic || is_physical) { // TODO(Blinkhawk): There are cases where a perspective attribute use PASS. // In theory by setting them as perspective, OpenGL does the perspective correction. // A way must figured to reverse the last step of it. -- cgit v1.2.3