• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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