diff options
Diffstat (limited to 'src/video_core/renderer_vulkan/vk_graphics_pipeline.h')
-rw-r--r-- | src/video_core/renderer_vulkan/vk_graphics_pipeline.h | 145 |
1 files changed, 97 insertions, 48 deletions
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 8b6a98fe0..2bd48d697 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -1,30 +1,36 @@ -// Copyright 2019 yuzu Emulator Project +// Copyright 2021 yuzu Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once +#include <algorithm> #include <array> -#include <optional> -#include <vector> +#include <atomic> +#include <condition_variable> +#include <mutex> +#include <type_traits> -#include "common/common_types.h" +#include "common/thread_worker.h" +#include "shader_recompiler/shader_info.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_descriptor_pool.h" -#include "video_core/renderer_vulkan/vk_shader_decompiler.h" +#include "video_core/renderer_vulkan/vk_texture_cache.h" #include "video_core/vulkan_common/vulkan_wrapper.h" -namespace Vulkan { +namespace VideoCore { +class ShaderNotify; +} -using Maxwell = Tegra::Engines::Maxwell3D::Regs; +namespace Vulkan { struct GraphicsPipelineCacheKey { - VkRenderPass renderpass; - std::array<GPUVAddr, Maxwell::MaxShaderProgram> shaders; - FixedPipelineState fixed_state; + std::array<u64, 6> unique_hashes; + FixedPipelineState state; - std::size_t Hash() const noexcept; + size_t Hash() const noexcept; bool operator==(const GraphicsPipelineCacheKey& rhs) const noexcept; @@ -32,72 +38,115 @@ struct GraphicsPipelineCacheKey { return !operator==(rhs); } - std::size_t Size() const noexcept { - return sizeof(renderpass) + sizeof(shaders) + fixed_state.Size(); + size_t Size() const noexcept { + return sizeof(unique_hashes) + state.Size(); } }; static_assert(std::has_unique_object_representations_v<GraphicsPipelineCacheKey>); static_assert(std::is_trivially_copyable_v<GraphicsPipelineCacheKey>); static_assert(std::is_trivially_constructible_v<GraphicsPipelineCacheKey>); +} // namespace Vulkan + +namespace std { +template <> +struct hash<Vulkan::GraphicsPipelineCacheKey> { + size_t operator()(const Vulkan::GraphicsPipelineCacheKey& k) const noexcept { + return k.Hash(); + } +}; +} // namespace std + +namespace Vulkan { + class Device; -class VKDescriptorPool; +class RenderPassCache; class VKScheduler; class VKUpdateDescriptorQueue; -using SPIRVProgram = std::array<std::optional<SPIRVShader>, Maxwell::MaxShaderStage>; +class GraphicsPipeline { + static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; -class VKGraphicsPipeline final { public: - explicit VKGraphicsPipeline(const Device& device_, VKScheduler& scheduler_, - VKDescriptorPool& descriptor_pool, - VKUpdateDescriptorQueue& update_descriptor_queue_, - const GraphicsPipelineCacheKey& key, - vk::Span<VkDescriptorSetLayoutBinding> bindings, - const SPIRVProgram& program, u32 num_color_buffers); - ~VKGraphicsPipeline(); - - VkDescriptorSet CommitDescriptorSet(); - - VkPipeline GetHandle() const { - return *pipeline; + explicit GraphicsPipeline( + Tegra::Engines::Maxwell3D& maxwell3d, Tegra::MemoryManager& gpu_memory, + VKScheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache, + VideoCore::ShaderNotify* shader_notify, const Device& device, + DescriptorPool& descriptor_pool, VKUpdateDescriptorQueue& update_descriptor_queue, + Common::ThreadWorker* worker_thread, RenderPassCache& render_pass_cache, + const GraphicsPipelineCacheKey& key, std::array<vk::ShaderModule, NUM_STAGES> stages, + const std::array<const Shader::Info*, NUM_STAGES>& infos); + + GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete; + GraphicsPipeline(GraphicsPipeline&&) noexcept = delete; + + GraphicsPipeline& operator=(const GraphicsPipeline&) = delete; + GraphicsPipeline(const GraphicsPipeline&) = delete; + + void AddTransition(GraphicsPipeline* transition); + + void Configure(bool is_indexed) { + configure_func(this, is_indexed); } - VkPipelineLayout GetLayout() const { - return *layout; + [[nodiscard]] GraphicsPipeline* Next(const GraphicsPipelineCacheKey& current_key) noexcept { + if (key == current_key) { + return this; + } + const auto it{std::find(transition_keys.begin(), transition_keys.end(), current_key)}; + return it != transition_keys.end() ? transitions[std::distance(transition_keys.begin(), it)] + : nullptr; } - GraphicsPipelineCacheKey GetCacheKey() const { - return cache_key; + [[nodiscard]] bool IsBuilt() const noexcept { + return is_built.load(std::memory_order::relaxed); } -private: - vk::DescriptorSetLayout CreateDescriptorSetLayout( - vk::Span<VkDescriptorSetLayoutBinding> bindings) const; + template <typename Spec> + static auto MakeConfigureSpecFunc() { + return [](GraphicsPipeline* pl, bool is_indexed) { pl->ConfigureImpl<Spec>(is_indexed); }; + } - vk::PipelineLayout CreatePipelineLayout() const; +private: + template <typename Spec> + void ConfigureImpl(bool is_indexed); - vk::DescriptorUpdateTemplateKHR CreateDescriptorUpdateTemplate( - const SPIRVProgram& program) const; + void ConfigureDraw(); - std::vector<vk::ShaderModule> CreateShaderModules(const SPIRVProgram& program) const; + void MakePipeline(VkRenderPass render_pass); - vk::Pipeline CreatePipeline(const SPIRVProgram& program, VkRenderPass renderpass, - u32 num_color_buffers) const; + void Validate(); + const GraphicsPipelineCacheKey key; + Tegra::Engines::Maxwell3D& maxwell3d; + Tegra::MemoryManager& gpu_memory; const Device& device; + TextureCache& texture_cache; + BufferCache& buffer_cache; VKScheduler& scheduler; - const GraphicsPipelineCacheKey cache_key; - const u64 hash; + VKUpdateDescriptorQueue& update_descriptor_queue; + + void (*configure_func)(GraphicsPipeline*, bool){}; + + std::vector<GraphicsPipelineCacheKey> transition_keys; + std::vector<GraphicsPipeline*> transitions; + + std::array<vk::ShaderModule, NUM_STAGES> spv_modules; + + std::array<Shader::Info, NUM_STAGES> stage_infos; + std::array<u32, 5> enabled_uniform_buffer_masks{}; + VideoCommon::UniformBufferSizes uniform_buffer_sizes{}; vk::DescriptorSetLayout descriptor_set_layout; DescriptorAllocator descriptor_allocator; - VKUpdateDescriptorQueue& update_descriptor_queue; - vk::PipelineLayout layout; - vk::DescriptorUpdateTemplateKHR descriptor_template; - std::vector<vk::ShaderModule> modules; - + vk::PipelineLayout pipeline_layout; + vk::DescriptorUpdateTemplateKHR descriptor_update_template; vk::Pipeline pipeline; + + std::condition_variable build_condvar; + std::mutex build_mutex; + std::atomic_bool is_built{false}; + bool uses_push_descriptor{false}; }; } // namespace Vulkan |