1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include "common/container/unordered_map.h"
#include "common/common_types.h"
#include "shader_recompiler/program_header.h"
#include "shader_recompiler/shader_info.h"
#include "shader_recompiler/stage.h"
#include "shader_recompiler/frontend/ir/value.h"
namespace Shader::IR {
class Inst;
}
namespace Shader {
struct CbufWordKey {
u32 index;
u32 offset;
constexpr bool operator==(const CbufWordKey& o) const noexcept {
return index == o.index && offset == o.offset;
}
};
struct CbufWordKeyHash {
constexpr size_t operator()(const CbufWordKey& k) const noexcept {
return (size_t(k.index) << 32) ^ k.offset;
}
};
struct HandleKey {
u32 index, offset, shift_left;
u32 sec_index, sec_offset, sec_shift_left;
u32 count;
bool has_secondary;
constexpr bool operator==(const HandleKey& o) const noexcept {
return std::tie(index, offset, shift_left, sec_index, sec_offset, sec_shift_left, count, has_secondary)
== std::tie(o.index, o.offset, o.shift_left, o.sec_index, o.sec_offset, o.sec_shift_left, o.count, o.has_secondary);
}
};
struct HandleKeyHash {
constexpr size_t operator()(const HandleKey& k) const noexcept {
size_t h = (size_t(k.index) << 32) ^ k.offset;
h ^= (size_t(k.shift_left) << 1);
h ^= (size_t(k.sec_index) << 33) ^ (size_t(k.sec_offset) << 2);
h ^= (size_t(k.sec_shift_left) << 3);
h ^= (size_t(k.count) << 7);
return h ^ (k.has_secondary ? 0x9e3779b97f4a7c15ULL : 0ULL);
}
};
struct ConstBufferAddr {
u32 index;
u32 offset;
u32 shift_left;
u32 secondary_index;
u32 secondary_offset;
u32 secondary_shift_left;
IR::U32 dynamic_offset;
u32 count;
bool has_secondary;
u32 handle_program{~0U}; ///< index in Info::handle_programs for a handle computed per draw
};
class Environment {
public:
virtual ~Environment() = default;
[[nodiscard]] virtual u64 ReadInstruction(u32 address) = 0;
[[nodiscard]] virtual u32 TranslateProgramAddress(u32 address) const { return address; }
[[nodiscard]] virtual u32 ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) = 0;
[[nodiscard]] virtual TextureType ReadTextureType(u32 raw_handle) = 0;
[[nodiscard]] virtual TexturePixelFormat ReadTexturePixelFormat(u32 raw_handle) = 0;
[[nodiscard]] virtual bool IsTexturePixelFormatInteger(u32 raw_handle) = 0;
[[nodiscard]] virtual u32 ReadViewportTransformState() = 0;
[[nodiscard]] virtual u32 TextureBoundBuffer() const = 0;
[[nodiscard]] virtual u32 LocalMemorySize() const = 0;
[[nodiscard]] virtual u32 SharedMemorySize() const = 0;
[[nodiscard]] virtual std::array<u32, 3> WorkgroupSize() const = 0;
[[nodiscard]] virtual bool HasHLEMacroState() const = 0;
[[nodiscard]] virtual std::optional<ReplaceConstant> GetReplaceConstBuffer(u32 bank,
u32 offset) = 0;
virtual void Dump(u64 pipeline_hash, u64 shader_hash) = 0;
[[nodiscard]] const ProgramHeader& SPH() const noexcept {
return sph;
}
[[nodiscard]] const std::array<u32, 8>& GpPassthroughMask() const noexcept {
return gp_passthrough_mask;
}
[[nodiscard]] Stage ShaderStage() const noexcept {
return stage;
}
[[nodiscard]] u32 StartAddress() const noexcept {
return start_address;
}
[[nodiscard]] bool IsProprietaryDriver() const noexcept {
return is_proprietary_driver;
}
/// Task and mesh programs: SET_MESH_SHADER_A, SET_MESH_SHADER_B and SET_MESH_INIT_SHADER.
[[nodiscard]] const std::array<u32, 3>& MeshRegisters() const noexcept {
return mesh_registers;
}
/// Mesh programs: the header of the pass-through geometry program bound with them, whose
/// output map lists the per-primitive outputs.
[[nodiscard]] const ProgramHeader& MeshPrimitiveHeader() const noexcept {
return mesh_primitive_header;
}
protected:
ProgramHeader sph{};
std::array<u32, 8> gp_passthrough_mask{};
std::array<u32, 3> mesh_registers{};
ProgramHeader mesh_primitive_header{};
Stage stage{};
u32 start_address{};
bool is_proprietary_driver{};
public:
::Common::unordered_map<CbufWordKey, u32, CbufWordKeyHash> cbuf_word_cache;
::Common::unordered_map<HandleKey, u32, HandleKeyHash> handle_cache;
::Common::unordered_map<const IR::Inst*, ConstBufferAddr> track_cache;
};
} // namespace Shader
|