diff options
| -rw-r--r-- | src/video_core/shader/decode.cpp | 36 | ||||
| -rw-r--r-- | src/video_core/shader/decode/texture.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 22 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 1 | 
4 files changed, 60 insertions, 8 deletions
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp index 507614d59..dd2f68a3e 100644 --- a/src/video_core/shader/decode.cpp +++ b/src/video_core/shader/decode.cpp @@ -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 diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index 886650d9e..e7c38f5d6 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp @@ -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;  } diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index b370df8f9..2f29b9506 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h @@ -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 diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index d85f14c97..121528346 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -435,6 +435,7 @@ private:      bool uses_instance_id{};      bool uses_vertex_id{};      bool uses_warps{}; +    bool uses_indexed_samplers{};      Tegra::Shader::Header header;  };  | 
