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