// Copyright 2019 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 "common/common_types.h" #include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/microinstruction.h" #include "shader_recompiler/frontend/maxwell/control_flow.h" #include "shader_recompiler/object_pool.h" #include "shader_recompiler/profile.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/renderer_vulkan/fixed_pipeline_state.h" #include "video_core/renderer_vulkan/vk_buffer_cache.h" #include "video_core/renderer_vulkan/vk_compute_pipeline.h" #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" #include "video_core/renderer_vulkan/vk_texture_cache.h" #include "video_core/shader_cache.h" #include "video_core/vulkan_common/vulkan_wrapper.h" namespace Core { class System; } namespace Vulkan { using Maxwell = Tegra::Engines::Maxwell3D::Regs; struct ComputePipelineCacheKey { u128 unique_hash; u32 shared_memory_size; std::array workgroup_size; size_t Hash() const noexcept; bool operator==(const ComputePipelineCacheKey& rhs) const noexcept; bool operator!=(const ComputePipelineCacheKey& rhs) const noexcept { return !operator==(rhs); } }; static_assert(std::has_unique_object_representations_v); static_assert(std::is_trivially_copyable_v); static_assert(std::is_trivially_constructible_v); struct GraphicsPipelineCacheKey { std::array unique_hashes; FixedPipelineState state; size_t Hash() const noexcept; bool operator==(const GraphicsPipelineCacheKey& rhs) const noexcept; bool operator!=(const GraphicsPipelineCacheKey& rhs) const noexcept { return !operator==(rhs); } size_t Size() const noexcept { return sizeof(unique_hashes) + state.Size(); } }; static_assert(std::has_unique_object_representations_v); static_assert(std::is_trivially_copyable_v); static_assert(std::is_trivially_constructible_v); } // namespace Vulkan namespace std { template <> struct hash { size_t operator()(const Vulkan::ComputePipelineCacheKey& k) const noexcept { return k.Hash(); } }; template <> struct hash { size_t operator()(const Vulkan::GraphicsPipelineCacheKey& k) const noexcept { return k.Hash(); } }; } // namespace std namespace Vulkan { class ComputePipeline; class Device; class RasterizerVulkan; class RenderPassCache; class VKDescriptorPool; class VKScheduler; class VKUpdateDescriptorQueue; struct ShaderInfo { u128 unique_hash{}; size_t size_bytes{}; }; class PipelineCache final : public VideoCommon::ShaderCache { public: explicit PipelineCache(RasterizerVulkan& rasterizer, Tegra::GPU& gpu, Tegra::Engines::Maxwell3D& maxwell3d, Tegra::Engines::KeplerCompute& kepler_compute, Tegra::MemoryManager& gpu_memory, const Device& device, VKScheduler& scheduler, VKDescriptorPool& descriptor_pool, VKUpdateDescriptorQueue& update_descriptor_queue, RenderPassCache& render_pass_cache, BufferCache& buffer_cache, TextureCache& texture_cache); ~PipelineCache() override; [[nodiscard]] GraphicsPipeline* CurrentGraphicsPipeline(); [[nodiscard]] ComputePipeline* CurrentComputePipeline(); private: bool RefreshStages(); const ShaderInfo* MakeShaderInfo(Maxwell::ShaderProgram program, GPUVAddr base_addr, u32 start_address, VAddr cpu_addr); GraphicsPipeline CreateGraphicsPipeline(); ComputePipeline CreateComputePipeline(ShaderInfo* shader); ComputePipeline* CreateComputePipelineWithoutShader(VAddr shader_cpu_addr); ComputePipelineCacheKey MakeComputePipelineKey(u128 unique_hash) const; Tegra::GPU& gpu; Tegra::Engines::Maxwell3D& maxwell3d; Tegra::Engines::KeplerCompute& kepler_compute; Tegra::MemoryManager& gpu_memory; const Device& device; VKScheduler& scheduler; VKDescriptorPool& descriptor_pool; VKUpdateDescriptorQueue& update_descriptor_queue; RenderPassCache& render_pass_cache; BufferCache& buffer_cache; TextureCache& texture_cache; GraphicsPipelineCacheKey graphics_key{}; std::unordered_map compute_cache; std::unordered_map graphics_cache; Shader::ObjectPool inst_pool; Shader::ObjectPool block_pool; Shader::ObjectPool flow_block_pool; Shader::Profile profile; }; } // namespace Vulkan