summaryrefslogtreecommitdiffstats
path: root/src/video_core/shader/decode/texture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/shader/decode/texture.cpp')
-rw-r--r--src/video_core/shader/decode/texture.cpp103
1 files changed, 74 insertions, 29 deletions
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 0b934a069..4c838c8bb 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -96,6 +96,10 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
}
break;
}
+ case OpCode::Id::TLD4_B: {
+ is_bindless = true;
+ [[fallthrough]];
+ }
case OpCode::Id::TLD4: {
ASSERT(instr.tld4.array == 0);
UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(TextureMiscMode::NDV),
@@ -108,11 +112,14 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
}
const auto texture_type = instr.tld4.texture_type.Value();
- const bool depth_compare = instr.tld4.UsesMiscMode(TextureMiscMode::DC);
+ const bool depth_compare = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::DC)
+ : instr.tld4.UsesMiscMode(TextureMiscMode::DC);
const bool is_array = instr.tld4.array != 0;
- const bool is_aoffi = instr.tld4.UsesMiscMode(TextureMiscMode::AOFFI);
+ const bool is_aoffi = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::AOFFI)
+ : instr.tld4.UsesMiscMode(TextureMiscMode::AOFFI);
WriteTexInstructionFloat(
- bb, instr, GetTld4Code(instr, texture_type, depth_compare, is_array, is_aoffi));
+ bb, instr,
+ GetTld4Code(instr, texture_type, depth_compare, is_array, is_aoffi, is_bindless));
break;
}
case OpCode::Id::TLD4S: {
@@ -141,7 +148,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
const Node component = Immediate(static_cast<u32>(instr.tld4s.component));
const auto& sampler =
- GetSampler(instr.sampler, TextureType::Texture2D, false, depth_compare);
+ GetSampler(instr.sampler, {{TextureType::Texture2D, false, depth_compare}});
Node4 values;
for (u32 element = 0; element < values.size(); ++element) {
@@ -150,7 +157,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
}
- WriteTexsInstructionFloat(bb, instr, values);
+ WriteTexsInstructionFloat(bb, instr, values, true);
break;
}
case OpCode::Id::TXQ_B:
@@ -165,10 +172,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
// Sadly, not all texture instructions specify the type of texture their sampler
// uses. This must be fixed at a later instance.
const auto& sampler =
- is_bindless
- ? GetBindlessSampler(instr.gpr8, Tegra::Shader::TextureType::Texture2D, false,
- false)
- : GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false, false);
+ is_bindless ? GetBindlessSampler(instr.gpr8, {}) : GetSampler(instr.sampler, {});
u32 indexer = 0;
switch (instr.txq.query_type) {
@@ -207,9 +211,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
auto texture_type = instr.tmml.texture_type.Value();
const bool is_array = instr.tmml.array != 0;
- const auto& sampler = is_bindless
- ? GetBindlessSampler(instr.gpr20, texture_type, is_array, false)
- : GetSampler(instr.sampler, texture_type, is_array, false);
+ const auto& sampler =
+ is_bindless ? GetBindlessSampler(instr.gpr20, {{texture_type, is_array, false}})
+ : GetSampler(instr.sampler, {{texture_type, is_array, false}});
std::vector<Node> coords;
@@ -285,9 +289,26 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
return pc;
}
-const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, TextureType type,
- bool is_array, bool is_shadow) {
- const auto offset = static_cast<std::size_t>(sampler.index.Value());
+const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
+ std::optional<SamplerInfo> sampler_info) {
+ const auto offset = static_cast<u32>(sampler.index.Value());
+
+ Tegra::Shader::TextureType type;
+ bool is_array;
+ bool is_shadow;
+ if (sampler_info) {
+ type = sampler_info->type;
+ is_array = sampler_info->is_array;
+ is_shadow = sampler_info->is_shadow;
+ } else if (auto sampler = locker.ObtainBoundSampler(offset); sampler) {
+ type = sampler->texture_type.Value();
+ is_array = sampler->is_array.Value() != 0;
+ is_shadow = sampler->is_shadow.Value() != 0;
+ } else {
+ type = Tegra::Shader::TextureType::Texture2D;
+ is_array = false;
+ is_shadow = false;
+ }
// If this sampler has already been used, return the existing mapping.
const auto itr =
@@ -303,15 +324,31 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, Textu
const std::size_t next_index = used_samplers.size();
const Sampler entry{offset, next_index, type, is_array, is_shadow};
return *used_samplers.emplace(entry).first;
-}
+} // namespace VideoCommon::Shader
-const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, TextureType type,
- bool is_array, bool is_shadow) {
+const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
+ std::optional<SamplerInfo> sampler_info) {
const Node sampler_register = GetRegister(reg);
const auto [base_sampler, cbuf_index, cbuf_offset] =
TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size()));
ASSERT(base_sampler != nullptr);
const auto cbuf_key = (static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset);
+ Tegra::Shader::TextureType type;
+ bool is_array;
+ bool is_shadow;
+ if (sampler_info) {
+ type = sampler_info->type;
+ is_array = sampler_info->is_array;
+ is_shadow = sampler_info->is_shadow;
+ } else if (auto sampler = locker.ObtainBindlessSampler(cbuf_index, cbuf_offset); sampler) {
+ type = sampler->texture_type.Value();
+ is_array = sampler->is_array.Value() != 0;
+ is_shadow = sampler->is_shadow.Value() != 0;
+ } else {
+ type = Tegra::Shader::TextureType::Texture2D;
+ is_array = false;
+ is_shadow = false;
+ }
// If this sampler has already been used, return the existing mapping.
const auto itr =
@@ -344,14 +381,14 @@ void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const
}
}
-void ShaderIR::WriteTexsInstructionFloat(NodeBlock& bb, Instruction instr,
- const Node4& components) {
+void ShaderIR::WriteTexsInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components,
+ bool ignore_mask) {
// TEXS has two destination registers and a swizzle. The first two elements in the swizzle
// go into gpr0+0 and gpr0+1, and the rest goes into gpr28+0 and gpr28+1
u32 dest_elem = 0;
for (u32 component = 0; component < 4; ++component) {
- if (!instr.texs.IsComponentEnabled(component))
+ if (!instr.texs.IsComponentEnabled(component) && !ignore_mask)
continue;
SetTemporary(bb, dest_elem++, components[component]);
}
@@ -411,9 +448,9 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
(texture_type == TextureType::TextureCube && is_array && is_shadow),
"This method is not supported.");
- const auto& sampler = is_bindless
- ? GetBindlessSampler(*bindless_reg, texture_type, is_array, is_shadow)
- : GetSampler(instr.sampler, texture_type, is_array, is_shadow);
+ const auto& sampler =
+ is_bindless ? GetBindlessSampler(*bindless_reg, {{texture_type, is_array, is_shadow}})
+ : GetSampler(instr.sampler, {{texture_type, is_array, is_shadow}});
const bool lod_needed = process_mode == TextureProcessMode::LZ ||
process_mode == TextureProcessMode::LL ||
@@ -553,7 +590,7 @@ Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type,
}
Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool depth_compare,
- bool is_array, bool is_aoffi) {
+ bool is_array, bool is_aoffi, bool is_bindless) {
const std::size_t coord_count = GetCoordCount(texture_type);
// If enabled arrays index is always stored in the gpr8 field
@@ -567,6 +604,12 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
}
u64 parameter_register = instr.gpr20.Value();
+
+ const auto& sampler =
+ is_bindless
+ ? GetBindlessSampler(parameter_register++, {{texture_type, is_array, depth_compare}})
+ : GetSampler(instr.sampler, {{texture_type, is_array, depth_compare}});
+
std::vector<Node> aoffi;
if (is_aoffi) {
aoffi = GetAoffiCoordinates(GetRegister(parameter_register++), coord_count, true);
@@ -577,12 +620,14 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de
dc = GetRegister(parameter_register++);
}
- const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, depth_compare);
+ const Node component = is_bindless ? Immediate(static_cast<u32>(instr.tld4_b.component))
+ : Immediate(static_cast<u32>(instr.tld4.component));
Node4 values;
for (u32 element = 0; element < values.size(); ++element) {
auto coords_copy = coords;
- MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, element};
+ MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, component,
+ element};
values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy));
}
@@ -610,7 +655,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) {
// const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr};
// const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr};
- const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, false);
+ const auto& sampler = GetSampler(instr.sampler, {{texture_type, is_array, false}});
Node4 values;
for (u32 element = 0; element < values.size(); ++element) {
@@ -646,7 +691,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
// When lod is used always is in gpr20
const Node lod = lod_enabled ? GetRegister(instr.gpr20) : Immediate(0);
- const auto& sampler = GetSampler(instr.sampler, texture_type, is_array, false);
+ const auto& sampler = GetSampler(instr.sampler, {{texture_type, is_array, false}});
Node4 values;
for (u32 element = 0; element < values.size(); ++element) {