|
|
@ -14,6 +14,7 @@ |
|
|
namespace VideoCommon::Shader { |
|
|
namespace VideoCommon::Shader { |
|
|
|
|
|
|
|
|
namespace { |
|
|
namespace { |
|
|
|
|
|
|
|
|
std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor, |
|
|
std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor, |
|
|
OperationCode operation_code) { |
|
|
OperationCode operation_code) { |
|
|
for (; cursor >= 0; --cursor) { |
|
|
for (; cursor >= 0; --cursor) { |
|
|
@ -72,40 +73,27 @@ bool AmendNodeCv(std::size_t amend_index, Node node) { |
|
|
|
|
|
|
|
|
} // Anonymous namespace
|
|
|
} // Anonymous namespace
|
|
|
|
|
|
|
|
|
std::tuple<Node, TrackSampler> ShaderIR::TrackBindlessSampler(Node tracked, const NodeBlock& code, |
|
|
|
|
|
s64 cursor) { |
|
|
|
|
|
|
|
|
std::pair<Node, TrackSampler> ShaderIR::TrackBindlessSampler(Node tracked, const NodeBlock& code, |
|
|
|
|
|
s64 cursor) { |
|
|
if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { |
|
|
if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { |
|
|
|
|
|
const u32 cbuf_index = cbuf->GetIndex(); |
|
|
|
|
|
|
|
|
// Constant buffer found, test if it's an immediate
|
|
|
// Constant buffer found, test if it's an immediate
|
|
|
const auto& offset = cbuf->GetOffset(); |
|
|
const auto& offset = cbuf->GetOffset(); |
|
|
if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) { |
|
|
if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) { |
|
|
auto track = |
|
|
|
|
|
MakeTrackSampler<BindlessSamplerNode>(cbuf->GetIndex(), immediate->GetValue()); |
|
|
|
|
|
|
|
|
auto track = MakeTrackSampler<BindlessSamplerNode>(cbuf_index, immediate->GetValue()); |
|
|
return {tracked, track}; |
|
|
return {tracked, track}; |
|
|
} |
|
|
} |
|
|
if (const auto operation = std::get_if<OperationNode>(&*offset)) { |
|
|
if (const auto operation = std::get_if<OperationNode>(&*offset)) { |
|
|
const u32 bound_buffer = registry.GetBoundBuffer(); |
|
|
const u32 bound_buffer = registry.GetBoundBuffer(); |
|
|
if (bound_buffer != cbuf->GetIndex()) { |
|
|
|
|
|
|
|
|
if (bound_buffer != cbuf_index) { |
|
|
return {}; |
|
|
return {}; |
|
|
} |
|
|
} |
|
|
const auto pair = DecoupleIndirectRead(*operation); |
|
|
|
|
|
if (!pair) { |
|
|
|
|
|
return {}; |
|
|
|
|
|
|
|
|
if (const std::optional pair = DecoupleIndirectRead(*operation)) { |
|
|
|
|
|
auto [gpr, base_offset] = *pair; |
|
|
|
|
|
return HandleBindlessIndirectRead(*cbuf, *operation, gpr, base_offset, tracked, |
|
|
|
|
|
code, cursor); |
|
|
} |
|
|
} |
|
|
auto [gpr, base_offset] = *pair; |
|
|
|
|
|
const auto offset_inm = std::get_if<ImmediateNode>(&*base_offset); |
|
|
|
|
|
const auto& gpu_driver = registry.AccessGuestDriverProfile(); |
|
|
|
|
|
const u32 bindless_cv = NewCustomVariable(); |
|
|
|
|
|
Node op = |
|
|
|
|
|
Operation(OperationCode::UDiv, gpr, Immediate(gpu_driver.GetTextureHandlerSize())); |
|
|
|
|
|
|
|
|
|
|
|
const Node cv_node = GetCustomVariable(bindless_cv); |
|
|
|
|
|
Node amend_op = Operation(OperationCode::Assign, cv_node, std::move(op)); |
|
|
|
|
|
const std::size_t amend_index = DeclareAmend(std::move(amend_op)); |
|
|
|
|
|
AmendNodeCv(amend_index, code[cursor]); |
|
|
|
|
|
// TODO Implement Bindless Index custom variable
|
|
|
|
|
|
auto track = MakeTrackSampler<ArraySamplerNode>(cbuf->GetIndex(), |
|
|
|
|
|
offset_inm->GetValue(), bindless_cv); |
|
|
|
|
|
return {tracked, track}; |
|
|
|
|
|
} |
|
|
} |
|
|
return {}; |
|
|
return {}; |
|
|
} |
|
|
} |
|
|
@ -139,6 +127,26 @@ std::tuple<Node, TrackSampler> ShaderIR::TrackBindlessSampler(Node tracked, cons |
|
|
return {}; |
|
|
return {}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::pair<Node, TrackSampler> ShaderIR::HandleBindlessIndirectRead( |
|
|
|
|
|
const CbufNode& cbuf, const OperationNode& operation, Node gpr, Node base_offset, Node tracked, |
|
|
|
|
|
const NodeBlock& code, s64 cursor) { |
|
|
|
|
|
const auto offset_imm = std::get<ImmediateNode>(*base_offset); |
|
|
|
|
|
const auto& gpu_driver = registry.AccessGuestDriverProfile(); |
|
|
|
|
|
const u32 bindless_cv = NewCustomVariable(); |
|
|
|
|
|
const u32 texture_handler_size = gpu_driver.GetTextureHandlerSize(); |
|
|
|
|
|
Node op = Operation(OperationCode::UDiv, gpr, Immediate(texture_handler_size)); |
|
|
|
|
|
|
|
|
|
|
|
Node cv_node = GetCustomVariable(bindless_cv); |
|
|
|
|
|
Node amend_op = Operation(OperationCode::Assign, std::move(cv_node), std::move(op)); |
|
|
|
|
|
const std::size_t amend_index = DeclareAmend(std::move(amend_op)); |
|
|
|
|
|
AmendNodeCv(amend_index, code[cursor]); |
|
|
|
|
|
|
|
|
|
|
|
// TODO: Implement bindless index custom variable
|
|
|
|
|
|
auto track = |
|
|
|
|
|
MakeTrackSampler<ArraySamplerNode>(cbuf.GetIndex(), offset_imm.GetValue(), bindless_cv); |
|
|
|
|
|
return {tracked, track}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
std::tuple<Node, u32, u32> ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, |
|
|
std::tuple<Node, u32, u32> ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, |
|
|
s64 cursor) const { |
|
|
s64 cursor) const { |
|
|
if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { |
|
|
if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { |
|
|
|