// Copyright 2021 yuzu Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once #include #include #include #include #include #include #include #include #include #include #include #include "common/common_types.h" #include "common/unique_function.h" #include "shader_recompiler/environment.h" #include "video_core/engines/maxwell_3d.h" namespace Tegra { class Memorymanager; } namespace VideoCommon { class GenericEnvironment : public Shader::Environment { public: explicit GenericEnvironment() = default; explicit GenericEnvironment(Tegra::MemoryManager& gpu_memory_, GPUVAddr program_base_, u32 start_address_); ~GenericEnvironment() override; [[nodiscard]] u32 TextureBoundBuffer() const final; [[nodiscard]] u32 LocalMemorySize() const final; [[nodiscard]] u32 SharedMemorySize() const final; [[nodiscard]] std::array WorkgroupSize() const final; [[nodiscard]] u64 ReadInstruction(u32 address) final; [[nodiscard]] std::optional Analyze(); void SetCachedSize(size_t size_bytes); [[nodiscard]] size_t CachedSize() const noexcept; [[nodiscard]] size_t ReadSize() const noexcept; [[nodiscard]] bool CanBeSerialized() const noexcept; [[nodiscard]] u64 CalculateHash() const; void Dump(u64 hash); void Serialize(std::ofstream& file) const; protected: std::optional TryFindSize(); Shader::TextureType ReadTextureTypeImpl(GPUVAddr tic_addr, u32 tic_limit, bool via_header_index, u32 raw); Tegra::MemoryManager* gpu_memory{}; GPUVAddr program_base{}; std::vector code; std::unordered_map texture_types; std::unordered_map cbuf_values; u32 local_memory_size{}; u32 texture_bound{}; u32 shared_memory_size{}; std::array workgroup_size{}; u32 read_lowest = std::numeric_limits::max(); u32 read_highest = 0; u32 cached_lowest = std::numeric_limits::max(); u32 cached_highest = 0; u32 initial_offset = 0; bool has_unbound_instructions = false; }; class GraphicsEnvironment final : public GenericEnvironment { public: explicit GraphicsEnvironment() = default; explicit GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_, Tegra::Engines::Maxwell3D::Regs::ShaderProgram program, GPUVAddr program_base_, u32 start_address_); ~GraphicsEnvironment() override = default; u32 ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) override; Shader::TextureType ReadTextureType(u32 handle) override; private: Tegra::Engines::Maxwell3D* maxwell3d{}; size_t stage_index{}; }; class ComputeEnvironment final : public GenericEnvironment { public: explicit ComputeEnvironment() = default; explicit ComputeEnvironment(Tegra::Engines::KeplerCompute& kepler_compute_, Tegra::MemoryManager& gpu_memory_, GPUVAddr program_base_, u32 start_address_); ~ComputeEnvironment() override = default; u32 ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) override; Shader::TextureType ReadTextureType(u32 handle) override; private: Tegra::Engines::KeplerCompute* kepler_compute{}; }; class FileEnvironment final : public Shader::Environment { public: FileEnvironment() = default; ~FileEnvironment() override = default; FileEnvironment& operator=(FileEnvironment&&) noexcept = default; FileEnvironment(FileEnvironment&&) noexcept = default; FileEnvironment& operator=(const FileEnvironment&) = delete; FileEnvironment(const FileEnvironment&) = delete; void Deserialize(std::ifstream& file); [[nodiscard]] u64 ReadInstruction(u32 address) override; [[nodiscard]] u32 ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) override; [[nodiscard]] Shader::TextureType ReadTextureType(u32 handle) override; [[nodiscard]] u32 LocalMemorySize() const override; [[nodiscard]] u32 SharedMemorySize() const override; [[nodiscard]] u32 TextureBoundBuffer() const override; [[nodiscard]] std::array WorkgroupSize() const override; void Dump(u64 hash) override; private: std::unique_ptr code; std::unordered_map texture_types; std::unordered_map cbuf_values; std::array workgroup_size{}; u32 local_memory_size{}; u32 shared_memory_size{}; u32 texture_bound{}; u32 read_lowest{}; u32 read_highest{}; u32 initial_offset{}; }; void SerializePipeline(std::span key, std::span envs, const std::filesystem::path& filename, u32 cache_version); template void SerializePipeline(const Key& key, const Envs& envs, const std::filesystem::path& filename, u32 cache_version) { static_assert(std::is_trivially_copyable_v); static_assert(std::has_unique_object_representations_v); SerializePipeline(std::span(reinterpret_cast(&key), sizeof(key)), std::span(envs.data(), envs.size()), filename, cache_version); } void LoadPipelines( std::stop_token stop_loading, const std::filesystem::path& filename, u32 expected_cache_version, Common::UniqueFunction load_compute, Common::UniqueFunction> load_graphics); } // namespace VideoCommon