diff options
| author | 2021-02-17 00:59:28 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:22 -0400 | |
| commit | 85cce78583bc2232428a8fb39e43182877c8d5ad (patch) | |
| tree | 308f4ef2d145652e08dff1da31c72c2f00dad2e1 /src/video_core/renderer_vulkan | |
| parent | shader: Remove old shader management (diff) | |
| download | yuzu-85cce78583bc2232428a8fb39e43182877c8d5ad.tar.gz yuzu-85cce78583bc2232428a8fb39e43182877c8d5ad.tar.xz yuzu-85cce78583bc2232428a8fb39e43182877c8d5ad.zip | |
shader: Primitive Vulkan integration
Diffstat (limited to 'src/video_core/renderer_vulkan')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | 140 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_compute_pipeline.h | 43 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_descriptor_pool.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_descriptor_pool.h | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline.h | 36 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 190 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.h | 30 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 23 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_resource_pool.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_resource_pool.h | 12 |
11 files changed, 428 insertions, 77 deletions
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 7a3660496..588ce6139 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -4,6 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #include <vector> | 5 | #include <vector> |
| 6 | 6 | ||
| 7 | #include <boost/container/small_vector.hpp> | ||
| 8 | |||
| 9 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | ||
| 7 | #include "video_core/renderer_vulkan/vk_compute_pipeline.h" | 10 | #include "video_core/renderer_vulkan/vk_compute_pipeline.h" |
| 8 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 11 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 9 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | 12 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" |
| @@ -13,9 +16,142 @@ | |||
| 13 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 16 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 14 | 17 | ||
| 15 | namespace Vulkan { | 18 | namespace Vulkan { |
| 19 | namespace { | ||
| 20 | vk::DescriptorSetLayout CreateDescriptorSetLayout(const Device& device, const Shader::Info& info) { | ||
| 21 | boost::container::small_vector<VkDescriptorSetLayoutBinding, 24> bindings; | ||
| 22 | u32 binding{}; | ||
| 23 | for ([[maybe_unused]] const auto& desc : info.constant_buffer_descriptors) { | ||
| 24 | bindings.push_back({ | ||
| 25 | .binding = binding, | ||
| 26 | .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, | ||
| 27 | .descriptorCount = 1, | ||
| 28 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 29 | .pImmutableSamplers = nullptr, | ||
| 30 | }); | ||
| 31 | ++binding; | ||
| 32 | } | ||
| 33 | for ([[maybe_unused]] const auto& desc : info.storage_buffers_descriptors) { | ||
| 34 | bindings.push_back({ | ||
| 35 | .binding = binding, | ||
| 36 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 37 | .descriptorCount = 1, | ||
| 38 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 39 | .pImmutableSamplers = nullptr, | ||
| 40 | }); | ||
| 41 | ++binding; | ||
| 42 | } | ||
| 43 | return device.GetLogical().CreateDescriptorSetLayout({ | ||
| 44 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, | ||
| 45 | .pNext = nullptr, | ||
| 46 | .flags = 0, | ||
| 47 | .bindingCount = static_cast<u32>(bindings.size()), | ||
| 48 | .pBindings = bindings.data(), | ||
| 49 | }); | ||
| 50 | } | ||
| 51 | |||
| 52 | vk::DescriptorUpdateTemplateKHR CreateDescriptorUpdateTemplate( | ||
| 53 | const Device& device, const Shader::Info& info, VkDescriptorSetLayout descriptor_set_layout, | ||
| 54 | VkPipelineLayout pipeline_layout) { | ||
| 55 | boost::container::small_vector<VkDescriptorUpdateTemplateEntry, 24> entries; | ||
| 56 | size_t offset{}; | ||
| 57 | u32 binding{}; | ||
| 58 | for ([[maybe_unused]] const auto& desc : info.constant_buffer_descriptors) { | ||
| 59 | entries.push_back({ | ||
| 60 | .dstBinding = binding, | ||
| 61 | .dstArrayElement = 0, | ||
| 62 | .descriptorCount = 1, | ||
| 63 | .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, | ||
| 64 | .offset = offset, | ||
| 65 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 66 | }); | ||
| 67 | ++binding; | ||
| 68 | offset += sizeof(DescriptorUpdateEntry); | ||
| 69 | } | ||
| 70 | for ([[maybe_unused]] const auto& desc : info.storage_buffers_descriptors) { | ||
| 71 | entries.push_back({ | ||
| 72 | .dstBinding = binding, | ||
| 73 | .dstArrayElement = 0, | ||
| 74 | .descriptorCount = 1, | ||
| 75 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 76 | .offset = offset, | ||
| 77 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 78 | }); | ||
| 79 | ++binding; | ||
| 80 | offset += sizeof(DescriptorUpdateEntry); | ||
| 81 | } | ||
| 82 | return device.GetLogical().CreateDescriptorUpdateTemplateKHR({ | ||
| 83 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, | ||
| 84 | .pNext = nullptr, | ||
| 85 | .flags = 0, | ||
| 86 | .descriptorUpdateEntryCount = static_cast<u32>(entries.size()), | ||
| 87 | .pDescriptorUpdateEntries = entries.data(), | ||
| 88 | .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, | ||
| 89 | .descriptorSetLayout = descriptor_set_layout, | ||
| 90 | .pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE, | ||
| 91 | .pipelineLayout = pipeline_layout, | ||
| 92 | .set = 0, | ||
| 93 | }); | ||
| 94 | } | ||
| 95 | } // Anonymous namespace | ||
| 96 | |||
| 97 | ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool, | ||
| 98 | VKUpdateDescriptorQueue& update_descriptor_queue_, | ||
| 99 | const Shader::Info& info_, vk::ShaderModule spv_module_) | ||
| 100 | : update_descriptor_queue{&update_descriptor_queue_}, info{info_}, | ||
| 101 | spv_module(std::move(spv_module_)), | ||
| 102 | descriptor_set_layout(CreateDescriptorSetLayout(device, info)), | ||
| 103 | descriptor_allocator(descriptor_pool, *descriptor_set_layout), | ||
| 104 | pipeline_layout{device.GetLogical().CreatePipelineLayout({ | ||
| 105 | .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | ||
| 106 | .pNext = nullptr, | ||
| 107 | .flags = 0, | ||
| 108 | .setLayoutCount = 1, | ||
| 109 | .pSetLayouts = descriptor_set_layout.address(), | ||
| 110 | .pushConstantRangeCount = 0, | ||
| 111 | .pPushConstantRanges = nullptr, | ||
| 112 | })}, | ||
| 113 | descriptor_update_template{ | ||
| 114 | CreateDescriptorUpdateTemplate(device, info, *descriptor_set_layout, *pipeline_layout)}, | ||
| 115 | pipeline{device.GetLogical().CreateComputePipeline({ | ||
| 116 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, | ||
| 117 | .pNext = nullptr, | ||
| 118 | .flags = 0, | ||
| 119 | .stage{ | ||
| 120 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | ||
| 121 | .pNext = nullptr, | ||
| 122 | .flags = 0, | ||
| 123 | .stage = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 124 | .module = *spv_module, | ||
| 125 | .pName = "main", | ||
| 126 | .pSpecializationInfo = nullptr, | ||
| 127 | }, | ||
| 128 | .layout = *pipeline_layout, | ||
| 129 | .basePipelineHandle = 0, | ||
| 130 | .basePipelineIndex = 0, | ||
| 131 | })} {} | ||
| 132 | |||
| 133 | void ComputePipeline::ConfigureBufferCache(BufferCache& buffer_cache) { | ||
| 134 | u32 enabled_uniforms{}; | ||
| 135 | for (const auto& desc : info.constant_buffer_descriptors) { | ||
| 136 | enabled_uniforms |= ((1ULL << desc.count) - 1) << desc.index; | ||
| 137 | } | ||
| 138 | buffer_cache.SetEnabledComputeUniformBuffers(enabled_uniforms); | ||
| 16 | 139 | ||
| 17 | ComputePipeline::ComputePipeline() = default; | 140 | buffer_cache.UnbindComputeStorageBuffers(); |
| 141 | size_t index{}; | ||
| 142 | for (const auto& desc : info.storage_buffers_descriptors) { | ||
| 143 | ASSERT(desc.count == 1); | ||
| 144 | buffer_cache.BindComputeStorageBuffer(index, desc.cbuf_index, desc.cbuf_offset, true); | ||
| 145 | ++index; | ||
| 146 | } | ||
| 147 | buffer_cache.UpdateComputeBuffers(); | ||
| 148 | buffer_cache.BindHostComputeBuffers(); | ||
| 149 | } | ||
| 18 | 150 | ||
| 19 | ComputePipeline::~ComputePipeline() = default; | 151 | VkDescriptorSet ComputePipeline::UpdateDescriptorSet() { |
| 152 | const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()}; | ||
| 153 | update_descriptor_queue->Send(*descriptor_update_template, descriptor_set); | ||
| 154 | return descriptor_set; | ||
| 155 | } | ||
| 20 | 156 | ||
| 21 | } // namespace Vulkan | 157 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h index 433d8bb3d..dc045d524 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h | |||
| @@ -5,19 +5,52 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "shader_recompiler/shader_info.h" | ||
| 9 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | ||
| 8 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 10 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 11 | #include "video_core/renderer_vulkan/vk_pipeline.h" | ||
| 12 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | ||
| 9 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 13 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 10 | 14 | ||
| 11 | namespace Vulkan { | 15 | namespace Vulkan { |
| 12 | 16 | ||
| 13 | class Device; | 17 | class Device; |
| 14 | class VKScheduler; | ||
| 15 | class VKUpdateDescriptorQueue; | ||
| 16 | 18 | ||
| 17 | class ComputePipeline { | 19 | class ComputePipeline : public Pipeline { |
| 18 | public: | 20 | public: |
| 19 | explicit ComputePipeline(); | 21 | explicit ComputePipeline() = default; |
| 20 | ~ComputePipeline(); | 22 | explicit ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool, |
| 23 | VKUpdateDescriptorQueue& update_descriptor_queue, | ||
| 24 | const Shader::Info& info, vk::ShaderModule spv_module); | ||
| 25 | |||
| 26 | ComputePipeline& operator=(ComputePipeline&&) noexcept = default; | ||
| 27 | ComputePipeline(ComputePipeline&&) noexcept = default; | ||
| 28 | |||
| 29 | ComputePipeline& operator=(const ComputePipeline&) = delete; | ||
| 30 | ComputePipeline(const ComputePipeline&) = delete; | ||
| 31 | |||
| 32 | void ConfigureBufferCache(BufferCache& buffer_cache); | ||
| 33 | |||
| 34 | [[nodiscard]] VkDescriptorSet UpdateDescriptorSet(); | ||
| 35 | |||
| 36 | [[nodiscard]] VkPipeline Handle() const noexcept { | ||
| 37 | return *pipeline; | ||
| 38 | } | ||
| 39 | |||
| 40 | [[nodiscard]] VkPipelineLayout PipelineLayout() const noexcept { | ||
| 41 | return *pipeline_layout; | ||
| 42 | } | ||
| 43 | |||
| 44 | private: | ||
| 45 | VKUpdateDescriptorQueue* update_descriptor_queue; | ||
| 46 | Shader::Info info; | ||
| 47 | |||
| 48 | vk::ShaderModule spv_module; | ||
| 49 | vk::DescriptorSetLayout descriptor_set_layout; | ||
| 50 | DescriptorAllocator descriptor_allocator; | ||
| 51 | vk::PipelineLayout pipeline_layout; | ||
| 52 | vk::DescriptorUpdateTemplateKHR descriptor_update_template; | ||
| 53 | vk::Pipeline pipeline; | ||
| 21 | }; | 54 | }; |
| 22 | 55 | ||
| 23 | } // namespace Vulkan | 56 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp index ef9fb5910..3bea1ff44 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp | |||
| @@ -19,9 +19,7 @@ constexpr std::size_t SETS_GROW_RATE = 0x20; | |||
| 19 | DescriptorAllocator::DescriptorAllocator(VKDescriptorPool& descriptor_pool_, | 19 | DescriptorAllocator::DescriptorAllocator(VKDescriptorPool& descriptor_pool_, |
| 20 | VkDescriptorSetLayout layout_) | 20 | VkDescriptorSetLayout layout_) |
| 21 | : ResourcePool(descriptor_pool_.master_semaphore, SETS_GROW_RATE), | 21 | : ResourcePool(descriptor_pool_.master_semaphore, SETS_GROW_RATE), |
| 22 | descriptor_pool{descriptor_pool_}, layout{layout_} {} | 22 | descriptor_pool{&descriptor_pool_}, layout{layout_} {} |
| 23 | |||
| 24 | DescriptorAllocator::~DescriptorAllocator() = default; | ||
| 25 | 23 | ||
| 26 | VkDescriptorSet DescriptorAllocator::Commit() { | 24 | VkDescriptorSet DescriptorAllocator::Commit() { |
| 27 | const std::size_t index = CommitResource(); | 25 | const std::size_t index = CommitResource(); |
| @@ -29,7 +27,7 @@ VkDescriptorSet DescriptorAllocator::Commit() { | |||
| 29 | } | 27 | } |
| 30 | 28 | ||
| 31 | void DescriptorAllocator::Allocate(std::size_t begin, std::size_t end) { | 29 | void DescriptorAllocator::Allocate(std::size_t begin, std::size_t end) { |
| 32 | descriptors_allocations.push_back(descriptor_pool.AllocateDescriptors(layout, end - begin)); | 30 | descriptors_allocations.push_back(descriptor_pool->AllocateDescriptors(layout, end - begin)); |
| 33 | } | 31 | } |
| 34 | 32 | ||
| 35 | VKDescriptorPool::VKDescriptorPool(const Device& device_, VKScheduler& scheduler) | 33 | VKDescriptorPool::VKDescriptorPool(const Device& device_, VKScheduler& scheduler) |
diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.h b/src/video_core/renderer_vulkan/vk_descriptor_pool.h index f892be7be..2501f9967 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.h +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.h | |||
| @@ -17,8 +17,12 @@ class VKScheduler; | |||
| 17 | 17 | ||
| 18 | class DescriptorAllocator final : public ResourcePool { | 18 | class DescriptorAllocator final : public ResourcePool { |
| 19 | public: | 19 | public: |
| 20 | explicit DescriptorAllocator() = default; | ||
| 20 | explicit DescriptorAllocator(VKDescriptorPool& descriptor_pool, VkDescriptorSetLayout layout); | 21 | explicit DescriptorAllocator(VKDescriptorPool& descriptor_pool, VkDescriptorSetLayout layout); |
| 21 | ~DescriptorAllocator() override; | 22 | ~DescriptorAllocator() override = default; |
| 23 | |||
| 24 | DescriptorAllocator& operator=(DescriptorAllocator&&) noexcept = default; | ||
| 25 | DescriptorAllocator(DescriptorAllocator&&) noexcept = default; | ||
| 22 | 26 | ||
| 23 | DescriptorAllocator& operator=(const DescriptorAllocator&) = delete; | 27 | DescriptorAllocator& operator=(const DescriptorAllocator&) = delete; |
| 24 | DescriptorAllocator(const DescriptorAllocator&) = delete; | 28 | DescriptorAllocator(const DescriptorAllocator&) = delete; |
| @@ -29,8 +33,8 @@ protected: | |||
| 29 | void Allocate(std::size_t begin, std::size_t end) override; | 33 | void Allocate(std::size_t begin, std::size_t end) override; |
| 30 | 34 | ||
| 31 | private: | 35 | private: |
| 32 | VKDescriptorPool& descriptor_pool; | 36 | VKDescriptorPool* descriptor_pool{}; |
| 33 | const VkDescriptorSetLayout layout; | 37 | VkDescriptorSetLayout layout{}; |
| 34 | 38 | ||
| 35 | std::vector<vk::DescriptorSets> descriptors_allocations; | 39 | std::vector<vk::DescriptorSets> descriptors_allocations; |
| 36 | }; | 40 | }; |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline.h b/src/video_core/renderer_vulkan/vk_pipeline.h new file mode 100644 index 000000000..b06288403 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_pipeline.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <cstddef> | ||
| 8 | |||
| 9 | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||
| 10 | |||
| 11 | namespace Vulkan { | ||
| 12 | |||
| 13 | class Pipeline { | ||
| 14 | public: | ||
| 15 | /// Add a reference count to the pipeline | ||
| 16 | void AddRef() noexcept { | ||
| 17 | ++ref_count; | ||
| 18 | } | ||
| 19 | |||
| 20 | [[nodiscard]] bool RemoveRef() noexcept { | ||
| 21 | --ref_count; | ||
| 22 | return ref_count == 0; | ||
| 23 | } | ||
| 24 | |||
| 25 | [[nodiscard]] u64 UsageTick() const noexcept { | ||
| 26 | return usage_tick; | ||
| 27 | } | ||
| 28 | |||
| 29 | protected: | ||
| 30 | u64 usage_tick{}; | ||
| 31 | |||
| 32 | private: | ||
| 33 | size_t ref_count{}; | ||
| 34 | }; | ||
| 35 | |||
| 36 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 7d0ba1180..4bf3e4819 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | #include "common/microprofile.h" | 12 | #include "common/microprofile.h" |
| 13 | #include "core/core.h" | 13 | #include "core/core.h" |
| 14 | #include "core/memory.h" | 14 | #include "core/memory.h" |
| 15 | #include "shader_recompiler/environment.h" | ||
| 16 | #include "shader_recompiler/recompiler.h" | ||
| 15 | #include "video_core/engines/kepler_compute.h" | 17 | #include "video_core/engines/kepler_compute.h" |
| 16 | #include "video_core/engines/maxwell_3d.h" | 18 | #include "video_core/engines/maxwell_3d.h" |
| 17 | #include "video_core/memory_manager.h" | 19 | #include "video_core/memory_manager.h" |
| @@ -22,43 +24,105 @@ | |||
| 22 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | 24 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" |
| 23 | #include "video_core/renderer_vulkan/vk_rasterizer.h" | 25 | #include "video_core/renderer_vulkan/vk_rasterizer.h" |
| 24 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 26 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 27 | #include "video_core/renderer_vulkan/vk_shader_util.h" | ||
| 25 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 28 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 26 | #include "video_core/shader_cache.h" | 29 | #include "video_core/shader_cache.h" |
| 27 | #include "video_core/shader_notify.h" | 30 | #include "video_core/shader_notify.h" |
| 28 | #include "video_core/vulkan_common/vulkan_device.h" | 31 | #include "video_core/vulkan_common/vulkan_device.h" |
| 29 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 32 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 30 | 33 | ||
| 34 | #pragma optimize("", off) | ||
| 35 | |||
| 31 | namespace Vulkan { | 36 | namespace Vulkan { |
| 32 | MICROPROFILE_DECLARE(Vulkan_PipelineCache); | 37 | MICROPROFILE_DECLARE(Vulkan_PipelineCache); |
| 33 | 38 | ||
| 34 | using Tegra::Engines::ShaderType; | 39 | using Tegra::Engines::ShaderType; |
| 35 | 40 | ||
| 36 | namespace { | 41 | namespace { |
| 37 | size_t StageFromProgram(size_t program) { | 42 | class Environment final : public Shader::Environment { |
| 38 | return program == 0 ? 0 : program - 1; | 43 | public: |
| 39 | } | 44 | explicit Environment(Tegra::Engines::KeplerCompute& kepler_compute_, |
| 45 | Tegra::MemoryManager& gpu_memory_, GPUVAddr program_base_) | ||
| 46 | : kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_}, program_base{program_base_} {} | ||
| 47 | |||
| 48 | ~Environment() override = default; | ||
| 49 | |||
| 50 | [[nodiscard]] std::optional<u128> Analyze(u32 start_address) { | ||
| 51 | const std::optional<u64> size{TryFindSize(start_address)}; | ||
| 52 | if (!size) { | ||
| 53 | return std::nullopt; | ||
| 54 | } | ||
| 55 | cached_lowest = start_address; | ||
| 56 | cached_highest = start_address + static_cast<u32>(*size); | ||
| 57 | return Common::CityHash128(reinterpret_cast<const char*>(code.data()), code.size()); | ||
| 58 | } | ||
| 40 | 59 | ||
| 41 | ShaderType StageFromProgram(Maxwell::ShaderProgram program) { | 60 | [[nodiscard]] size_t ShaderSize() const noexcept { |
| 42 | return static_cast<ShaderType>(StageFromProgram(static_cast<size_t>(program))); | 61 | return read_highest - read_lowest + INST_SIZE; |
| 43 | } | 62 | } |
| 44 | 63 | ||
| 45 | ShaderType GetShaderType(Maxwell::ShaderProgram program) { | 64 | [[nodiscard]] u128 ComputeHash() const { |
| 46 | switch (program) { | 65 | const size_t size{ShaderSize()}; |
| 47 | case Maxwell::ShaderProgram::VertexB: | 66 | auto data = std::make_unique<u64[]>(size); |
| 48 | return ShaderType::Vertex; | 67 | gpu_memory.ReadBlock(program_base + read_lowest, data.get(), size); |
| 49 | case Maxwell::ShaderProgram::TesselationControl: | 68 | return Common::CityHash128(reinterpret_cast<const char*>(data.get()), size); |
| 50 | return ShaderType::TesselationControl; | ||
| 51 | case Maxwell::ShaderProgram::TesselationEval: | ||
| 52 | return ShaderType::TesselationEval; | ||
| 53 | case Maxwell::ShaderProgram::Geometry: | ||
| 54 | return ShaderType::Geometry; | ||
| 55 | case Maxwell::ShaderProgram::Fragment: | ||
| 56 | return ShaderType::Fragment; | ||
| 57 | default: | ||
| 58 | UNIMPLEMENTED_MSG("program={}", program); | ||
| 59 | return ShaderType::Vertex; | ||
| 60 | } | 69 | } |
| 61 | } | 70 | |
| 71 | u64 ReadInstruction(u32 address) override { | ||
| 72 | read_lowest = std::min(read_lowest, address); | ||
| 73 | read_highest = std::max(read_highest, address); | ||
| 74 | |||
| 75 | if (address >= cached_lowest && address < cached_highest) { | ||
| 76 | return code[address / INST_SIZE]; | ||
| 77 | } | ||
| 78 | return gpu_memory.Read<u64>(program_base + address); | ||
| 79 | } | ||
| 80 | |||
| 81 | std::array<u32, 3> WorkgroupSize() override { | ||
| 82 | const auto& qmd{kepler_compute.launch_description}; | ||
| 83 | return {qmd.block_dim_x, qmd.block_dim_y, qmd.block_dim_z}; | ||
| 84 | } | ||
| 85 | |||
| 86 | private: | ||
| 87 | static constexpr size_t INST_SIZE = sizeof(u64); | ||
| 88 | static constexpr size_t BLOCK_SIZE = 0x1000; | ||
| 89 | static constexpr size_t MAXIMUM_SIZE = 0x100000; | ||
| 90 | |||
| 91 | static constexpr u64 SELF_BRANCH_A = 0xE2400FFFFF87000FULL; | ||
| 92 | static constexpr u64 SELF_BRANCH_B = 0xE2400FFFFF07000FULL; | ||
| 93 | |||
| 94 | std::optional<u64> TryFindSize(u32 start_address) { | ||
| 95 | GPUVAddr guest_addr = program_base + start_address; | ||
| 96 | size_t offset = 0; | ||
| 97 | size_t size = BLOCK_SIZE; | ||
| 98 | while (size <= MAXIMUM_SIZE) { | ||
| 99 | code.resize(size / INST_SIZE); | ||
| 100 | u64* const data = code.data() + offset / INST_SIZE; | ||
| 101 | gpu_memory.ReadBlock(guest_addr, data, BLOCK_SIZE); | ||
| 102 | for (size_t i = 0; i < BLOCK_SIZE; i += INST_SIZE) { | ||
| 103 | const u64 inst = data[i / INST_SIZE]; | ||
| 104 | if (inst == SELF_BRANCH_A || inst == SELF_BRANCH_B) { | ||
| 105 | return offset + i; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | guest_addr += BLOCK_SIZE; | ||
| 109 | size += BLOCK_SIZE; | ||
| 110 | offset += BLOCK_SIZE; | ||
| 111 | } | ||
| 112 | return std::nullopt; | ||
| 113 | } | ||
| 114 | |||
| 115 | Tegra::Engines::KeplerCompute& kepler_compute; | ||
| 116 | Tegra::MemoryManager& gpu_memory; | ||
| 117 | GPUVAddr program_base; | ||
| 118 | |||
| 119 | u32 read_lowest = 0; | ||
| 120 | u32 read_highest = 0; | ||
| 121 | |||
| 122 | std::vector<u64> code; | ||
| 123 | u32 cached_lowest = std::numeric_limits<u32>::max(); | ||
| 124 | u32 cached_highest = 0; | ||
| 125 | }; | ||
| 62 | } // Anonymous namespace | 126 | } // Anonymous namespace |
| 63 | 127 | ||
| 64 | size_t ComputePipelineCacheKey::Hash() const noexcept { | 128 | size_t ComputePipelineCacheKey::Hash() const noexcept { |
| @@ -70,35 +134,91 @@ bool ComputePipelineCacheKey::operator==(const ComputePipelineCacheKey& rhs) con | |||
| 70 | return std::memcmp(&rhs, this, sizeof *this) == 0; | 134 | return std::memcmp(&rhs, this, sizeof *this) == 0; |
| 71 | } | 135 | } |
| 72 | 136 | ||
| 73 | Shader::Shader() = default; | ||
| 74 | |||
| 75 | Shader::~Shader() = default; | ||
| 76 | |||
| 77 | PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::GPU& gpu_, | 137 | PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::GPU& gpu_, |
| 78 | Tegra::Engines::Maxwell3D& maxwell3d_, | 138 | Tegra::Engines::Maxwell3D& maxwell3d_, |
| 79 | Tegra::Engines::KeplerCompute& kepler_compute_, | 139 | Tegra::Engines::KeplerCompute& kepler_compute_, |
| 80 | Tegra::MemoryManager& gpu_memory_, const Device& device_, | 140 | Tegra::MemoryManager& gpu_memory_, const Device& device_, |
| 81 | VKScheduler& scheduler_, VKDescriptorPool& descriptor_pool_, | 141 | VKScheduler& scheduler_, VKDescriptorPool& descriptor_pool_, |
| 82 | VKUpdateDescriptorQueue& update_descriptor_queue_) | 142 | VKUpdateDescriptorQueue& update_descriptor_queue_) |
| 83 | : VideoCommon::ShaderCache<Shader>{rasterizer_}, gpu{gpu_}, maxwell3d{maxwell3d_}, | 143 | : VideoCommon::ShaderCache<ShaderInfo>{rasterizer_}, gpu{gpu_}, maxwell3d{maxwell3d_}, |
| 84 | kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_}, device{device_}, | 144 | kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_}, device{device_}, |
| 85 | scheduler{scheduler_}, descriptor_pool{descriptor_pool_}, update_descriptor_queue{ | 145 | scheduler{scheduler_}, descriptor_pool{descriptor_pool_}, update_descriptor_queue{ |
| 86 | update_descriptor_queue_} {} | 146 | update_descriptor_queue_} {} |
| 87 | 147 | ||
| 88 | PipelineCache::~PipelineCache() = default; | 148 | PipelineCache::~PipelineCache() = default; |
| 89 | 149 | ||
| 90 | ComputePipeline& PipelineCache::GetComputePipeline(const ComputePipelineCacheKey& key) { | 150 | ComputePipeline* PipelineCache::CurrentComputePipeline() { |
| 91 | MICROPROFILE_SCOPE(Vulkan_PipelineCache); | 151 | MICROPROFILE_SCOPE(Vulkan_PipelineCache); |
| 92 | 152 | ||
| 93 | const auto [pair, is_cache_miss] = compute_cache.try_emplace(key); | 153 | const GPUVAddr program_base{kepler_compute.regs.code_loc.Address()}; |
| 94 | auto& entry = pair->second; | 154 | const auto& qmd{kepler_compute.launch_description}; |
| 95 | if (!is_cache_miss) { | 155 | const GPUVAddr shader_addr{program_base + qmd.program_start}; |
| 96 | return *entry; | 156 | const std::optional<VAddr> cpu_shader_addr{gpu_memory.GpuToCpuAddress(shader_addr)}; |
| 157 | if (!cpu_shader_addr) { | ||
| 158 | return nullptr; | ||
| 159 | } | ||
| 160 | ShaderInfo* const shader{TryGet(*cpu_shader_addr)}; | ||
| 161 | if (!shader) { | ||
| 162 | return CreateComputePipelineWithoutShader(*cpu_shader_addr); | ||
| 163 | } | ||
| 164 | const ComputePipelineCacheKey key{MakeComputePipelineKey(shader->unique_hash)}; | ||
| 165 | const auto [pair, is_new]{compute_cache.try_emplace(key)}; | ||
| 166 | auto& pipeline{pair->second}; | ||
| 167 | if (!is_new) { | ||
| 168 | return &pipeline; | ||
| 169 | } | ||
| 170 | pipeline = CreateComputePipeline(shader); | ||
| 171 | shader->compute_users.push_back(key); | ||
| 172 | return &pipeline; | ||
| 173 | } | ||
| 174 | |||
| 175 | ComputePipeline PipelineCache::CreateComputePipeline(ShaderInfo* shader_info) { | ||
| 176 | const GPUVAddr program_base{kepler_compute.regs.code_loc.Address()}; | ||
| 177 | const auto& qmd{kepler_compute.launch_description}; | ||
| 178 | Environment env{kepler_compute, gpu_memory, program_base}; | ||
| 179 | if (const std::optional<u128> cached_hash{env.Analyze(qmd.program_start)}) { | ||
| 180 | // TODO: Load from cache | ||
| 97 | } | 181 | } |
| 98 | LOG_INFO(Render_Vulkan, "Compile 0x{:016X}", key.Hash()); | 182 | const auto [info, code]{Shader::RecompileSPIRV(env, qmd.program_start)}; |
| 99 | throw "Bad"; | 183 | shader_info->unique_hash = env.ComputeHash(); |
| 184 | shader_info->size_bytes = env.ShaderSize(); | ||
| 185 | return ComputePipeline{device, descriptor_pool, update_descriptor_queue, info, | ||
| 186 | BuildShader(device, code)}; | ||
| 100 | } | 187 | } |
| 101 | 188 | ||
| 102 | void PipelineCache::OnShaderRemoval(Shader*) {} | 189 | ComputePipeline* PipelineCache::CreateComputePipelineWithoutShader(VAddr shader_cpu_addr) { |
| 190 | ShaderInfo shader; | ||
| 191 | ComputePipeline pipeline{CreateComputePipeline(&shader)}; | ||
| 192 | const ComputePipelineCacheKey key{MakeComputePipelineKey(shader.unique_hash)}; | ||
| 193 | shader.compute_users.push_back(key); | ||
| 194 | pipeline.AddRef(); | ||
| 195 | |||
| 196 | const size_t size_bytes{shader.size_bytes}; | ||
| 197 | Register(std::make_unique<ShaderInfo>(std::move(shader)), shader_cpu_addr, size_bytes); | ||
| 198 | return &compute_cache.emplace(key, std::move(pipeline)).first->second; | ||
| 199 | } | ||
| 200 | |||
| 201 | ComputePipelineCacheKey PipelineCache::MakeComputePipelineKey(u128 unique_hash) const { | ||
| 202 | const auto& qmd{kepler_compute.launch_description}; | ||
| 203 | return { | ||
| 204 | .unique_hash = unique_hash, | ||
| 205 | .shared_memory_size = qmd.shared_alloc, | ||
| 206 | .workgroup_size{qmd.block_dim_x, qmd.block_dim_y, qmd.block_dim_z}, | ||
| 207 | }; | ||
| 208 | } | ||
| 209 | |||
| 210 | void PipelineCache::OnShaderRemoval(ShaderInfo* shader) { | ||
| 211 | for (const ComputePipelineCacheKey& key : shader->compute_users) { | ||
| 212 | const auto it = compute_cache.find(key); | ||
| 213 | ASSERT(it != compute_cache.end()); | ||
| 214 | |||
| 215 | Pipeline& pipeline = it->second; | ||
| 216 | if (pipeline.RemoveRef()) { | ||
| 217 | // Wait for the pipeline to be free of GPU usage before destroying it | ||
| 218 | scheduler.Wait(pipeline.UsageTick()); | ||
| 219 | compute_cache.erase(it); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | } | ||
| 103 | 223 | ||
| 104 | } // namespace Vulkan | 224 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index e3e63340d..eb35abc27 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -36,7 +36,7 @@ class VKUpdateDescriptorQueue; | |||
| 36 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 36 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 37 | 37 | ||
| 38 | struct ComputePipelineCacheKey { | 38 | struct ComputePipelineCacheKey { |
| 39 | GPUVAddr shader; | 39 | u128 unique_hash; |
| 40 | u32 shared_memory_size; | 40 | u32 shared_memory_size; |
| 41 | std::array<u32, 3> workgroup_size; | 41 | std::array<u32, 3> workgroup_size; |
| 42 | 42 | ||
| @@ -67,13 +67,13 @@ struct hash<Vulkan::ComputePipelineCacheKey> { | |||
| 67 | 67 | ||
| 68 | namespace Vulkan { | 68 | namespace Vulkan { |
| 69 | 69 | ||
| 70 | class Shader { | 70 | struct ShaderInfo { |
| 71 | public: | 71 | u128 unique_hash{}; |
| 72 | explicit Shader(); | 72 | size_t size_bytes{}; |
| 73 | ~Shader(); | 73 | std::vector<ComputePipelineCacheKey> compute_users; |
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| 76 | class PipelineCache final : public VideoCommon::ShaderCache<Shader> { | 76 | class PipelineCache final : public VideoCommon::ShaderCache<ShaderInfo> { |
| 77 | public: | 77 | public: |
| 78 | explicit PipelineCache(RasterizerVulkan& rasterizer, Tegra::GPU& gpu, | 78 | explicit PipelineCache(RasterizerVulkan& rasterizer, Tegra::GPU& gpu, |
| 79 | Tegra::Engines::Maxwell3D& maxwell3d, | 79 | Tegra::Engines::Maxwell3D& maxwell3d, |
| @@ -83,12 +83,18 @@ public: | |||
| 83 | VKUpdateDescriptorQueue& update_descriptor_queue); | 83 | VKUpdateDescriptorQueue& update_descriptor_queue); |
| 84 | ~PipelineCache() override; | 84 | ~PipelineCache() override; |
| 85 | 85 | ||
| 86 | ComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key); | 86 | [[nodiscard]] ComputePipeline* CurrentComputePipeline(); |
| 87 | 87 | ||
| 88 | protected: | 88 | protected: |
| 89 | void OnShaderRemoval(Shader* shader) final; | 89 | void OnShaderRemoval(ShaderInfo* shader) override; |
| 90 | 90 | ||
| 91 | private: | 91 | private: |
| 92 | ComputePipeline CreateComputePipeline(ShaderInfo* shader); | ||
| 93 | |||
| 94 | ComputePipeline* CreateComputePipelineWithoutShader(VAddr shader_cpu_addr); | ||
| 95 | |||
| 96 | ComputePipelineCacheKey MakeComputePipelineKey(u128 unique_hash) const; | ||
| 97 | |||
| 92 | Tegra::GPU& gpu; | 98 | Tegra::GPU& gpu; |
| 93 | Tegra::Engines::Maxwell3D& maxwell3d; | 99 | Tegra::Engines::Maxwell3D& maxwell3d; |
| 94 | Tegra::Engines::KeplerCompute& kepler_compute; | 100 | Tegra::Engines::KeplerCompute& kepler_compute; |
| @@ -99,13 +105,7 @@ private: | |||
| 99 | VKDescriptorPool& descriptor_pool; | 105 | VKDescriptorPool& descriptor_pool; |
| 100 | VKUpdateDescriptorQueue& update_descriptor_queue; | 106 | VKUpdateDescriptorQueue& update_descriptor_queue; |
| 101 | 107 | ||
| 102 | std::unique_ptr<Shader> null_shader; | 108 | std::unordered_map<ComputePipelineCacheKey, ComputePipeline> compute_cache; |
| 103 | std::unique_ptr<Shader> null_kernel; | ||
| 104 | |||
| 105 | std::array<Shader*, Maxwell::MaxShaderProgram> last_shaders{}; | ||
| 106 | |||
| 107 | std::mutex pipeline_cache; | ||
| 108 | std::unordered_map<ComputePipelineCacheKey, std::unique_ptr<ComputePipeline>> compute_cache; | ||
| 109 | }; | 109 | }; |
| 110 | 110 | ||
| 111 | } // namespace Vulkan | 111 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index f152297d9..b757454c4 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -36,6 +36,8 @@ | |||
| 36 | #include "video_core/vulkan_common/vulkan_device.h" | 36 | #include "video_core/vulkan_common/vulkan_device.h" |
| 37 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 37 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 38 | 38 | ||
| 39 | #pragma optimize("", off) | ||
| 40 | |||
| 39 | namespace Vulkan { | 41 | namespace Vulkan { |
| 40 | 42 | ||
| 41 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 43 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| @@ -237,7 +239,26 @@ void RasterizerVulkan::Clear() { | |||
| 237 | } | 239 | } |
| 238 | 240 | ||
| 239 | void RasterizerVulkan::DispatchCompute() { | 241 | void RasterizerVulkan::DispatchCompute() { |
| 240 | UNREACHABLE_MSG("Not implemented"); | 242 | ComputePipeline* const pipeline{pipeline_cache.CurrentComputePipeline()}; |
| 243 | if (!pipeline) { | ||
| 244 | return; | ||
| 245 | } | ||
| 246 | std::scoped_lock lock{buffer_cache.mutex}; | ||
| 247 | update_descriptor_queue.Acquire(); | ||
| 248 | pipeline->ConfigureBufferCache(buffer_cache); | ||
| 249 | const VkDescriptorSet descriptor_set{pipeline->UpdateDescriptorSet()}; | ||
| 250 | |||
| 251 | const auto& qmd{kepler_compute.launch_description}; | ||
| 252 | const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z}; | ||
| 253 | const VkPipeline pipeline_handle{pipeline->Handle()}; | ||
| 254 | const VkPipelineLayout pipeline_layout{pipeline->PipelineLayout()}; | ||
| 255 | scheduler.Record( | ||
| 256 | [pipeline_handle, pipeline_layout, dim, descriptor_set](vk::CommandBuffer cmdbuf) { | ||
| 257 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_handle); | ||
| 258 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, | ||
| 259 | descriptor_set, nullptr); | ||
| 260 | cmdbuf.Dispatch(dim[0], dim[1], dim[2]); | ||
| 261 | }); | ||
| 241 | } | 262 | } |
| 242 | 263 | ||
| 243 | void RasterizerVulkan::ResetCounter(VideoCore::QueryType type) { | 264 | void RasterizerVulkan::ResetCounter(VideoCore::QueryType type) { |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 31017dc2b..3fd03b915 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | 21 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" |
| 22 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 22 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 23 | #include "video_core/renderer_vulkan/vk_fence_manager.h" | 23 | #include "video_core/renderer_vulkan/vk_fence_manager.h" |
| 24 | #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" | ||
| 25 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | 24 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" |
| 26 | #include "video_core/renderer_vulkan/vk_query_cache.h" | 25 | #include "video_core/renderer_vulkan/vk_query_cache.h" |
| 27 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 26 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| @@ -150,8 +149,6 @@ private: | |||
| 150 | BlitImageHelper blit_image; | 149 | BlitImageHelper blit_image; |
| 151 | ASTCDecoderPass astc_decoder_pass; | 150 | ASTCDecoderPass astc_decoder_pass; |
| 152 | 151 | ||
| 153 | GraphicsPipelineCacheKey graphics_key; | ||
| 154 | |||
| 155 | TextureCacheRuntime texture_cache_runtime; | 152 | TextureCacheRuntime texture_cache_runtime; |
| 156 | TextureCache texture_cache; | 153 | TextureCache texture_cache; |
| 157 | BufferCacheRuntime buffer_cache_runtime; | 154 | BufferCacheRuntime buffer_cache_runtime; |
diff --git a/src/video_core/renderer_vulkan/vk_resource_pool.cpp b/src/video_core/renderer_vulkan/vk_resource_pool.cpp index a8bf7bda8..2dd514968 100644 --- a/src/video_core/renderer_vulkan/vk_resource_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_resource_pool.cpp | |||
| @@ -10,18 +10,16 @@ | |||
| 10 | namespace Vulkan { | 10 | namespace Vulkan { |
| 11 | 11 | ||
| 12 | ResourcePool::ResourcePool(MasterSemaphore& master_semaphore_, size_t grow_step_) | 12 | ResourcePool::ResourcePool(MasterSemaphore& master_semaphore_, size_t grow_step_) |
| 13 | : master_semaphore{master_semaphore_}, grow_step{grow_step_} {} | 13 | : master_semaphore{&master_semaphore_}, grow_step{grow_step_} {} |
| 14 | |||
| 15 | ResourcePool::~ResourcePool() = default; | ||
| 16 | 14 | ||
| 17 | size_t ResourcePool::CommitResource() { | 15 | size_t ResourcePool::CommitResource() { |
| 18 | // Refresh semaphore to query updated results | 16 | // Refresh semaphore to query updated results |
| 19 | master_semaphore.Refresh(); | 17 | master_semaphore->Refresh(); |
| 20 | const u64 gpu_tick = master_semaphore.KnownGpuTick(); | 18 | const u64 gpu_tick = master_semaphore->KnownGpuTick(); |
| 21 | const auto search = [this, gpu_tick](size_t begin, size_t end) -> std::optional<size_t> { | 19 | const auto search = [this, gpu_tick](size_t begin, size_t end) -> std::optional<size_t> { |
| 22 | for (size_t iterator = begin; iterator < end; ++iterator) { | 20 | for (size_t iterator = begin; iterator < end; ++iterator) { |
| 23 | if (gpu_tick >= ticks[iterator]) { | 21 | if (gpu_tick >= ticks[iterator]) { |
| 24 | ticks[iterator] = master_semaphore.CurrentTick(); | 22 | ticks[iterator] = master_semaphore->CurrentTick(); |
| 25 | return iterator; | 23 | return iterator; |
| 26 | } | 24 | } |
| 27 | } | 25 | } |
| @@ -36,7 +34,7 @@ size_t ResourcePool::CommitResource() { | |||
| 36 | // Both searches failed, the pool is full; handle it. | 34 | // Both searches failed, the pool is full; handle it. |
| 37 | const size_t free_resource = ManageOverflow(); | 35 | const size_t free_resource = ManageOverflow(); |
| 38 | 36 | ||
| 39 | ticks[free_resource] = master_semaphore.CurrentTick(); | 37 | ticks[free_resource] = master_semaphore->CurrentTick(); |
| 40 | found = free_resource; | 38 | found = free_resource; |
| 41 | } | 39 | } |
| 42 | } | 40 | } |
diff --git a/src/video_core/renderer_vulkan/vk_resource_pool.h b/src/video_core/renderer_vulkan/vk_resource_pool.h index 9d0bb3b4d..f0b80ad59 100644 --- a/src/video_core/renderer_vulkan/vk_resource_pool.h +++ b/src/video_core/renderer_vulkan/vk_resource_pool.h | |||
| @@ -18,8 +18,16 @@ class MasterSemaphore; | |||
| 18 | */ | 18 | */ |
| 19 | class ResourcePool { | 19 | class ResourcePool { |
| 20 | public: | 20 | public: |
| 21 | explicit ResourcePool() = default; | ||
| 21 | explicit ResourcePool(MasterSemaphore& master_semaphore, size_t grow_step); | 22 | explicit ResourcePool(MasterSemaphore& master_semaphore, size_t grow_step); |
| 22 | virtual ~ResourcePool(); | 23 | |
| 24 | virtual ~ResourcePool() = default; | ||
| 25 | |||
| 26 | ResourcePool& operator=(ResourcePool&&) noexcept = default; | ||
| 27 | ResourcePool(ResourcePool&&) noexcept = default; | ||
| 28 | |||
| 29 | ResourcePool& operator=(const ResourcePool&) = default; | ||
| 30 | ResourcePool(const ResourcePool&) = default; | ||
| 23 | 31 | ||
| 24 | protected: | 32 | protected: |
| 25 | size_t CommitResource(); | 33 | size_t CommitResource(); |
| @@ -34,7 +42,7 @@ private: | |||
| 34 | /// Allocates a new page of resources. | 42 | /// Allocates a new page of resources. |
| 35 | void Grow(); | 43 | void Grow(); |
| 36 | 44 | ||
| 37 | MasterSemaphore& master_semaphore; | 45 | MasterSemaphore* master_semaphore{}; |
| 38 | size_t grow_step = 0; ///< Number of new resources created after an overflow | 46 | size_t grow_step = 0; ///< Number of new resources created after an overflow |
| 39 | size_t hint_iterator = 0; ///< Hint to where the next free resources is likely to be found | 47 | size_t hint_iterator = 0; ///< Hint to where the next free resources is likely to be found |
| 40 | std::vector<u64> ticks; ///< Ticks for each resource | 48 | std::vector<u64> ticks; ///< Ticks for each resource |