summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler')
-rw-r--r--src/shader_recompiler/CMakeLists.txt14
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp4
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp4
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.cpp5
-rw-r--r--src/shader_recompiler/frontend/ir/value.h4
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate_program.cpp47
-rw-r--r--src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp98
-rw-r--r--src/shader_recompiler/runtime_info.h2
-rw-r--r--src/shader_recompiler/shader_info.h3
9 files changed, 44 insertions, 137 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt
index af8e51fe8..bcdd60db9 100644
--- a/src/shader_recompiler/CMakeLists.txt
+++ b/src/shader_recompiler/CMakeLists.txt
@@ -241,24 +241,14 @@ target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit)
if (MSVC)
target_compile_options(shader_recompiler PRIVATE
/W4
- /WX
- /we4018 # 'expression' : signed/unsigned mismatch
- /we4244 # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point)
- /we4245 # 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
+
+ /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
- /we4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data
- /we4305 # 'context' : truncation from 'type1' to 'type2'
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
- /we4826 # Conversion from 'type1' to 'type2' is sign-extended. This may cause unexpected runtime behavior.
)
else()
target_compile_options(shader_recompiler PRIVATE
- -Werror
-Werror=conversion
- -Werror=ignored-qualifiers
- $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
- $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
- -Werror=unused-variable
# Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6.
# And this in turns limits the size of a std::array.
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
index 7094d8e42..1f4ffdd62 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
@@ -5,10 +5,6 @@
#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
#include "shader_recompiler/frontend/ir/value.h"
-#ifdef _MSC_VER
-#pragma warning(disable : 4100)
-#endif
-
namespace Shader::Backend::GLASM {
#define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__)
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
index b03a8ba1e..9f1ed95a4 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
@@ -7,10 +7,6 @@
#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
#include "shader_recompiler/frontend/ir/value.h"
-#ifdef _MSC_VER
-#pragma warning(disable : 4100)
-#endif
-
namespace Shader::Backend::GLSL {
void EmitGetRegister(EmitContext& ctx) {
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp
index 468782eb1..84417980b 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.cpp
+++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp
@@ -325,11 +325,6 @@ void Inst::AddPhiOperand(Block* predecessor, const Value& value) {
phi_args.emplace_back(predecessor, value);
}
-void Inst::ErasePhiOperand(size_t index) {
- const auto operand_it{phi_args.begin() + static_cast<ptrdiff_t>(index)};
- phi_args.erase(operand_it);
-}
-
void Inst::OrderPhiArgs() {
if (op != Opcode::Phi) {
throw LogicError("{} is not a Phi instruction", op);
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h
index 1a2e4ccb6..6a673ca05 100644
--- a/src/shader_recompiler/frontend/ir/value.h
+++ b/src/shader_recompiler/frontend/ir/value.h
@@ -178,13 +178,9 @@ public:
/// Get a pointer to the block of a phi argument.
[[nodiscard]] Block* PhiBlock(size_t index) const;
-
/// Add phi operand to a phi instruction.
void AddPhiOperand(Block* predecessor, const Value& value);
- // Erase the phi operand at the given index.
- void ErasePhiOperand(size_t index);
-
/// Orders the Phi arguments from farthest away to nearest.
void OrderPhiArgs();
diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
index 77efb4f57..b58741d4d 100644
--- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
@@ -137,28 +137,35 @@ bool IsLegacyAttribute(IR::Attribute attribute) {
}
std::map<IR::Attribute, IR::Attribute> GenerateLegacyToGenericMappings(
- const VaryingState& state, std::queue<IR::Attribute> ununsed_generics) {
+ const VaryingState& state, std::queue<IR::Attribute> unused_generics,
+ const std::map<IR::Attribute, IR::Attribute>& previous_stage_mapping) {
std::map<IR::Attribute, IR::Attribute> mapping;
+ auto update_mapping = [&mapping, &unused_generics, previous_stage_mapping](IR::Attribute attr,
+ size_t count) {
+ if (previous_stage_mapping.find(attr) != previous_stage_mapping.end()) {
+ for (size_t i = 0; i < count; ++i) {
+ mapping.insert({attr + i, previous_stage_mapping.at(attr + i)});
+ }
+ } else {
+ for (size_t i = 0; i < count; ++i) {
+ mapping.insert({attr + i, unused_generics.front() + i});
+ }
+ unused_generics.pop();
+ }
+ };
for (size_t index = 0; index < 4; ++index) {
auto attr = IR::Attribute::ColorFrontDiffuseR + index * 4;
if (state.AnyComponent(attr)) {
- for (size_t i = 0; i < 4; ++i) {
- mapping.insert({attr + i, ununsed_generics.front() + i});
- }
- ununsed_generics.pop();
+ update_mapping(attr, 4);
}
}
if (state[IR::Attribute::FogCoordinate]) {
- mapping.insert({IR::Attribute::FogCoordinate, ununsed_generics.front()});
- ununsed_generics.pop();
+ update_mapping(IR::Attribute::FogCoordinate, 1);
}
for (size_t index = 0; index < IR::NUM_FIXEDFNCTEXTURE; ++index) {
auto attr = IR::Attribute::FixedFncTexture0S + index * 4;
if (state.AnyComponent(attr)) {
- for (size_t i = 0; i < 4; ++i) {
- mapping.insert({attr + i, ununsed_generics.front() + i});
- }
- ununsed_generics.pop();
+ update_mapping(attr, 4);
}
}
return mapping;
@@ -265,21 +272,22 @@ IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b
void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& runtime_info) {
auto& stores = program.info.stores;
if (stores.Legacy()) {
- std::queue<IR::Attribute> ununsed_output_generics{};
+ std::queue<IR::Attribute> unused_output_generics{};
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
if (!stores.Generic(index)) {
- ununsed_output_generics.push(IR::Attribute::Generic0X + index * 4);
+ unused_output_generics.push(IR::Attribute::Generic0X + index * 4);
}
}
- auto mappings = GenerateLegacyToGenericMappings(stores, ununsed_output_generics);
+ program.info.legacy_stores_mapping =
+ GenerateLegacyToGenericMappings(stores, unused_output_generics, {});
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
switch (inst.GetOpcode()) {
case IR::Opcode::SetAttribute: {
const auto attr = inst.Arg(0).Attribute();
if (IsLegacyAttribute(attr)) {
- stores.Set(mappings[attr], true);
- inst.SetArg(0, Shader::IR::Value(mappings[attr]));
+ stores.Set(program.info.legacy_stores_mapping[attr], true);
+ inst.SetArg(0, Shader::IR::Value(program.info.legacy_stores_mapping[attr]));
}
break;
}
@@ -292,15 +300,16 @@ void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& run
auto& loads = program.info.loads;
if (loads.Legacy()) {
- std::queue<IR::Attribute> ununsed_input_generics{};
+ std::queue<IR::Attribute> unused_input_generics{};
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
const AttributeType input_type{runtime_info.generic_input_types[index]};
if (!runtime_info.previous_stage_stores.Generic(index) || !loads.Generic(index) ||
input_type == AttributeType::Disabled) {
- ununsed_input_generics.push(IR::Attribute::Generic0X + index * 4);
+ unused_input_generics.push(IR::Attribute::Generic0X + index * 4);
}
}
- auto mappings = GenerateLegacyToGenericMappings(loads, ununsed_input_generics);
+ auto mappings = GenerateLegacyToGenericMappings(
+ loads, unused_input_generics, runtime_info.previous_stage_legacy_stores_mapping);
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
switch (inst.GetOpcode()) {
diff --git a/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp b/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp
index 9a7d47344..1bd8afd6f 100644
--- a/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp
+++ b/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp
@@ -1,104 +1,24 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <algorithm>
-
-#include <boost/container/small_vector.hpp>
-
#include "shader_recompiler/frontend/ir/basic_block.h"
#include "shader_recompiler/frontend/ir/value.h"
#include "shader_recompiler/ir_opt/passes.h"
namespace Shader::Optimization {
-namespace {
-template <bool TEST_USES>
-void DeadInstElimination(IR::Block* const block) {
+
+void DeadCodeEliminationPass(IR::Program& program) {
// We iterate over the instructions in reverse order.
// This is because removing an instruction reduces the number of uses for earlier instructions.
- auto it{block->end()};
- while (it != block->begin()) {
- --it;
- if constexpr (TEST_USES) {
- if (it->HasUses() || it->MayHaveSideEffects()) {
- continue;
- }
- }
- it->Invalidate();
- it = block->Instructions().erase(it);
- }
-}
-
-void DeletedPhiArgElimination(IR::Program& program, std::span<const IR::Block*> dead_blocks) {
- for (IR::Block* const block : program.blocks) {
- for (IR::Inst& phi : *block) {
- if (!IR::IsPhi(phi)) {
- continue;
- }
- for (size_t i = 0; i < phi.NumArgs(); ++i) {
- if (std::ranges::find(dead_blocks, phi.PhiBlock(i)) == dead_blocks.end()) {
- continue;
- }
- // Phi operand at this index is an unreachable block
- phi.ErasePhiOperand(i);
- --i;
- }
- }
- }
-}
-
-void DeadBranchElimination(IR::Program& program) {
- boost::container::small_vector<const IR::Block*, 3> dead_blocks;
- const auto begin_it{program.syntax_list.begin()};
- for (auto node_it = begin_it; node_it != program.syntax_list.end(); ++node_it) {
- if (node_it->type != IR::AbstractSyntaxNode::Type::If) {
- continue;
- }
- IR::Inst* const cond_ref{node_it->data.if_node.cond.Inst()};
- const IR::U1 cond{cond_ref->Arg(0)};
- if (!cond.IsImmediate()) {
- continue;
- }
- if (cond.U1()) {
- continue;
- }
- // False immediate condition. Remove condition ref, erase the entire branch.
- cond_ref->Invalidate();
- // Account for nested if-statements within the if(false) branch
- u32 nested_ifs{1u};
- while (node_it->type != IR::AbstractSyntaxNode::Type::EndIf || nested_ifs > 0) {
- node_it = program.syntax_list.erase(node_it);
- switch (node_it->type) {
- case IR::AbstractSyntaxNode::Type::If:
- ++nested_ifs;
- break;
- case IR::AbstractSyntaxNode::Type::EndIf:
- --nested_ifs;
- break;
- case IR::AbstractSyntaxNode::Type::Block: {
- IR::Block* const block{node_it->data.block};
- DeadInstElimination<false>(block);
- dead_blocks.push_back(block);
- break;
- }
- default:
- break;
+ for (IR::Block* const block : program.post_order_blocks) {
+ auto it{block->end()};
+ while (it != block->begin()) {
+ --it;
+ if (!it->HasUses() && !it->MayHaveSideEffects()) {
+ it->Invalidate();
+ it = block->Instructions().erase(it);
}
}
- // Erase EndIf node of the if(false) branch
- node_it = program.syntax_list.erase(node_it);
- // Account for loop increment
- --node_it;
- }
- if (!dead_blocks.empty()) {
- DeletedPhiArgElimination(program, std::span(dead_blocks.data(), dead_blocks.size()));
- }
-}
-} // namespace
-
-void DeadCodeEliminationPass(IR::Program& program) {
- DeadBranchElimination(program);
- for (IR::Block* const block : program.post_order_blocks) {
- DeadInstElimination<true>(block);
}
}
diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h
index dcb5ab158..549b81ef7 100644
--- a/src/shader_recompiler/runtime_info.h
+++ b/src/shader_recompiler/runtime_info.h
@@ -4,6 +4,7 @@
#pragma once
#include <array>
+#include <map>
#include <optional>
#include <vector>
@@ -60,6 +61,7 @@ struct TransformFeedbackVarying {
struct RuntimeInfo {
std::array<AttributeType, 32> generic_input_types{};
VaryingState previous_stage_stores;
+ std::map<IR::Attribute, IR::Attribute> previous_stage_legacy_stores_mapping;
bool convert_depth_mode{};
bool force_early_z{};
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h
index cc596da4f..81097bf1a 100644
--- a/src/shader_recompiler/shader_info.h
+++ b/src/shader_recompiler/shader_info.h
@@ -5,6 +5,7 @@
#include <array>
#include <bitset>
+#include <map>
#include "common/common_types.h"
#include "shader_recompiler/frontend/ir/type.h"
@@ -127,6 +128,8 @@ struct Info {
VaryingState stores;
VaryingState passthrough;
+ std::map<IR::Attribute, IR::Attribute> legacy_stores_mapping;
+
bool loads_indexed_attributes{};
std::array<bool, 8> stores_frag_color{};