Simplify inline sampler handling

This commit is contained in:
Marcin Mikołajczyk 2025-06-16 19:48:37 +01:00
parent ce63e18e5e
commit bfefae55cd
3 changed files with 17 additions and 33 deletions

View File

@ -531,8 +531,7 @@ IR::Value EmitImageSample(IR::IREmitter& ir, const GcnInst& inst, const IR::Scal
// Load first dword of T# and S#. We will use them as the handle that will guide resource // Load first dword of T# and S#. We will use them as the handle that will guide resource
// tracking pass where to read the sharps. This will later also get patched to the SPIRV texture // tracking pass where to read the sharps. This will later also get patched to the SPIRV texture
// binding index. // binding index.
const IR::Value handle = const IR::Value handle = ir.GetScalarReg(tsharp_reg);
ir.CompositeConstruct(ir.GetScalarReg(tsharp_reg), ir.GetScalarReg(sampler_reg));
const IR::Value inline_sampler = const IR::Value inline_sampler =
ir.CompositeConstruct(ir.GetScalarReg(sampler_reg), ir.GetScalarReg(sampler_reg + 1), ir.CompositeConstruct(ir.GetScalarReg(sampler_reg), ir.GetScalarReg(sampler_reg + 1),
ir.GetScalarReg(sampler_reg + 2), ir.GetScalarReg(sampler_reg + 3)); ir.GetScalarReg(sampler_reg + 2), ir.GetScalarReg(sampler_reg + 3));

View File

@ -3,6 +3,7 @@
#pragma once #pragma once
#include <span> #include <span>
#include <variant>
#include <vector> #include <vector>
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
#include <boost/container/static_vector.hpp> #include <boost/container/static_vector.hpp>

View File

@ -351,8 +351,7 @@ void PatchBufferSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors&
void PatchImageSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) { void PatchImageSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) {
const auto pred = [](const IR::Inst* inst) -> std::optional<const IR::Inst*> { const auto pred = [](const IR::Inst* inst) -> std::optional<const IR::Inst*> {
const auto opcode = inst->GetOpcode(); const auto opcode = inst->GetOpcode();
if (opcode == IR::Opcode::CompositeConstructU32x2 || // IMAGE_SAMPLE (image+sampler) if (opcode == IR::Opcode::ReadConst || // IMAGE_LOAD (image only)
opcode == IR::Opcode::ReadConst || // IMAGE_LOAD (image only)
opcode == IR::Opcode::GetUserData) { opcode == IR::Opcode::GetUserData) {
return inst; return inst;
} }
@ -360,9 +359,7 @@ void PatchImageSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors&
}; };
const auto result = IR::BreadthFirstSearch(&inst, pred); const auto result = IR::BreadthFirstSearch(&inst, pred);
ASSERT_MSG(result, "Unable to find image sharp source"); ASSERT_MSG(result, "Unable to find image sharp source");
const IR::Inst* producer = result.value(); const IR::Inst* tsharp_handle = result.value();
const bool has_sampler = producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2;
const auto tsharp_handle = has_sampler ? producer->Arg(0).InstRecursive() : producer;
// Read image sharp. // Read image sharp.
const auto tsharp = TrackSharp(tsharp_handle, info); const auto tsharp = TrackSharp(tsharp_handle, info);
@ -428,28 +425,14 @@ void PatchImageSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors&
if (inst.GetOpcode() == IR::Opcode::ImageSampleRaw) { if (inst.GetOpcode() == IR::Opcode::ImageSampleRaw) {
// Read sampler sharp. // Read sampler sharp.
const auto sampler_binding = [&] -> u32 { const auto sampler_binding = [&] -> u32 {
ASSERT(producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2); const auto sampler = inst.Arg(5).InstRecursive();
const IR::Value& handle = producer->Arg(1); ASSERT(sampler && sampler->GetOpcode() == IR::Opcode::CompositeConstructU32x4);
const auto handle = sampler->Arg(0);
// Inline sampler resource. // Inline sampler resource.
if (handle.IsImmediate()) { if (handle.IsImmediate()) {
LOG_WARNING(Render_Vulkan, "Inline sampler detected"); LOG_DEBUG(Render_Vulkan, "Inline sampler detected");
const auto inline_sampler_arg = inst.Arg(5).InstRecursive();
const auto pred = [](const IR::Inst* inst) -> std::optional<const IR::Inst*> {
const auto opcode = inst->GetOpcode();
if (opcode == IR::Opcode::CompositeConstructU32x4) {
return inst;
}
return std::nullopt;
};
const auto result = IR::BreadthFirstSearch(inline_sampler_arg, pred);
ASSERT_MSG(result, "Unable to find immediate sampler");
const IR::Inst* inline_producer = result.value();
ASSERT(inline_producer &&
inline_producer->GetOpcode() == IR::Opcode::CompositeConstructU32x4);
const auto [s1, s2, s3, s4] = const auto [s1, s2, s3, s4] =
std::tuple{inline_producer->Arg(0), inline_producer->Arg(1), std::tuple{sampler->Arg(0), sampler->Arg(1), sampler->Arg(2), sampler->Arg(3)};
inline_producer->Arg(2), inline_producer->Arg(3)};
ASSERT(s1.IsImmediate() && s2.IsImmediate() && s3.IsImmediate() && ASSERT(s1.IsImmediate() && s2.IsImmediate() && s3.IsImmediate() &&
s4.IsImmediate()); s4.IsImmediate());
const auto inline_sampler = AmdGpu::Sampler{ const auto inline_sampler = AmdGpu::Sampler{
@ -458,14 +441,15 @@ void PatchImageSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors&
}; };
const auto binding = descriptors.Add(SamplerResource{inline_sampler}); const auto binding = descriptors.Add(SamplerResource{inline_sampler});
return binding; return binding;
} else {
// Normal sampler resource.
const auto ssharp_handle = handle.InstRecursive();
const auto& [ssharp_ud, disable_aniso] = TryDisableAnisoLod0(ssharp_handle);
const auto ssharp = TrackSharp(ssharp_ud, info);
const auto binding =
descriptors.Add(SamplerResource{ssharp, image_binding, disable_aniso});
return binding;
} }
// Normal sampler resource.
const auto ssharp_handle = handle.InstRecursive();
const auto& [ssharp_ud, disable_aniso] = TryDisableAnisoLod0(ssharp_handle);
const auto ssharp = TrackSharp(ssharp_ud, info);
const auto binding =
descriptors.Add(SamplerResource{ssharp, image_binding, disable_aniso});
return binding;
}(); }();
// Patch image and sampler handle. // Patch image and sampler handle.
inst.SetArg(0, ir.Imm32(image_binding | sampler_binding << 16)); inst.SetArg(0, ir.Imm32(image_binding | sampler_binding << 16));