2024-05-22 01:35:12 +03:00
|
|
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
#include "shader_recompiler/frontend/control_flow_graph.h"
|
|
|
|
#include "shader_recompiler/frontend/decode.h"
|
|
|
|
#include "shader_recompiler/frontend/structured_control_flow.h"
|
2024-05-29 01:28:34 +03:00
|
|
|
#include "shader_recompiler/ir/passes/ir_passes.h"
|
2024-05-22 01:35:12 +03:00
|
|
|
#include "shader_recompiler/ir/post_order.h"
|
2024-09-03 14:04:30 +03:00
|
|
|
#include "shader_recompiler/recompiler.h"
|
2024-05-22 01:35:12 +03:00
|
|
|
|
|
|
|
namespace Shader {
|
|
|
|
|
|
|
|
IR::BlockList GenerateBlocks(const IR::AbstractSyntaxList& syntax_list) {
|
|
|
|
size_t num_syntax_blocks{};
|
|
|
|
for (const auto& node : syntax_list) {
|
|
|
|
if (node.type == IR::AbstractSyntaxNode::Type::Block) {
|
|
|
|
++num_syntax_blocks;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
IR::BlockList blocks;
|
|
|
|
blocks.reserve(num_syntax_blocks);
|
|
|
|
u32 order_index{};
|
|
|
|
for (const auto& node : syntax_list) {
|
|
|
|
if (node.type == IR::AbstractSyntaxNode::Type::Block) {
|
|
|
|
blocks.push_back(node.data.block);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return blocks;
|
|
|
|
}
|
|
|
|
|
2024-09-03 14:04:30 +03:00
|
|
|
IR::Program TranslateProgram(std::span<const u32> code, Pools& pools, Info& info,
|
2024-12-14 02:56:17 -08:00
|
|
|
RuntimeInfo& runtime_info, const Profile& profile) {
|
2024-05-22 01:35:12 +03:00
|
|
|
// Ensure first instruction is expected.
|
|
|
|
constexpr u32 token_mov_vcchi = 0xBEEB03FF;
|
2024-11-21 19:24:13 +01:00
|
|
|
if (code[0] != token_mov_vcchi) {
|
|
|
|
LOG_WARNING(Render_Recompiler, "First instruction is not s_mov_b32 vcc_hi, #imm");
|
|
|
|
}
|
2024-05-22 01:35:12 +03:00
|
|
|
|
2024-09-03 14:04:30 +03:00
|
|
|
Gcn::GcnCodeSlice slice(code.data(), code.data() + code.size());
|
2024-05-22 01:35:12 +03:00
|
|
|
Gcn::GcnDecodeContext decoder;
|
|
|
|
|
|
|
|
// Decode and save instructions
|
2024-08-29 19:29:54 +03:00
|
|
|
IR::Program program{info};
|
2024-09-03 14:04:30 +03:00
|
|
|
program.ins_list.reserve(code.size());
|
2024-05-22 01:35:12 +03:00
|
|
|
while (!slice.atEnd()) {
|
|
|
|
program.ins_list.emplace_back(decoder.decodeInstruction(slice));
|
|
|
|
}
|
|
|
|
|
2024-09-03 14:04:30 +03:00
|
|
|
// Clear any previous pooled data.
|
|
|
|
pools.ReleaseContents();
|
|
|
|
|
2024-05-22 01:35:12 +03:00
|
|
|
// Create control flow graph
|
2024-08-08 15:02:10 +03:00
|
|
|
Common::ObjectPool<Gcn::Block> gcn_block_pool{64};
|
2024-05-22 01:35:12 +03:00
|
|
|
Gcn::CFG cfg{gcn_block_pool, program.ins_list};
|
|
|
|
|
|
|
|
// Structurize control flow graph and create program.
|
2024-09-03 14:04:30 +03:00
|
|
|
program.syntax_list = Shader::Gcn::BuildASL(pools.inst_pool, pools.block_pool, cfg,
|
|
|
|
program.info, runtime_info, profile);
|
2024-05-22 01:35:12 +03:00
|
|
|
program.blocks = GenerateBlocks(program.syntax_list);
|
|
|
|
program.post_order_blocks = Shader::IR::PostOrder(program.syntax_list.front());
|
|
|
|
|
|
|
|
// Run optimization passes
|
2025-04-28 00:04:16 -07:00
|
|
|
if (!profile.support_float64) {
|
|
|
|
Shader::Optimization::LowerFp64ToFp32(program);
|
|
|
|
}
|
2024-05-22 01:35:12 +03:00
|
|
|
Shader::Optimization::SsaRewritePass(program.post_order_blocks);
|
2025-03-23 00:35:42 +02:00
|
|
|
Shader::Optimization::ConstantPropagationPass(program.post_order_blocks);
|
2024-12-14 02:56:17 -08:00
|
|
|
Shader::Optimization::IdentityRemovalPass(program.blocks);
|
|
|
|
if (info.l_stage == LogicalStage::TessellationControl) {
|
|
|
|
Shader::Optimization::TessellationPreprocess(program, runtime_info);
|
|
|
|
Shader::Optimization::HullShaderTransform(program, runtime_info);
|
|
|
|
} else if (info.l_stage == LogicalStage::TessellationEval) {
|
|
|
|
Shader::Optimization::TessellationPreprocess(program, runtime_info);
|
|
|
|
Shader::Optimization::DomainShaderTransform(program, runtime_info);
|
|
|
|
}
|
2025-03-23 00:35:42 +02:00
|
|
|
Shader::Optimization::RingAccessElimination(program, runtime_info);
|
|
|
|
Shader::Optimization::ReadLaneEliminationPass(program);
|
2024-10-31 23:55:53 -07:00
|
|
|
Shader::Optimization::FlattenExtendedUserdataPass(program);
|
2024-08-24 22:51:47 +03:00
|
|
|
Shader::Optimization::ResourceTrackingPass(program);
|
2025-02-06 20:40:49 -08:00
|
|
|
Shader::Optimization::LowerBufferFormatToRaw(program);
|
2025-02-15 14:06:56 +02:00
|
|
|
Shader::Optimization::SharedMemoryToStoragePass(program, runtime_info, profile);
|
|
|
|
Shader::Optimization::SharedMemoryBarrierPass(program, runtime_info, profile);
|
2024-05-22 01:35:12 +03:00
|
|
|
Shader::Optimization::IdentityRemovalPass(program.blocks);
|
2024-06-06 02:24:30 +03:00
|
|
|
Shader::Optimization::DeadCodeEliminationPass(program);
|
2025-01-25 14:59:18 -08:00
|
|
|
Shader::Optimization::ConstantPropagationPass(program.post_order_blocks);
|
2024-05-25 15:33:15 +03:00
|
|
|
Shader::Optimization::CollectShaderInfoPass(program);
|
2024-05-22 01:35:12 +03:00
|
|
|
|
2024-05-25 15:33:15 +03:00
|
|
|
return program;
|
2024-05-22 01:35:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Shader
|