Browse Source
Merge pull request #1960 from ReinUsesLisp/shader-ir-ldg
Merge pull request #1960 from ReinUsesLisp/shader-ir-ldg
video_core: Implement LDG through heuristics based on IRnce_cpp
committed by
GitHub
13 changed files with 380 additions and 14 deletions
-
1src/video_core/CMakeLists.txt
-
8src/video_core/engines/shader_bytecode.h
-
70src/video_core/renderer_opengl/gl_global_cache.cpp
-
18src/video_core/renderer_opengl/gl_global_cache.h
-
22src/video_core/renderer_opengl/gl_rasterizer.cpp
-
10src/video_core/renderer_opengl/gl_rasterizer.h
-
18src/video_core/renderer_opengl/gl_shader_cache.cpp
-
6src/video_core/renderer_opengl/gl_shader_cache.h
-
44src/video_core/renderer_opengl/gl_shader_decompiler.cpp
-
34src/video_core/renderer_opengl/gl_shader_decompiler.h
-
49src/video_core/shader/decode/memory.cpp
-
38src/video_core/shader/shader_ir.h
-
76src/video_core/shader/track.cpp
@ -0,0 +1,76 @@ |
|||||
|
// Copyright 2018 yuzu Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include <algorithm>
|
||||
|
#include <utility>
|
||||
|
#include <variant>
|
||||
|
|
||||
|
#include "video_core/shader/shader_ir.h"
|
||||
|
|
||||
|
namespace VideoCommon::Shader { |
||||
|
|
||||
|
namespace { |
||||
|
std::pair<Node, s64> FindOperation(const BasicBlock& code, s64 cursor, |
||||
|
OperationCode operation_code) { |
||||
|
for (; cursor >= 0; --cursor) { |
||||
|
const Node node = code[cursor]; |
||||
|
if (const auto operation = std::get_if<OperationNode>(node)) { |
||||
|
if (operation->GetCode() == operation_code) |
||||
|
return {node, cursor}; |
||||
|
} |
||||
|
} |
||||
|
return {}; |
||||
|
} |
||||
|
} // namespace
|
||||
|
|
||||
|
Node ShaderIR::TrackCbuf(Node tracked, const BasicBlock& code, s64 cursor) { |
||||
|
if (const auto cbuf = std::get_if<CbufNode>(tracked)) { |
||||
|
// Cbuf found, but it has to be immediate
|
||||
|
return std::holds_alternative<ImmediateNode>(*cbuf->GetOffset()) ? tracked : nullptr; |
||||
|
} |
||||
|
if (const auto gpr = std::get_if<GprNode>(tracked)) { |
||||
|
if (gpr->GetIndex() == Tegra::Shader::Register::ZeroIndex) { |
||||
|
return nullptr; |
||||
|
} |
||||
|
// Reduce the cursor in one to avoid infinite loops when the instruction sets the same
|
||||
|
// register that it uses as operand
|
||||
|
const auto [source, new_cursor] = TrackRegister(gpr, code, cursor - 1); |
||||
|
if (!source) { |
||||
|
return nullptr; |
||||
|
} |
||||
|
return TrackCbuf(source, code, new_cursor); |
||||
|
} |
||||
|
if (const auto operation = std::get_if<OperationNode>(tracked)) { |
||||
|
for (std::size_t i = 0; i < operation->GetOperandsCount(); ++i) { |
||||
|
if (const auto found = TrackCbuf((*operation)[i], code, cursor)) { |
||||
|
// Cbuf found in operand
|
||||
|
return found; |
||||
|
} |
||||
|
} |
||||
|
return nullptr; |
||||
|
} |
||||
|
return nullptr; |
||||
|
} |
||||
|
|
||||
|
std::pair<Node, s64> ShaderIR::TrackRegister(const GprNode* tracked, const BasicBlock& code, |
||||
|
s64 cursor) { |
||||
|
for (; cursor >= 0; --cursor) { |
||||
|
const auto [found_node, new_cursor] = FindOperation(code, cursor, OperationCode::Assign); |
||||
|
if (!found_node) { |
||||
|
return {}; |
||||
|
} |
||||
|
const auto operation = std::get_if<OperationNode>(found_node); |
||||
|
ASSERT(operation); |
||||
|
|
||||
|
const auto& target = (*operation)[0]; |
||||
|
if (const auto gpr_target = std::get_if<GprNode>(target)) { |
||||
|
if (gpr_target->GetIndex() == tracked->GetIndex()) { |
||||
|
return {(*operation)[1], new_cursor}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return {}; |
||||
|
} |
||||
|
|
||||
|
} // namespace VideoCommon::Shader
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue