1 // Copyright 2018 The Amber Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/vulkan/compute_pipeline.h"
16 #include <cstdint>
17
18 #include "src/vulkan/command_pool.h"
19 #include "src/vulkan/device.h"
20
21 namespace amber {
22 namespace vulkan {
23
ComputePipeline(Device * device,uint32_t fence_timeout_ms,bool pipeline_runtime_layer_enabled,const std::vector<VkPipelineShaderStageCreateInfo> & shader_stage_info)24 ComputePipeline::ComputePipeline(
25 Device* device,
26 uint32_t fence_timeout_ms,
27 bool pipeline_runtime_layer_enabled,
28 const std::vector<VkPipelineShaderStageCreateInfo>& shader_stage_info)
29 : Pipeline(PipelineType::kCompute,
30 device,
31 fence_timeout_ms,
32 pipeline_runtime_layer_enabled,
33 shader_stage_info) {}
34
35 ComputePipeline::~ComputePipeline() = default;
36
Initialize(CommandPool * pool)37 Result ComputePipeline::Initialize(CommandPool* pool) {
38 return Pipeline::Initialize(pool);
39 }
40
CreateVkComputePipeline(const VkPipelineLayout & pipeline_layout,VkPipeline * pipeline)41 Result ComputePipeline::CreateVkComputePipeline(
42 const VkPipelineLayout& pipeline_layout,
43 VkPipeline* pipeline) {
44 auto shader_stage_info = GetVkShaderStageInfo();
45 if (shader_stage_info.size() != 1) {
46 return Result(
47 "Vulkan::CreateVkComputePipeline number of shaders given to compute "
48 "pipeline is not 1");
49 }
50
51 if (shader_stage_info[0].stage != VK_SHADER_STAGE_COMPUTE_BIT)
52 return Result("Vulkan: Non compute shader for compute pipeline");
53
54 shader_stage_info[0].pName = GetEntryPointName(VK_SHADER_STAGE_COMPUTE_BIT);
55
56 VkComputePipelineCreateInfo pipeline_info = VkComputePipelineCreateInfo();
57 pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
58 pipeline_info.stage = shader_stage_info[0];
59 pipeline_info.layout = pipeline_layout;
60
61 if (device_->GetPtrs()->vkCreateComputePipelines(
62 device_->GetVkDevice(), VK_NULL_HANDLE, 1, &pipeline_info, nullptr,
63 pipeline) != VK_SUCCESS) {
64 return Result("Vulkan::Calling vkCreateComputePipelines Fail");
65 }
66
67 return {};
68 }
69
Compute(uint32_t x,uint32_t y,uint32_t z,bool is_timed_execution)70 Result ComputePipeline::Compute(uint32_t x,
71 uint32_t y,
72 uint32_t z,
73 bool is_timed_execution) {
74 Result r = SendDescriptorDataToDeviceIfNeeded();
75 if (!r.IsSuccess())
76 return r;
77
78 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
79 r = CreateVkPipelineLayout(&pipeline_layout);
80 if (!r.IsSuccess())
81 return r;
82
83 VkPipeline pipeline = VK_NULL_HANDLE;
84 r = CreateVkComputePipeline(pipeline_layout, &pipeline);
85 if (!r.IsSuccess())
86 return r;
87
88 // Note that a command updating a descriptor set and a command using
89 // it must be submitted separately, because using a descriptor set
90 // while updating it is not safe.
91 UpdateDescriptorSetsIfNeeded();
92 CreateTimingQueryObjectIfNeeded(is_timed_execution);
93 {
94 CommandBufferGuard guard(GetCommandBuffer());
95 if (!guard.IsRecording())
96 return guard.GetResult();
97
98 BindVkDescriptorSets(pipeline_layout);
99
100 r = RecordPushConstant(pipeline_layout);
101 if (!r.IsSuccess())
102 return r;
103
104 device_->GetPtrs()->vkCmdBindPipeline(command_->GetVkCommandBuffer(),
105 VK_PIPELINE_BIND_POINT_COMPUTE,
106 pipeline);
107 BeginTimerQuery();
108 device_->GetPtrs()->vkCmdDispatch(command_->GetVkCommandBuffer(), x, y, z);
109 EndTimerQuery();
110
111 r = guard.Submit(GetFenceTimeout(), GetPipelineRuntimeLayerEnabled());
112 if (!r.IsSuccess())
113 return r;
114 }
115 DestroyTimingQueryObjectIfNeeded();
116 r = ReadbackDescriptorsToHostDataQueue();
117 if (!r.IsSuccess())
118 return r;
119
120 device_->GetPtrs()->vkDestroyPipeline(device_->GetVkDevice(), pipeline,
121 nullptr);
122 device_->GetPtrs()->vkDestroyPipelineLayout(device_->GetVkDevice(),
123 pipeline_layout, nullptr);
124
125 return {};
126 }
127
128 } // namespace vulkan
129 } // namespace amber
130