// Copyright 2018 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 "common/common_types.h" #include "video_core/engines/shader_type.h" #include "video_core/renderer_opengl/gl_resource_manager.h" #include "video_core/renderer_opengl/gl_shader_decompiler.h" #include "video_core/renderer_opengl/gl_shader_disk_cache.h" #include "video_core/shader/registry.h" #include "video_core/shader/shader_ir.h" #include "video_core/shader_cache.h" namespace Tegra { class MemoryManager; } namespace Core::Frontend { class EmuWindow; } namespace VideoCommon::Shader { class AsyncShaders; } namespace OpenGL { class Device; class RasterizerOpenGL; using Maxwell = Tegra::Engines::Maxwell3D::Regs; struct ProgramHandle { OGLProgram source_program; OGLAssemblyProgram assembly_program; }; using ProgramSharedPtr = std::shared_ptr; struct PrecompiledShader { ProgramSharedPtr program; std::shared_ptr registry; ShaderEntries entries; }; struct ShaderParameters { Tegra::GPU& gpu; Tegra::Engines::ConstBufferEngineInterface& engine; ShaderDiskCacheOpenGL& disk_cache; const Device& device; VAddr cpu_addr; const u8* host_ptr; u64 unique_identifier; }; ProgramSharedPtr BuildShader(const Device& device, Tegra::Engines::ShaderType shader_type, u64 unique_identifier, const VideoCommon::Shader::ShaderIR& ir, const VideoCommon::Shader::Registry& registry, bool hint_retrievable = false); class Shader final { public: ~Shader(); /// Gets the GL program handle for the shader GLuint GetHandle() const; bool IsBuilt() const; /// Gets the shader entries for the shader const ShaderEntries& GetEntries() const { return entries; } const VideoCommon::Shader::Registry& GetRegistry() const { return *registry; } /// Mark a OpenGL shader as built void AsyncOpenGLBuilt(OGLProgram new_program); /// Mark a GLASM shader as built void AsyncGLASMBuilt(OGLAssemblyProgram new_program); static std::unique_ptr CreateStageFromMemory( const ShaderParameters& params, Maxwell::ShaderProgram program_type, ProgramCode program_code, ProgramCode program_code_b, VideoCommon::Shader::AsyncShaders& async_shaders, VAddr cpu_addr); static std::unique_ptr CreateKernelFromMemory(const ShaderParameters& params, ProgramCode code); static std::unique_ptr CreateFromCache(const ShaderParameters& params, const PrecompiledShader& precompiled_shader); private: explicit Shader(std::shared_ptr registry, ShaderEntries entries, ProgramSharedPtr program, bool is_built_ = true); std::shared_ptr registry; ShaderEntries entries; ProgramSharedPtr program; GLuint handle = 0; bool is_built{}; }; class ShaderCacheOpenGL final : public VideoCommon::ShaderCache { public: explicit ShaderCacheOpenGL(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu, Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::Engines::KeplerCompute& kepler_compute_, Tegra::MemoryManager& gpu_memory_, const Device& device_); ~ShaderCacheOpenGL() override; /// Loads disk cache for the current game void LoadDiskCache(u64 title_id, const std::atomic_bool& stop_loading, const VideoCore::DiskResourceLoadCallback& callback); /// Gets the current specified shader stage program Shader* GetStageProgram(Maxwell::ShaderProgram program, VideoCommon::Shader::AsyncShaders& async_shaders); /// Gets a compute kernel in the passed address Shader* GetComputeKernel(GPUVAddr code_addr); private: ProgramSharedPtr GeneratePrecompiledProgram( const ShaderDiskCacheEntry& entry, const ShaderDiskCachePrecompiled& precompiled_entry, const std::unordered_set& supported_formats); Core::Frontend::EmuWindow& emu_window; Tegra::GPU& gpu; Tegra::MemoryManager& gpu_memory; Tegra::Engines::Maxwell3D& maxwell3d; Tegra::Engines::KeplerCompute& kepler_compute; const Device& device; ShaderDiskCacheOpenGL disk_cache; std::unordered_map runtime_cache; std::unique_ptr null_shader; std::unique_ptr null_kernel; std::array last_shaders{}; }; } // namespace OpenGL