// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include #include #include #include #include #include #include #include #include #include "common/common_types.h" #include "common/polyfill_thread.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 CachedSizeWords() const noexcept; [[nodiscard]] size_t CachedSizeBytes() const noexcept; [[nodiscard]] size_t ReadSizeBytes() const noexcept; [[nodiscard]] bool CanBeSerialized() const noexcept; [[nodiscard]] u64 CalculateHash() const; void Dump(u64 pipeline_hash, u64 shader_hash) override; void Serialize(std::ofstream& file) const; bool HasHLEMacroState() const override { return has_hle_engine_state; } protected: std::optional TryFindSize(); Tegra::Texture::TICEntry ReadTextureInfo(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 texture_pixel_formats; std::unordered_map cbuf_values; std::unordered_map cbuf_replacements; 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; u32 viewport_transform_state = 1; bool has_unbound_instructions = false; bool has_hle_engine_state = false; }; class GraphicsEnvironment final : public GenericEnvironment { public: explicit GraphicsEnvironment() = default; explicit GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_, Tegra::Engines::Maxwell3D::Regs::ShaderType 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; Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override; bool IsTexturePixelFormatInteger(u32 handle) override; u32 ReadViewportTransformState() override; std::optional GetReplaceConstBuffer(u32 bank, u32 offset) 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; Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override; bool IsTexturePixelFormatInteger(u32 handle) override; u32 ReadViewportTransformState() override; std::optional GetReplaceConstBuffer( [[maybe_unused]] u32 bank, [[maybe_unused]] u32 offset) override { return std::nullopt; } 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]] Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override; [[nodiscard]] bool IsTexturePixelFormatInteger(u32 handle) override; [[nodiscard]] u32 ReadViewportTransformState() override; [[nodiscard]] u32 LocalMemorySize() const override; [[nodiscard]] u32 SharedMemorySize() const override; [[nodiscard]] u32 TextureBoundBuffer() const override; [[nodiscard]] std::array WorkgroupSize() const override; [[nodiscard]] std::optional GetReplaceConstBuffer(u32 bank, u32 offset) override; [[nodiscard]] bool HasHLEMacroState() const override { return cbuf_replacements.size() != 0; } void Dump(u64 pipeline_hash, u64 shader_hash) override; private: std::vector code; std::unordered_map texture_types; std::unordered_map texture_pixel_formats; std::unordered_map cbuf_values; std::unordered_map cbuf_replacements; std::array workgroup_size{}; u32 local_memory_size{}; u32 shared_memory_size{}; u32 texture_bound{}; u32 read_lowest{}; u32 read_highest{}; u32 initial_offset{}; u32 viewport_transform_state = 1; }; 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