mirror of
https://git.suyu.dev/suyu/suyu
synced 2024-12-24 18:32:49 -06:00
Shader_IR: deduce size of indexed samplers
This commit is contained in:
parent
f4603d23c5
commit
037ea431ce
4 changed files with 60 additions and 8 deletions
|
@ -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
|
} // Anonymous namespace
|
||||||
|
|
||||||
class ASTDecoder {
|
class ASTDecoder {
|
||||||
|
@ -342,6 +365,19 @@ void ShaderIR::PostDecode() {
|
||||||
// Deduce texture handler size if needed
|
// Deduce texture handler size if needed
|
||||||
auto gpu_driver = locker.AccessGuestDriverProfile();
|
auto gpu_driver = locker.AccessGuestDriverProfile();
|
||||||
DeduceTextureHandlerSize(gpu_driver, used_samplers);
|
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
|
} // namespace VideoCommon::Shader
|
||||||
|
|
|
@ -383,7 +383,7 @@ const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
|
||||||
// Otherwise create a new mapping for this sampler
|
// Otherwise create a new mapping for this sampler
|
||||||
const auto next_index = static_cast<u32>(used_samplers.size());
|
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,
|
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,
|
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
|
// Otherwise create a new mapping for this sampler
|
||||||
const auto next_index = static_cast<u32>(used_samplers.size());
|
const auto next_index = static_cast<u32>(used_samplers.size());
|
||||||
return &used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array,
|
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 =
|
} else if (const auto array_sampler_info =
|
||||||
std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) {
|
std::get_if<ArraySamplerNode>(&*tracked_sampler_info)) {
|
||||||
const u32 base_offset = array_sampler_info->GetBaseOffset() / 4;
|
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()) {
|
if (it != used_samplers.end()) {
|
||||||
ASSERT(!it->IsBindless() && it->GetType() == info.type &&
|
ASSERT(!it->IsBindless() && it->GetType() == info.type &&
|
||||||
it->IsArray() == info.is_array && it->IsShadow() == info.is_shadow &&
|
it->IsArray() == info.is_array && it->IsShadow() == info.is_shadow &&
|
||||||
it->IsBuffer() == info.is_buffer);
|
it->IsBuffer() == info.is_buffer && it->IsIndexed());
|
||||||
return &*it;
|
return &*it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uses_indexed_samplers = true;
|
||||||
// Otherwise create a new mapping for this sampler
|
// Otherwise create a new mapping for this sampler
|
||||||
const auto next_index = static_cast<u32>(used_samplers.size());
|
const auto next_index = static_cast<u32>(used_samplers.size());
|
||||||
return &used_samplers.emplace_back(next_index, base_offset, info.type, info.is_array,
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,15 +240,15 @@ class Sampler {
|
||||||
public:
|
public:
|
||||||
/// This constructor is for bound samplers
|
/// This constructor is for bound samplers
|
||||||
constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type,
|
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},
|
: 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
|
/// This constructor is for bindless samplers
|
||||||
constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type,
|
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},
|
: 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 {
|
constexpr u32 GetIndex() const {
|
||||||
return index;
|
return index;
|
||||||
|
@ -282,16 +282,30 @@ public:
|
||||||
return is_bindless;
|
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:
|
private:
|
||||||
u32 index{}; ///< Emulated index given for the this sampler.
|
u32 index{}; ///< Emulated index given for the this sampler.
|
||||||
u32 offset{}; ///< Offset in the const buffer from where the sampler is being read.
|
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 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)
|
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_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_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_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_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
|
/// Represents a tracked bindless sampler into a direct const buffer
|
||||||
|
|
|
@ -435,6 +435,7 @@ private:
|
||||||
bool uses_instance_id{};
|
bool uses_instance_id{};
|
||||||
bool uses_vertex_id{};
|
bool uses_vertex_id{};
|
||||||
bool uses_warps{};
|
bool uses_warps{};
|
||||||
|
bool uses_indexed_samplers{};
|
||||||
|
|
||||||
Tegra::Shader::Header header;
|
Tegra::Shader::Header header;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue