Shader_IR: deduce size of indexed samplers
This commit is contained in:
parent
f4603d23c5
commit
037ea431ce
|
@ -56,6 +56,29 @@ void DeduceTextureHandlerSize(VideoCore::GuestDriverProfile* gpu_driver,
|
|||
}
|
||||
}
|
||||
|
||||
std::optional<u32> TryDeduceSamplerSize(Sampler& sampler_to_deduce,
|
||||
VideoCore::GuestDriverProfile* gpu_driver,
|
||||
std::list<Sampler>& used_samplers) {
|
||||
if (gpu_driver == nullptr) {
|
||||
LOG_CRITICAL(HW_GPU, "GPU Driver profile has not been created yet");
|
||||
return std::nullopt;
|
||||
}
|
||||
const u32 base_offset = sampler_to_deduce.GetOffset();
|
||||
u32 max_offset{UINT_MAX};
|
||||
for (const auto& sampler : used_samplers) {
|
||||
if (sampler.IsBindless()) {
|
||||
continue;
|
||||
}
|
||||
if (sampler.GetOffset() > base_offset) {
|
||||
max_offset = std::min(sampler.GetOffset(), max_offset);
|
||||
}
|
||||
}
|
||||
if (max_offset == UINT_MAX) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return ((max_offset - base_offset) * 4) / gpu_driver->GetTextureHandlerSize();
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
class ASTDecoder {
|
||||
|
@ -342,6 +365,19 @@ void ShaderIR::PostDecode() {
|
|||
// Deduce texture handler size if needed
|
||||
auto gpu_driver = locker.AccessGuestDriverProfile();
|
||||
DeduceTextureHandlerSize(gpu_driver, used_samplers);
|
||||
// Deduce Indexed Samplers
|
||||
if (uses_indexed_samplers) {
|
||||
for (auto& sampler : used_samplers) {
|
||||
if (sampler.IsIndexed()) {
|
||||
auto size = TryDeduceSamplerSize(sampler, gpu_driver, used_samplers);
|
||||
if (size) {
|
||||
sampler.SetSize(*size);
|
||||
} else {
|
||||
sampler.SetSize(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace VideoCommon::Shader
|
||||
|
|
|
@ -383,7 +383,7 @@ const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
|
|||
// Otherwise create a new mapping for this sampler
|
||||
const auto next_index = static_cast<u32>(used_samplers.size());
|
||||
return &used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow,
|
||||
info.is_buffer);
|
||||
info.is_buffer, false);
|
||||
}
|
||||
|
||||
const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
|
||||
|
@ -417,7 +417,7 @@ const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
|
|||
// Otherwise create a new mapping for this sampler
|
||||
const auto next_index = static_cast<u32>(used_samplers.size());
|
||||
return &used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array,
|
||||
info.is_shadow, info.is_buffer);
|
||||
info.is_shadow, info.is_buffer, false);
|
||||
} else if (const auto array_sampler_info =
|
||||
std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) {
|
||||
const u32 base_offset = array_sampler_info->GetBaseOffset() / 4;
|
||||
|
@ -430,14 +430,15 @@ const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg,
|
|||
if (it != used_samplers.end()) {
|
||||
ASSERT(!it->IsBindless() && it->GetType() == info.type &&
|
||||
it->IsArray() == info.is_array && it->IsShadow() == info.is_shadow &&
|
||||
it->IsBuffer() == info.is_buffer);
|
||||
it->IsBuffer() == info.is_buffer && it->IsIndexed());
|
||||
return &*it;
|
||||
}
|
||||
|
||||
uses_indexed_samplers = true;
|
||||
// Otherwise create a new mapping for this sampler
|
||||
const auto next_index = static_cast<u32>(used_samplers.size());
|
||||
return &used_samplers.emplace_back(next_index, base_offset, info.type, info.is_array,
|
||||
info.is_shadow, info.is_buffer);
|
||||
info.is_shadow, info.is_buffer, true);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -240,15 +240,15 @@ class Sampler {
|
|||
public:
|
||||
/// This constructor is for bound samplers
|
||||
constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type,
|
||||
bool is_array, bool is_shadow, bool is_buffer)
|
||||
bool is_array, bool is_shadow, bool is_buffer, bool is_indexed)
|
||||
: index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow},
|
||||
is_buffer{is_buffer} {}
|
||||
is_buffer{is_buffer}, is_indexed{is_indexed} {}
|
||||
|
||||
/// This constructor is for bindless samplers
|
||||
constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type,
|
||||
bool is_array, bool is_shadow, bool is_buffer)
|
||||
bool is_array, bool is_shadow, bool is_buffer, bool is_indexed)
|
||||
: index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array},
|
||||
is_shadow{is_shadow}, is_buffer{is_buffer}, is_bindless{true} {}
|
||||
is_shadow{is_shadow}, is_buffer{is_buffer}, is_bindless{true}, is_indexed{is_indexed} {}
|
||||
|
||||
constexpr u32 GetIndex() const {
|
||||
return index;
|
||||
|
@ -282,16 +282,30 @@ public:
|
|||
return is_bindless;
|
||||
}
|
||||
|
||||
constexpr bool IsIndexed() const {
|
||||
return is_indexed;
|
||||
}
|
||||
|
||||
constexpr u32 Size() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
void SetSize(u32 new_size) {
|
||||
size = new_size;
|
||||
}
|
||||
|
||||
private:
|
||||
u32 index{}; ///< Emulated index given for the this sampler.
|
||||
u32 offset{}; ///< Offset in the const buffer from where the sampler is being read.
|
||||
u32 buffer{}; ///< Buffer where the bindless sampler is being read (unused on bound samplers).
|
||||
u32 size{}; ///< Size of the sampler if indexed.
|
||||
|
||||
Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc)
|
||||
bool is_array{}; ///< Whether the texture is being sampled as an array texture or not.
|
||||
bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not.
|
||||
bool is_buffer{}; ///< Whether the texture is a texture buffer without sampler.
|
||||
bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not.
|
||||
bool is_indexed{}; ///< Whether this sampler is an indexed array of textures.
|
||||
};
|
||||
|
||||
/// Represents a tracked bindless sampler into a direct const buffer
|
||||
|
|
|
@ -435,6 +435,7 @@ private:
|
|||
bool uses_instance_id{};
|
||||
bool uses_vertex_id{};
|
||||
bool uses_warps{};
|
||||
bool uses_indexed_samplers{};
|
||||
|
||||
Tegra::Shader::Header header;
|
||||
};
|
||||
|
|
Reference in New Issue