1 // Copyright 2018 The Amber Authors. 2 // Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #ifndef SRC_VULKAN_PIPELINE_H_ 17 #define SRC_VULKAN_PIPELINE_H_ 18 19 #include <memory> 20 #include <string> 21 #include <unordered_map> 22 #include <vector> 23 24 #include "amber/result.h" 25 #include "amber/vulkan_header.h" 26 #include "src/cast_hash.h" 27 #include "src/engine.h" 28 #include "src/vulkan/buffer_backed_descriptor.h" 29 #include "src/vulkan/command_buffer.h" 30 #include "src/vulkan/push_constant.h" 31 #include "src/vulkan/resource.h" 32 33 namespace amber { 34 35 class BufferCommand; 36 37 namespace vulkan { 38 39 class ComputePipeline; 40 class Device; 41 class GraphicsPipeline; 42 class RayTracingPipeline; 43 44 /// Base class for a pipeline in Vulkan. 45 class Pipeline { 46 public: 47 virtual ~Pipeline(); 48 IsGraphics()49 bool IsGraphics() const { return pipeline_type_ == PipelineType::kGraphics; } IsCompute()50 bool IsCompute() const { return pipeline_type_ == PipelineType::kCompute; } IsRayTracing()51 bool IsRayTracing() const { 52 return pipeline_type_ == PipelineType::kRayTracing; 53 } 54 55 GraphicsPipeline* AsGraphics(); 56 ComputePipeline* AsCompute(); 57 RayTracingPipeline* AsRayTracingPipeline(); 58 59 Result AddBufferDescriptor(const BufferCommand*); 60 Result AddSamplerDescriptor(const SamplerCommand*); 61 Result AddTLASDescriptor(const TLASCommand*); 62 63 /// Add |buffer| data to the push constants at |offset|. 64 Result AddPushConstantBuffer(const Buffer* buf, uint32_t offset); 65 66 /// Reads back the contents of resources of all descriptors to a 67 /// buffer data object and put it into buffer data queue in host. 68 Result ReadbackDescriptorsToHostDataQueue(); 69 70 std::unordered_map<Buffer*, std::unique_ptr<Resource>>& GetDescriptorTransferResources()71 GetDescriptorTransferResources() { 72 return descriptor_transfer_resources_; 73 } 74 SetEntryPointName(VkShaderStageFlagBits stage,const std::string & entry)75 void SetEntryPointName(VkShaderStageFlagBits stage, 76 const std::string& entry) { 77 entry_points_[stage] = entry; 78 } 79 GetCommandBuffer()80 CommandBuffer* GetCommandBuffer() const { return command_.get(); } GetDevice()81 Device* GetDevice() const { return device_; } GetBlases()82 virtual BlasesMap* GetBlases() { return nullptr; } GetTlases()83 virtual TlasesMap* GetTlases() { return nullptr; } GetVkPipelineLayout()84 VkPipelineLayout GetVkPipelineLayout() const { return pipeline_layout_; } GetVkPipeline()85 VkPipeline GetVkPipeline() const { return pipeline_; } 86 87 protected: 88 Pipeline( 89 PipelineType type, 90 Device* device, 91 uint32_t fence_timeout_ms, 92 bool pipeline_runtime_layer_enabled, 93 const std::vector<VkPipelineShaderStageCreateInfo>& shader_stage_info, 94 VkPipelineCreateFlags create_flags = 0); 95 96 /// Initializes the pipeline. 97 Result Initialize(CommandPool* pool); 98 99 Result GetDescriptorSlot(uint32_t desc_set, 100 uint32_t binding, 101 Descriptor** desc); 102 void UpdateDescriptorSetsIfNeeded(); 103 104 // This functions are used in benchmarking when 'TIMED_EXECUTION' option is 105 // specifed. 106 void CreateTimingQueryObjectIfNeeded(bool is_timed_execution); 107 void DestroyTimingQueryObjectIfNeeded(); 108 void BeginTimerQuery(); 109 void EndTimerQuery(); 110 111 Result SendDescriptorDataToDeviceIfNeeded(); 112 void BindVkDescriptorSets(const VkPipelineLayout& pipeline_layout); 113 114 /// Records a Vulkan command for push contant. 115 Result RecordPushConstant(const VkPipelineLayout& pipeline_layout); 116 GetVkShaderStageInfo()117 const std::vector<VkPipelineShaderStageCreateInfo>& GetVkShaderStageInfo() 118 const { 119 return shader_stage_info_; 120 } 121 122 const char* GetEntryPointName(VkShaderStageFlagBits stage) const; GetFenceTimeout()123 uint32_t GetFenceTimeout() const { return fence_timeout_ms_; } GetPipelineRuntimeLayerEnabled()124 bool GetPipelineRuntimeLayerEnabled() const { 125 return pipeline_runtime_layer_enabled_; 126 } 127 128 Result CreateVkPipelineLayout(VkPipelineLayout* pipeline_layout); 129 SetVkPipelineLayout(VkPipelineLayout pipeline_layout)130 void SetVkPipelineLayout(VkPipelineLayout pipeline_layout) { 131 assert(pipeline_layout_ == VK_NULL_HANDLE); 132 pipeline_layout_ = pipeline_layout; 133 } 134 SetVkPipeline(VkPipeline pipeline)135 void SetVkPipeline(VkPipeline pipeline) { 136 assert(pipeline_ == VK_NULL_HANDLE); 137 pipeline_ = pipeline; 138 } 139 140 VkQueryPool query_pool_ = VK_NULL_HANDLE; 141 VkPipeline pipeline_ = VK_NULL_HANDLE; 142 VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE; 143 144 Device* device_ = nullptr; 145 std::unique_ptr<CommandBuffer> command_; 146 VkPipelineCreateFlags create_flags_ = 0; 147 148 private: 149 struct DescriptorSetInfo { 150 bool empty = true; 151 VkDescriptorSetLayout layout = VK_NULL_HANDLE; 152 VkDescriptorPool pool = VK_NULL_HANDLE; 153 VkDescriptorSet vk_desc_set = VK_NULL_HANDLE; 154 std::vector<std::unique_ptr<Descriptor>> descriptors; 155 }; 156 157 /// Creates Vulkan descriptor related objects. 158 Result CreateVkDescriptorRelatedObjectsIfNeeded(); 159 Result CreateDescriptorSetLayouts(); 160 Result CreateDescriptorPools(); 161 Result CreateDescriptorSets(); 162 /// Adds a buffer used by a descriptor. The added buffers are be stored in 163 /// |descriptor_buffers_| vector in the order they are added. 164 Result AddDescriptorBuffer(Buffer* amber_buffer); 165 166 PipelineType pipeline_type_; 167 std::vector<DescriptorSetInfo> descriptor_set_info_; 168 std::vector<VkPipelineShaderStageCreateInfo> shader_stage_info_; 169 std::unordered_map<Buffer*, std::unique_ptr<Resource>> 170 descriptor_transfer_resources_; 171 /// Buffers used by descriptors (buffer descriptors and image descriptors). 172 std::vector<Buffer*> descriptor_buffers_; 173 174 uint32_t fence_timeout_ms_ = 1000; 175 bool pipeline_runtime_layer_enabled_ = false; 176 bool descriptor_related_objects_already_created_ = false; 177 std::unordered_map<VkShaderStageFlagBits, 178 std::string, 179 CastHash<VkShaderStageFlagBits>> 180 entry_points_; 181 182 std::unique_ptr<PushConstant> push_constant_; 183 bool in_timed_execution_ = false; 184 }; 185 186 } // namespace vulkan 187 } // namespace amber 188 189 #endif // SRC_VULKAN_PIPELINE_H_ 190