summaryrefslogtreecommitdiff
path: root/src/video_core/shader
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/shader')
-rw-r--r--src/video_core/shader/decode/memory.cpp82
-rw-r--r--src/video_core/shader/shader_ir.h6
2 files changed, 57 insertions, 31 deletions
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index 165c2b41b..e6a010a7d 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -146,12 +146,25 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
146 } 146 }
147 break; 147 break;
148 } 148 }
149 case OpCode::Id::LD:
149 case OpCode::Id::LDG: { 150 case OpCode::Id::LDG: {
151 const auto type = [instr, &opcode]() -> Tegra::Shader::UniformType {
152 switch (opcode->get().GetId()) {
153 case OpCode::Id::LD:
154 UNIMPLEMENTED_IF_MSG(!instr.generic.extended, "Unextended LD is not implemented");
155 return instr.generic.type;
156 case OpCode::Id::LDG:
157 return instr.ldg.type;
158 default:
159 UNREACHABLE();
160 return {};
161 }
162 }();
163
150 const auto [real_address_base, base_address, descriptor] = 164 const auto [real_address_base, base_address, descriptor] =
151 TrackAndGetGlobalMemory(bb, GetRegister(instr.gpr8), 165 TrackAndGetGlobalMemory(bb, instr, false);
152 static_cast<u32>(instr.ldg.immediate_offset.Value()), false);
153 166
154 const u32 count = GetUniformTypeElementsCount(instr.ldg.type); 167 const u32 count = GetUniformTypeElementsCount(type);
155 for (u32 i = 0; i < count; ++i) { 168 for (u32 i = 0; i < count; ++i) {
156 const Node it_offset = Immediate(i * 4); 169 const Node it_offset = Immediate(i * 4);
157 const Node real_address = 170 const Node real_address =
@@ -165,28 +178,6 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
165 } 178 }
166 break; 179 break;
167 } 180 }
168 case OpCode::Id::STG: {
169 const auto [real_address_base, base_address, descriptor] =
170 TrackAndGetGlobalMemory(bb, GetRegister(instr.gpr8),
171 static_cast<u32>(instr.stg.immediate_offset.Value()), true);
172
173 // Encode in temporary registers like this: real_base_address, {registers_to_be_written...}
174 SetTemporal(bb, 0, real_address_base);
175
176 const u32 count = GetUniformTypeElementsCount(instr.stg.type);
177 for (u32 i = 0; i < count; ++i) {
178 SetTemporal(bb, i + 1, GetRegister(instr.gpr0.Value() + i));
179 }
180 for (u32 i = 0; i < count; ++i) {
181 const Node it_offset = Immediate(i * 4);
182 const Node real_address =
183 Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset);
184 const Node gmem = StoreNode(GmemNode(real_address, base_address, descriptor));
185
186 bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporal(i + 1)));
187 }
188 break;
189 }
190 case OpCode::Id::ST_A: { 181 case OpCode::Id::ST_A: {
191 UNIMPLEMENTED_IF_MSG(instr.gpr8.Value() != Register::ZeroIndex, 182 UNIMPLEMENTED_IF_MSG(instr.gpr8.Value() != Register::ZeroIndex,
192 "Indirect attribute loads are not supported"); 183 "Indirect attribute loads are not supported");
@@ -242,6 +233,41 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
242 } 233 }
243 break; 234 break;
244 } 235 }
236 case OpCode::Id::ST:
237 case OpCode::Id::STG: {
238 const auto type = [instr, &opcode]() -> Tegra::Shader::UniformType {
239 switch (opcode->get().GetId()) {
240 case OpCode::Id::ST:
241 UNIMPLEMENTED_IF_MSG(!instr.generic.extended, "Unextended ST is not implemented");
242 return instr.generic.type;
243 case OpCode::Id::STG:
244 return instr.stg.type;
245 default:
246 UNREACHABLE();
247 return {};
248 }
249 }();
250
251 const auto [real_address_base, base_address, descriptor] =
252 TrackAndGetGlobalMemory(bb, instr, true);
253
254 // Encode in temporary registers like this: real_base_address, {registers_to_be_written...}
255 SetTemporal(bb, 0, real_address_base);
256
257 const u32 count = GetUniformTypeElementsCount(type);
258 for (u32 i = 0; i < count; ++i) {
259 SetTemporal(bb, i + 1, GetRegister(instr.gpr0.Value() + i));
260 }
261 for (u32 i = 0; i < count; ++i) {
262 const Node it_offset = Immediate(i * 4);
263 const Node real_address =
264 Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset);
265 const Node gmem = StoreNode(GmemNode(real_address, base_address, descriptor));
266
267 bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporal(i + 1)));
268 }
269 break;
270 }
245 case OpCode::Id::AL2P: { 271 case OpCode::Id::AL2P: {
246 // Ignore al2p.direction since we don't care about it. 272 // Ignore al2p.direction since we don't care about it.
247 273
@@ -265,9 +291,11 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
265} 291}
266 292
267std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeBlock& bb, 293std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeBlock& bb,
268 Node addr_register, 294 Instruction instr,
269 u32 immediate_offset,
270 bool is_write) { 295 bool is_write) {
296 const auto addr_register{GetRegister(instr.gmem.gpr)};
297 const auto immediate_offset{static_cast<u32>(instr.gmem.offset)};
298
271 const Node base_address{ 299 const Node base_address{
272 TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()))}; 300 TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()))};
273 const auto cbuf = std::get_if<CbufNode>(base_address); 301 const auto cbuf = std::get_if<CbufNode>(base_address);
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 34d183ec7..35f72bddb 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -818,10 +818,8 @@ private:
818 std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, 818 std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code,
819 s64 cursor) const; 819 s64 cursor) const;
820 820
821 std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory(NodeBlock& bb, 821 std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory(
822 Node addr_register, 822 NodeBlock& bb, Tegra::Shader::Instruction instr, bool is_write);
823 u32 immediate_offset,
824 bool is_write);
825 823
826 template <typename... T> 824 template <typename... T>
827 Node Operation(OperationCode code, const T*... operands) { 825 Node Operation(OperationCode code, const T*... operands) {