summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/ir_opt/layer_pass.cpp
diff options
context:
space:
mode:
authorGravatar Liam2022-11-30 17:16:00 -0500
committerGravatar Liam2022-12-01 09:51:27 -0500
commit3ef006b5abbe78bb2ae423a7cab74d7da2f8bc08 (patch)
treebf0c9ed637dc39faea655fb836b7a48a9f5d28ee /src/shader_recompiler/ir_opt/layer_pass.cpp
parentMerge pull request #9308 from lat9nq/from-scratch (diff)
downloadyuzu-3ef006b5abbe78bb2ae423a7cab74d7da2f8bc08.tar.gz
yuzu-3ef006b5abbe78bb2ae423a7cab74d7da2f8bc08.tar.xz
yuzu-3ef006b5abbe78bb2ae423a7cab74d7da2f8bc08.zip
shader_recompiler: add gl_Layer translation GS for older hardware
Diffstat (limited to 'src/shader_recompiler/ir_opt/layer_pass.cpp')
-rw-r--r--src/shader_recompiler/ir_opt/layer_pass.cpp68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/shader_recompiler/ir_opt/layer_pass.cpp b/src/shader_recompiler/ir_opt/layer_pass.cpp
new file mode 100644
index 000000000..4574f7cf2
--- /dev/null
+++ b/src/shader_recompiler/ir_opt/layer_pass.cpp
@@ -0,0 +1,68 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <algorithm>
5#include <bit>
6#include <optional>
7
8#include <boost/container/small_vector.hpp>
9
10#include "shader_recompiler/environment.h"
11#include "shader_recompiler/frontend/ir/basic_block.h"
12#include "shader_recompiler/frontend/ir/breadth_first_search.h"
13#include "shader_recompiler/frontend/ir/ir_emitter.h"
14#include "shader_recompiler/host_translate_info.h"
15#include "shader_recompiler/ir_opt/passes.h"
16#include "shader_recompiler/shader_info.h"
17
18namespace Shader::Optimization {
19
20static IR::Attribute EmulatedLayerAttribute(VaryingState& stores) {
21 for (u32 i = 0; i < 32; i++) {
22 if (!stores.Generic(i)) {
23 return IR::Attribute::Generic0X + (i * 4);
24 }
25 }
26 return IR::Attribute::Layer;
27}
28
29static bool PermittedProgramStage(Stage stage) {
30 switch (stage) {
31 case Stage::VertexA:
32 case Stage::VertexB:
33 case Stage::TessellationControl:
34 case Stage::TessellationEval:
35 return true;
36 default:
37 return false;
38 }
39}
40
41void LayerPass(IR::Program& program, const HostTranslateInfo& host_info) {
42 if (host_info.support_viewport_index_layer || !PermittedProgramStage(program.stage)) {
43 return;
44 }
45
46 const auto end{program.post_order_blocks.end()};
47 const auto layer_attribute = EmulatedLayerAttribute(program.info.stores);
48 bool requires_layer_emulation = false;
49
50 for (auto block = program.post_order_blocks.begin(); block != end; ++block) {
51 for (IR::Inst& inst : (*block)->Instructions()) {
52 if (inst.GetOpcode() == IR::Opcode::SetAttribute &&
53 inst.Arg(0).Attribute() == IR::Attribute::Layer) {
54 requires_layer_emulation = true;
55 inst.SetArg(0, IR::Value{layer_attribute});
56 }
57 }
58 }
59
60 if (requires_layer_emulation) {
61 program.info.requires_layer_emulation = true;
62 program.info.emulated_layer = layer_attribute;
63 program.info.stores.Set(IR::Attribute::Layer, false);
64 program.info.stores.Set(layer_attribute, true);
65 }
66}
67
68} // namespace Shader::Optimization