summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp112
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.h66
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.h39
4 files changed, 219 insertions, 0 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index efdd2c902..61ac0f23a 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -155,6 +155,8 @@ if (ENABLE_VULKAN)
155 renderer_vulkan/maxwell_to_vk.h 155 renderer_vulkan/maxwell_to_vk.h
156 renderer_vulkan/vk_buffer_cache.cpp 156 renderer_vulkan/vk_buffer_cache.cpp
157 renderer_vulkan/vk_buffer_cache.h 157 renderer_vulkan/vk_buffer_cache.h
158 renderer_vulkan/vk_compute_pipeline.cpp
159 renderer_vulkan/vk_compute_pipeline.h
158 renderer_vulkan/vk_descriptor_pool.cpp 160 renderer_vulkan/vk_descriptor_pool.cpp
159 renderer_vulkan/vk_descriptor_pool.h 161 renderer_vulkan/vk_descriptor_pool.h
160 renderer_vulkan/vk_device.cpp 162 renderer_vulkan/vk_device.cpp
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
new file mode 100644
index 000000000..9d5b8de7a
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -0,0 +1,112 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <memory>
6#include <vector>
7
8#include "video_core/renderer_vulkan/declarations.h"
9#include "video_core/renderer_vulkan/vk_compute_pipeline.h"
10#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
11#include "video_core/renderer_vulkan/vk_device.h"
12#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
13#include "video_core/renderer_vulkan/vk_resource_manager.h"
14#include "video_core/renderer_vulkan/vk_scheduler.h"
15#include "video_core/renderer_vulkan/vk_shader_decompiler.h"
16#include "video_core/renderer_vulkan/vk_update_descriptor.h"
17
18namespace Vulkan {
19
20VKComputePipeline::VKComputePipeline(const VKDevice& device, VKScheduler& scheduler,
21 VKDescriptorPool& descriptor_pool,
22 VKUpdateDescriptorQueue& update_descriptor_queue,
23 const SPIRVShader& shader)
24 : device{device}, scheduler{scheduler}, entries{shader.entries},
25 descriptor_set_layout{CreateDescriptorSetLayout()},
26 descriptor_allocator{descriptor_pool, *descriptor_set_layout},
27 update_descriptor_queue{update_descriptor_queue}, layout{CreatePipelineLayout()},
28 descriptor_template{CreateDescriptorUpdateTemplate()},
29 shader_module{CreateShaderModule(shader.code)}, pipeline{CreatePipeline()} {}
30
31VKComputePipeline::~VKComputePipeline() = default;
32
33vk::DescriptorSet VKComputePipeline::CommitDescriptorSet() {
34 if (!descriptor_template) {
35 return {};
36 }
37 const auto set = descriptor_allocator.Commit(scheduler.GetFence());
38 update_descriptor_queue.Send(*descriptor_template, set);
39 return set;
40}
41
42UniqueDescriptorSetLayout VKComputePipeline::CreateDescriptorSetLayout() const {
43 std::vector<vk::DescriptorSetLayoutBinding> bindings;
44 u32 binding = 0;
45 const auto AddBindings = [&](vk::DescriptorType descriptor_type, std::size_t num_entries) {
46 // TODO(Rodrigo): Maybe make individual bindings here?
47 for (u32 bindpoint = 0; bindpoint < static_cast<u32>(num_entries); ++bindpoint) {
48 bindings.emplace_back(binding++, descriptor_type, 1, vk::ShaderStageFlagBits::eCompute,
49 nullptr);
50 }
51 };
52 AddBindings(vk::DescriptorType::eUniformBuffer, entries.const_buffers.size());
53 AddBindings(vk::DescriptorType::eStorageBuffer, entries.global_buffers.size());
54 AddBindings(vk::DescriptorType::eUniformTexelBuffer, entries.texel_buffers.size());
55 AddBindings(vk::DescriptorType::eCombinedImageSampler, entries.samplers.size());
56 AddBindings(vk::DescriptorType::eStorageImage, entries.images.size());
57
58 const vk::DescriptorSetLayoutCreateInfo descriptor_set_layout_ci(
59 {}, static_cast<u32>(bindings.size()), bindings.data());
60
61 const auto dev = device.GetLogical();
62 const auto& dld = device.GetDispatchLoader();
63 return dev.createDescriptorSetLayoutUnique(descriptor_set_layout_ci, nullptr, dld);
64}
65
66UniquePipelineLayout VKComputePipeline::CreatePipelineLayout() const {
67 const vk::PipelineLayoutCreateInfo layout_ci({}, 1, &*descriptor_set_layout, 0, nullptr);
68 const auto dev = device.GetLogical();
69 return dev.createPipelineLayoutUnique(layout_ci, nullptr, device.GetDispatchLoader());
70}
71
72UniqueDescriptorUpdateTemplate VKComputePipeline::CreateDescriptorUpdateTemplate() const {
73 std::vector<vk::DescriptorUpdateTemplateEntry> template_entries;
74 u32 binding = 0;
75 u32 offset = 0;
76 FillDescriptorUpdateTemplateEntries(device, entries, binding, offset, template_entries);
77 if (template_entries.empty()) {
78 // If the shader doesn't use descriptor sets, skip template creation.
79 return UniqueDescriptorUpdateTemplate{};
80 }
81
82 const vk::DescriptorUpdateTemplateCreateInfo template_ci(
83 {}, static_cast<u32>(template_entries.size()), template_entries.data(),
84 vk::DescriptorUpdateTemplateType::eDescriptorSet, *descriptor_set_layout,
85 vk::PipelineBindPoint::eGraphics, *layout, DESCRIPTOR_SET);
86
87 const auto dev = device.GetLogical();
88 const auto& dld = device.GetDispatchLoader();
89 return dev.createDescriptorUpdateTemplateUnique(template_ci, nullptr, dld);
90}
91
92UniqueShaderModule VKComputePipeline::CreateShaderModule(const std::vector<u32>& code) const {
93 const vk::ShaderModuleCreateInfo module_ci({}, code.size() * sizeof(u32), code.data());
94 const auto dev = device.GetLogical();
95 return dev.createShaderModuleUnique(module_ci, nullptr, device.GetDispatchLoader());
96}
97
98UniquePipeline VKComputePipeline::CreatePipeline() const {
99 vk::PipelineShaderStageCreateInfo shader_stage_ci({}, vk::ShaderStageFlagBits::eCompute,
100 *shader_module, "main", nullptr);
101 vk::PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci;
102 subgroup_size_ci.requiredSubgroupSize = GuestWarpSize;
103 if (entries.uses_warps && device.IsGuestWarpSizeSupported(vk::ShaderStageFlagBits::eCompute)) {
104 shader_stage_ci.pNext = &subgroup_size_ci;
105 }
106
107 const vk::ComputePipelineCreateInfo create_info({}, shader_stage_ci, *layout, {}, 0);
108 const auto dev = device.GetLogical();
109 return dev.createComputePipelineUnique({}, create_info, nullptr, device.GetDispatchLoader());
110}
111
112} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
new file mode 100644
index 000000000..22235c6c9
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
@@ -0,0 +1,66 @@
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 <memory>
8
9#include "common/common_types.h"
10#include "video_core/renderer_vulkan/declarations.h"
11#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
12#include "video_core/renderer_vulkan/vk_shader_decompiler.h"
13
14namespace Vulkan {
15
16class VKDevice;
17class VKScheduler;
18class VKUpdateDescriptorQueue;
19
20class VKComputePipeline final {
21public:
22 explicit VKComputePipeline(const VKDevice& device, VKScheduler& scheduler,
23 VKDescriptorPool& descriptor_pool,
24 VKUpdateDescriptorQueue& update_descriptor_queue,
25 const SPIRVShader& shader);
26 ~VKComputePipeline();
27
28 vk::DescriptorSet CommitDescriptorSet();
29
30 vk::Pipeline GetHandle() const {
31 return *pipeline;
32 }
33
34 vk::PipelineLayout GetLayout() const {
35 return *layout;
36 }
37
38 const ShaderEntries& GetEntries() {
39 return entries;
40 }
41
42private:
43 UniqueDescriptorSetLayout CreateDescriptorSetLayout() const;
44
45 UniquePipelineLayout CreatePipelineLayout() const;
46
47 UniqueDescriptorUpdateTemplate CreateDescriptorUpdateTemplate() const;
48
49 UniqueShaderModule CreateShaderModule(const std::vector<u32>& code) const;
50
51 UniquePipeline CreatePipeline() const;
52
53 const VKDevice& device;
54 VKScheduler& scheduler;
55 ShaderEntries entries;
56
57 UniqueDescriptorSetLayout descriptor_set_layout;
58 DescriptorAllocator descriptor_allocator;
59 VKUpdateDescriptorQueue& update_descriptor_queue;
60 UniquePipelineLayout layout;
61 UniqueDescriptorUpdateTemplate descriptor_template;
62 UniqueShaderModule shader_module;
63 UniquePipeline pipeline;
64};
65
66} // 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 532ee45cc..33b1a1d23 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
@@ -4,9 +4,12 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include <cstddef>
7#include <vector> 9#include <vector>
8 10
9#include "common/common_types.h" 11#include "common/common_types.h"
12#include "video_core/engines/maxwell_3d.h"
10#include "video_core/renderer_vulkan/declarations.h" 13#include "video_core/renderer_vulkan/declarations.h"
11#include "video_core/renderer_vulkan/vk_shader_decompiler.h" 14#include "video_core/renderer_vulkan/vk_shader_decompiler.h"
12#include "video_core/shader/shader_ir.h" 15#include "video_core/shader/shader_ir.h"
@@ -15,6 +18,42 @@ namespace Vulkan {
15 18
16class VKDevice; 19class VKDevice;
17 20
21struct ComputePipelineCacheKey {
22 GPUVAddr shader{};
23 u32 shared_memory_size{};
24 std::array<u32, 3> workgroup_size{};
25
26 std::size_t Hash() const noexcept {
27 return static_cast<std::size_t>(shader) ^
28 ((static_cast<std::size_t>(shared_memory_size) >> 7) << 40) ^
29 static_cast<std::size_t>(workgroup_size[0]) ^
30 (static_cast<std::size_t>(workgroup_size[1]) << 16) ^
31 (static_cast<std::size_t>(workgroup_size[2]) << 24);
32 }
33
34 bool operator==(const ComputePipelineCacheKey& rhs) const noexcept {
35 return std::tie(shader, shared_memory_size, workgroup_size) ==
36 std::tie(rhs.shader, rhs.shared_memory_size, rhs.workgroup_size);
37 }
38};
39
40} // namespace Vulkan
41
42namespace std {
43
44template <>
45struct hash<Vulkan::ComputePipelineCacheKey> {
46 std::size_t operator()(const Vulkan::ComputePipelineCacheKey& k) const noexcept {
47 return k.Hash();
48 }
49};
50
51} // namespace std
52
53namespace Vulkan {
54
55class VKDevice;
56
18void FillDescriptorUpdateTemplateEntries( 57void FillDescriptorUpdateTemplateEntries(
19 const VKDevice& device, const ShaderEntries& entries, u32& binding, u32& offset, 58 const VKDevice& device, const ShaderEntries& entries, u32& binding, u32& offset,
20 std::vector<vk::DescriptorUpdateTemplateEntry>& template_entries); 59 std::vector<vk::DescriptorUpdateTemplateEntry>& template_entries);