From 002ecbea190de16294d32449c3d2b61e57490dae Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 29 Apr 2019 23:28:28 -0300 Subject: shader_ir/memory: Emit AL2P IR --- src/video_core/shader/decode/memory.cpp | 17 +++++++++++++++++ src/video_core/shader/shader_ir.h | 5 +++++ 2 files changed, 22 insertions(+) (limited to 'src/video_core/shader') diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index ea1092db1..4aa74965f 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp @@ -12,6 +12,8 @@ #include "video_core/engines/shader_bytecode.h" #include "video_core/shader/shader_ir.h" +#pragma optimize("", off) + namespace VideoCommon::Shader { using Tegra::Shader::Attribute; @@ -239,6 +241,21 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { } break; } + case OpCode::Id::AL2P: { + // Ignore al2p.direction since we don't care about it. + + // Calculate emulation fake physical address. + const Node fixed_address{Immediate(static_cast(instr.al2p.address))}; + const Node reg{GetRegister(instr.gpr8)}; + const Node fake_address{Operation(OperationCode::IAdd, NO_PRECISE, reg, fixed_address)}; + + // Set the fake address to target register. + SetRegister(bb, instr.gpr0, fake_address); + + // Signal the shader IR to declare all possible attributes and varyings + use_physical_attributes = true; + break; + } default: UNIMPLEMENTED_MSG("Unhandled memory instruction: {}", opcode->get().GetName()); } diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 65f1e1de9..b157608b7 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -615,6 +615,10 @@ public: return static_cast(coverage_end * sizeof(u64)); } + bool HasPhysicalAttributes() const { + return use_physical_attributes; + } + const Tegra::Shader::Header& GetHeader() const { return header; } @@ -879,6 +883,7 @@ private: std::set used_samplers; std::array used_clip_distances{}; std::map used_global_memory; + bool use_physical_attributes = true; // Shader uses AL2P Tegra::Shader::Header header; }; -- cgit v1.2.3 From 06b363c9b5ccb64cfe7ac4d001ae35bff30828de Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 29 Apr 2019 23:37:09 -0300 Subject: shader: Remove unused AbufNode Ipa mode --- .../renderer_opengl/gl_shader_decompiler.cpp | 3 +-- .../renderer_vulkan/vk_shader_decompiler.cpp | 7 +++---- src/video_core/shader/decode/memory.cpp | 7 ++----- src/video_core/shader/decode/other.cpp | 2 +- src/video_core/shader/shader_ir.cpp | 10 +++------- src/video_core/shader/shader_ir.h | 20 ++++---------------- 6 files changed, 14 insertions(+), 35 deletions(-) (limited to 'src/video_core/shader') diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index ef1a1995f..33c0edca9 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -317,8 +317,7 @@ private: void DeclareInputAttributes() { const auto& attributes = ir.GetInputAttributes(); - for (const auto element : attributes) { - const Attribute::Index index = element.first; + 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; diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 23d9b10db..850085f35 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -194,8 +194,8 @@ public: for (const auto& sampler : ir.GetSamplers()) { entries.samplers.emplace_back(sampler); } - for (const auto& attr : ir.GetInputAttributes()) { - entries.attributes.insert(GetGenericAttributeLocation(attr.first)); + for (const auto& attribute : ir.GetInputAttributes()) { + entries.attributes.insert(GetGenericAttributeLocation(attribute)); } entries.clip_distances = ir.GetClipDistances(); entries.shader_length = ir.GetLength(); @@ -322,8 +322,7 @@ private: } void DeclareInputAttributes() { - for (const auto element : ir.GetInputAttributes()) { - const Attribute::Index index = element.first; + for (const auto index : ir.GetInputAttributes()) { if (!IsGenericAttribute(index)) { continue; } diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index 4aa74965f..84db4d4dc 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp @@ -50,16 +50,13 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0, "Unaligned attribute loads are not supported"); - Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Pass, - Tegra::Shader::IpaSampleMode::Default}; - 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, input_mode, buffer); + const Node attribute = + GetInputAttribute(static_cast(next_index), next_element, buffer); SetRegister(bb, instr.gpr0.Value() + reg_offset, attribute); diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index d750a2936..776bdb931 100644 --- a/src/video_core/shader/decode/other.cpp +++ b/src/video_core/shader/decode/other.cpp @@ -134,7 +134,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { const Tegra::Shader::IpaMode input_mode{instr.ipa.interp_mode.Value(), instr.ipa.sample_mode.Value()}; - const Node attr = GetInputAttribute(attribute.index, attribute.element, input_mode); + const Node attr = GetInputAttribute(attribute.index, attribute.element); Node value = attr; const Tegra::Shader::Attribute::Index index = attribute.index.Value(); if (index >= Tegra::Shader::Attribute::Index::Attribute_0 && diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index e4eb0dfd9..0307ae5b0 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -89,13 +89,9 @@ Node ShaderIR::GetPredicate(bool immediate) { return GetPredicate(static_cast(immediate ? Pred::UnusedIndex : Pred::NeverExecute)); } -Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, - const Tegra::Shader::IpaMode& input_mode, Node buffer) { - const auto [entry, is_new] = - used_input_attributes.emplace(std::make_pair(index, std::set{})); - entry->second.insert(input_mode); - - return StoreNode(AbufNode(index, static_cast(element), input_mode, buffer)); +Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) { + used_input_attributes.emplace(index); + return StoreNode(AbufNode(index, static_cast(element), buffer)); } Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index b157608b7..6aff64394 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -465,17 +465,9 @@ private: /// Attribute buffer memory (known as attributes or varyings in GLSL terms) class AbufNode final { public: - explicit constexpr AbufNode(Tegra::Shader::Attribute::Index index, u32 element, - const Tegra::Shader::IpaMode& input_mode, Node buffer = {}) - : input_mode{input_mode}, buffer{buffer}, index{index}, element{element} {} - explicit constexpr AbufNode(Tegra::Shader::Attribute::Index index, u32 element, Node buffer = {}) - : input_mode{}, buffer{buffer}, index{index}, element{element} {} - - Tegra::Shader::IpaMode GetInputMode() const { - return input_mode; - } + : buffer{buffer}, index{index}, element{element} {} Tegra::Shader::Attribute::Index GetIndex() const { return index; @@ -490,7 +482,6 @@ public: } private: - const Tegra::Shader::IpaMode input_mode; const Node buffer; const Tegra::Shader::Attribute::Index index; const u32 element; @@ -585,8 +576,7 @@ public: return used_predicates; } - const std::map>& - GetInputAttributes() const { + const std::set& GetInputAttributes() const { return used_input_attributes; } @@ -700,8 +690,7 @@ private: /// Generates a predicate node for an immediate true or false value 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, - const Tegra::Shader::IpaMode& input_mode, Node buffer = {}); + Node GetInputAttribute(Tegra::Shader::Attribute::Index index, u64 element, 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 @@ -876,8 +865,7 @@ private: std::set used_registers; std::set used_predicates; - std::map> - used_input_attributes; + std::set used_input_attributes; std::set used_output_attributes; std::map used_cbufs; std::set used_samplers; -- 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/shader') 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 c6f9e651b21aca5ec5afef1f217b39a3b85518b9 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 30 Apr 2019 19:36:18 -0300 Subject: gl_shader_decompiler: Implement GLSL physical attributes --- .../renderer_opengl/gl_shader_decompiler.cpp | 165 +++++++++++++-------- src/video_core/shader/shader_ir.h | 2 +- 2 files changed, 101 insertions(+), 66 deletions(-) (limited to 'src/video_core/shader') diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 1ad33107d..47bfa5538 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -165,6 +165,7 @@ public: DeclareConstantBuffers(); DeclareGlobalMemory(); DeclareSamplers(); + DeclarePhysicalAttributeReader(); code.AddLine("void execute_" + suffix + "() {"); ++code.scope; @@ -330,8 +331,7 @@ private: void DeclareInputAttributes() { if (ir.HasPhysicalAttributes()) { - const u32 num_inputs{stage == ShaderStage::Vertex ? GetNumPhysicalAttributes() - : GetNumPhysicalVaryings()}; + const u32 num_inputs{GetNumPhysicalInputAttributes()}; for (u32 i = 0; i < num_inputs; ++i) { DeclareInputAttribute(ToGenericAttribute(i)); } @@ -374,7 +374,7 @@ private: } void DeclareOutputAttributes() { - if (ir.HasPhysicalAttributes()) { + if (ir.HasPhysicalAttributes() && stage != ShaderStage::Fragment) { for (u32 i = 0; i < GetNumPhysicalVaryings(); ++i) { DeclareOutputAttribute(ToGenericAttribute(i)); } @@ -461,6 +461,31 @@ private: code.AddNewLine(); } + void DeclarePhysicalAttributeReader() { + if (!ir.HasPhysicalAttributes()) { + return; + } + code.AddLine("float readPhysicalAttribute(uint physical_address) {"); + ++code.scope; + code.AddLine("switch (physical_address) {"); + + // Just declare generic attributes for now. + const auto num_attributes{static_cast(GetNumPhysicalAttributes())}; + for (u32 index = 0; index < num_attributes; ++index) { + for (u32 element = 0; element < 4; ++element) { + code.AddLine(fmt::format("case 0x{:x}: return {};", 0x80 + index * 16 + element * 4, + ReadAttribute(ToGenericAttribute(index), element))); + } + } + + code.AddLine("default: return 0;"); + + code.AddLine('}'); + --code.scope; + code.AddLine('}'); + code.AddNewLine(); + } + void VisitBlock(const NodeBlock& bb) { for (const Node node : bb) { if (const std::string expr = Visit(node); !expr.empty()) { @@ -515,69 +540,12 @@ private: return value; } else if (const auto abuf = std::get_if(node)) { - const auto attribute = abuf->GetIndex(); - const auto element = abuf->GetElement(); - - const auto GeometryPass = [&](const std::string& name) { - if (stage == ShaderStage::Geometry && abuf->GetBuffer()) { - // TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games - // set an 0x80000000 index for those and the shader fails to build. Find out why - // this happens and what's its intent. - return "gs_" + name + "[ftou(" + Visit(abuf->GetBuffer()) + - ") % MAX_VERTEX_INPUT]"; - } - return name; - }; - - switch (attribute) { - case Attribute::Index::Position: - if (stage != ShaderStage::Fragment) { - return GeometryPass("position") + GetSwizzle(element); - } else { - return element == 3 ? "1.0f" : "gl_FragCoord" + GetSwizzle(element); - } - case Attribute::Index::PointCoord: - switch (element) { - case 0: - return "gl_PointCoord.x"; - case 1: - return "gl_PointCoord.y"; - case 2: - case 3: - return "0"; - } - UNREACHABLE(); - return "0"; - case Attribute::Index::TessCoordInstanceIDVertexID: - // TODO(Subv): Find out what the values are for the first two elements when inside a - // vertex shader, and what's the value of the fourth element when inside a Tess Eval - // shader. - ASSERT(stage == ShaderStage::Vertex); - switch (element) { - case 2: - // Config pack's first value is instance_id. - return "uintBitsToFloat(config_pack[0])"; - case 3: - return "uintBitsToFloat(gl_VertexID)"; - } - UNIMPLEMENTED_MSG("Unmanaged TessCoordInstanceIDVertexID element={}", element); - return "0"; - case Attribute::Index::FrontFacing: - // TODO(Subv): Find out what the values are for the other elements. - ASSERT(stage == ShaderStage::Fragment); - switch (element) { - case 3: - return "itof(gl_FrontFacing ? -1 : 0)"; - } - UNIMPLEMENTED_MSG("Unmanaged FrontFacing element={}", element); - return "0"; - default: - if (IsGenericAttribute(attribute)) { - return GeometryPass(GetInputAttribute(attribute)) + GetSwizzle(element); - } - break; + UNIMPLEMENTED_IF_MSG(abuf->IsPhysicalBuffer() && stage == ShaderStage::Geometry, + "Physical attributes in geometry shaders are not implemented"); + if (abuf->IsPhysicalBuffer()) { + return "readPhysicalAttribute(ftou(" + Visit(abuf->GetPhysicalAddress()) + "))"; } - UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast(attribute)); + return ReadAttribute(abuf->GetIndex(), abuf->GetElement(), abuf->GetBuffer()); } else if (const auto cbuf = std::get_if(node)) { const Node offset = cbuf->GetOffset(); @@ -629,6 +597,69 @@ private: return {}; } + std::string ReadAttribute(Attribute::Index attribute, u32 element, Node buffer = {}) { + const auto GeometryPass = [&](std::string name) { + if (stage == ShaderStage::Geometry && buffer) { + // TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games + // set an 0x80000000 index for those and the shader fails to build. Find out why + // this happens and what's its intent. + return "gs_" + std::move(name) + "[ftou(" + Visit(buffer) + ") % MAX_VERTEX_INPUT]"; + } + return name; + }; + + switch (attribute) { + case Attribute::Index::Position: + if (stage != ShaderStage::Fragment) { + return GeometryPass("position") + GetSwizzle(element); + } else { + return element == 3 ? "1.0f" : "gl_FragCoord" + GetSwizzle(element); + } + case Attribute::Index::PointCoord: + switch (element) { + case 0: + return "gl_PointCoord.x"; + case 1: + return "gl_PointCoord.y"; + case 2: + case 3: + return "0"; + } + UNREACHABLE(); + return "0"; + case Attribute::Index::TessCoordInstanceIDVertexID: + // TODO(Subv): Find out what the values are for the first two elements when inside a + // vertex shader, and what's the value of the fourth element when inside a Tess Eval + // shader. + ASSERT(stage == ShaderStage::Vertex); + switch (element) { + case 2: + // Config pack's first value is instance_id. + return "uintBitsToFloat(config_pack[0])"; + case 3: + return "uintBitsToFloat(gl_VertexID)"; + } + UNIMPLEMENTED_MSG("Unmanaged TessCoordInstanceIDVertexID element={}", element); + return "0"; + case Attribute::Index::FrontFacing: + // TODO(Subv): Find out what the values are for the other elements. + ASSERT(stage == ShaderStage::Fragment); + switch (element) { + case 3: + return "itof(gl_FrontFacing ? -1 : 0)"; + } + UNIMPLEMENTED_MSG("Unmanaged FrontFacing element={}", element); + return "0"; + default: + if (IsGenericAttribute(attribute)) { + return GeometryPass(GetInputAttribute(attribute)) + GetSwizzle(element); + } + break; + } + UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast(attribute)); + return "0"; + } + std::string ApplyPrecise(Operation operation, const std::string& value) { if (!IsPrecise(operation)) { return value; @@ -1677,6 +1708,10 @@ private: return name + '_' + std::to_string(index) + '_' + suffix; } + u32 GetNumPhysicalInputAttributes() const { + return stage == ShaderStage::Vertex ? GetNumPhysicalAttributes() : GetNumPhysicalVaryings(); + } + u32 GetNumPhysicalAttributes() const { return std::min(device.GetMaxVertexAttributes(), Maxwell::NumVertexAttributes); } diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 3a1164d4f..a4bb0c41c 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -885,7 +885,7 @@ private: std::set used_samplers; std::array used_clip_distances{}; std::map used_global_memory; - bool use_physical_attributes = true; // Shader uses AL2P + bool use_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes Tegra::Shader::Header header; }; -- cgit v1.2.3 From fe700e1856fa078ba0fc93ced8576f5023f3146a Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 30 Apr 2019 19:46:49 -0300 Subject: shader: Add physical attributes commentaries --- src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 2 ++ src/video_core/shader/decode/memory.cpp | 2 +- src/video_core/shader/shader_ir.cpp | 2 +- src/video_core/shader/shader_ir.h | 6 ++++-- 4 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src/video_core/shader') diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 47bfa5538..52552333f 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -895,6 +895,8 @@ private: target = GetRegister(gpr->GetIndex()); } else if (const auto abuf = std::get_if(dest)) { + UNIMPLEMENTED_IF(abuf->IsPhysicalBuffer()); + target = [&]() -> std::string { switch (const auto attribute = abuf->GetIndex(); abuf->GetIndex()) { case Attribute::Index::Position: diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index 339692295..c4f68f8ab 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp @@ -253,7 +253,7 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { SetRegister(bb, instr.gpr0, fake_address); // Signal the shader IR to declare all possible attributes and varyings - use_physical_attributes = true; + uses_physical_attributes = true; break; } default: diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 947a372a2..691d095c8 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -95,7 +95,7 @@ Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffe } Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_address, Node buffer) { - use_physical_attributes = true; + uses_physical_attributes = true; return StoreNode(AbufNode(GetRegister(physical_address), buffer)); } diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index a4bb0c41c..7e54f7e74 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -465,10 +465,12 @@ private: /// Attribute buffer memory (known as attributes or varyings in GLSL terms) class AbufNode final { public: + // Initialize for standard attributes (index is explicit). explicit constexpr AbufNode(Tegra::Shader::Attribute::Index index, u32 element, Node buffer = {}) : buffer{buffer}, index{index}, element{element} {} + // Initialize for physical attributes (index is a variable value). explicit constexpr AbufNode(Node physical_address, Node buffer = {}) : physical_address{physical_address}, buffer{buffer} {} @@ -618,7 +620,7 @@ public: } bool HasPhysicalAttributes() const { - return use_physical_attributes; + return uses_physical_attributes; } const Tegra::Shader::Header& GetHeader() const { @@ -885,7 +887,7 @@ private: std::set used_samplers; std::array used_clip_distances{}; std::map used_global_memory; - bool use_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes + bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes Tegra::Shader::Header header; }; -- cgit v1.2.3 From 28bffb1ffa2585429d63c6dab8584b8e46179696 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 30 Apr 2019 20:11:41 -0300 Subject: shader_ir/memory: Assert on non-32 bits ALD.PHYS --- src/video_core/shader/decode/memory.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/video_core/shader') diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index c4f68f8ab..6a992c543 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp @@ -49,6 +49,9 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { "Indirect attribute loads are not supported"); UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0, "Unaligned attribute loads are not supported"); + UNIMPLEMENTED_IF_MSG(instr.attribute.fmt20.IsPhysical() && + instr.attribute.fmt20.size != Tegra::Shader::AttributeSize::Word, + "Non-32 bits PHYS reads are not implemented"); const Node buffer{GetRegister(instr.gpr39)}; -- 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/shader') 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