diff options
author | Jaebaek Seo <duke.acacia@gmail.com> | 2018-11-26 22:39:31 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-26 22:39:31 -0500 |
commit | 3a6f620e15e9c14ab6fd71e974549e61c2ca9d6e (patch) | |
tree | cd6ea5142c725dde8c01da7431a976550f593761 | |
parent | da1d01dfca44f24ab1e344f7c531d57735a499ac (diff) | |
download | amber-3a6f620e15e9c14ab6fd71e974549e61c2ca9d6e.tar.gz |
Vulkan: add compute pipeline (#98)
Fixes #13
-rw-r--r-- | src/vulkan/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/vulkan/compute_pipeline.cc | 85 | ||||
-rw-r--r-- | src/vulkan/compute_pipeline.h | 47 | ||||
-rw-r--r-- | src/vulkan/engine_vulkan.cc | 23 | ||||
-rw-r--r-- | src/vulkan/graphics_pipeline.cc | 23 | ||||
-rw-r--r-- | src/vulkan/graphics_pipeline.h | 10 | ||||
-rw-r--r-- | src/vulkan/pipeline.cc | 25 | ||||
-rw-r--r-- | src/vulkan/pipeline.h | 20 | ||||
-rw-r--r-- | tests/cases/compute_nothing.amber | 22 |
9 files changed, 226 insertions, 30 deletions
diff --git a/src/vulkan/CMakeLists.txt b/src/vulkan/CMakeLists.txt index 9c41e39..8a66544 100644 --- a/src/vulkan/CMakeLists.txt +++ b/src/vulkan/CMakeLists.txt @@ -16,6 +16,7 @@ set(VULKAN_ENGINE_SOURCES bit_copy.cc buffer.cc command.cc + compute_pipeline.cc descriptor.cc device.cc engine_vulkan.cc diff --git a/src/vulkan/compute_pipeline.cc b/src/vulkan/compute_pipeline.cc new file mode 100644 index 0000000..bfba88e --- /dev/null +++ b/src/vulkan/compute_pipeline.cc @@ -0,0 +1,85 @@ +// Copyright 2018 The Amber Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/vulkan/compute_pipeline.h" + +namespace amber { +namespace vulkan { + +ComputePipeline::ComputePipeline( + VkDevice device, + const VkPhysicalDeviceMemoryProperties& properties, + uint32_t fence_timeout_ms, + const std::vector<VkPipelineShaderStageCreateInfo>& shader_stage_info) + : Pipeline(PipelineType::kCompute, + device, + properties, + fence_timeout_ms, + shader_stage_info) {} + +ComputePipeline::~ComputePipeline() = default; + +Result ComputePipeline::Initialize(VkCommandPool pool, VkQueue queue) { + return Pipeline::InitializeCommandBuffer(pool, queue); +} + +Result ComputePipeline::CreateVkComputePipeline() { + const auto& shader_stage_info = GetShaderStageInfo(); + if (shader_stage_info.size() != 1) { + return Result( + "Vulkan::CreateVkComputePipeline number of shaders given to compute " + "pipeline is not 1"); + } + + Result r = CreateVkDescriptorRelatedObjects(); + if (!r.IsSuccess()) + return r; + + VkComputePipelineCreateInfo pipeline_info = {}; + pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + pipeline_info.stage = shader_stage_info[0]; + pipeline_info.layout = pipeline_layout_; + + if (vkCreateComputePipelines(device_, VK_NULL_HANDLE, 1, &pipeline_info, + nullptr, &pipeline_) != VK_SUCCESS) { + return Result("Vulkan::Calling vkCreateComputePipelines Fail"); + } + + return {}; +} + +Result ComputePipeline::Compute(uint32_t x, uint32_t y, uint32_t z) { + if (pipeline_ == VK_NULL_HANDLE) { + Result r = CreateVkComputePipeline(); + if (!r.IsSuccess()) + return r; + } + + Result r = command_->BeginIfNotInRecording(); + if (!r.IsSuccess()) + return r; + + r = SendDescriptorDataToGPUIfNeeded(); + if (!r.IsSuccess()) + return r; + + BindVkDescriptorSets(); + BindVkPipeline(); + + vkCmdDispatch(command_->GetCommandBuffer(), x, y, z); + return {}; +} + +} // namespace vulkan +} // namespace amber diff --git a/src/vulkan/compute_pipeline.h b/src/vulkan/compute_pipeline.h new file mode 100644 index 0000000..ddbc39d --- /dev/null +++ b/src/vulkan/compute_pipeline.h @@ -0,0 +1,47 @@ +// Copyright 2018 The Amber Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_VULKAN_COMPUTE_PIPELINE_H_ +#define SRC_VULKAN_COMPUTE_PIPELINE_H_ + +#include <vector> + +#include "amber/result.h" +#include "src/vulkan/pipeline.h" +#include "vulkan/vulkan.h" + +namespace amber { +namespace vulkan { + +class ComputePipeline : public Pipeline { + public: + ComputePipeline( + VkDevice device, + const VkPhysicalDeviceMemoryProperties& properties, + uint32_t fence_timeout_ms, + const std::vector<VkPipelineShaderStageCreateInfo>& shader_stage_info); + ~ComputePipeline() override; + + Result Initialize(VkCommandPool pool, VkQueue queue); + + Result Compute(uint32_t x, uint32_t y, uint32_t z); + + private: + Result CreateVkComputePipeline(); +}; + +} // namespace vulkan +} // namespace amber + +#endif // SRC_VULKAN_COMPUTE_PIPELINE_H_ diff --git a/src/vulkan/engine_vulkan.cc b/src/vulkan/engine_vulkan.cc index abad862..d407ab7 100644 --- a/src/vulkan/engine_vulkan.cc +++ b/src/vulkan/engine_vulkan.cc @@ -18,6 +18,7 @@ #include <cassert> #include "src/make_unique.h" +#include "src/vulkan/compute_pipeline.h" #include "src/vulkan/descriptor.h" #include "src/vulkan/format_data.h" #include "src/vulkan/graphics_pipeline.h" @@ -121,8 +122,13 @@ Result EngineVulkan::AddRequirement(Feature feature, } Result EngineVulkan::CreatePipeline(PipelineType type) { - if (type == PipelineType::kCompute) - return Result("Vulkan::Compute Pipeline Not Implemented"); + if (type == PipelineType::kCompute) { + pipeline_ = MakeUnique<ComputePipeline>( + device_->GetDevice(), device_->GetPhysicalMemoryProperties(), + fence_timeout_ms_, GetShaderStageInfo()); + return pipeline_->AsCompute()->Initialize(pool_->GetCommandPool(), + device_->GetQueue()); + } VkFormat frame_buffer_format = kDefaultColorFormat; auto it_frame_buffer = @@ -146,7 +152,7 @@ Result EngineVulkan::CreatePipeline(PipelineType type) { } pipeline_ = MakeUnique<GraphicsPipeline>( - type, device_->GetDevice(), device_->GetPhysicalMemoryProperties(), + device_->GetDevice(), device_->GetPhysicalMemoryProperties(), frame_buffer_format, depth_stencil_format, fence_timeout_ms_, GetShaderStageInfo()); @@ -157,9 +163,6 @@ Result EngineVulkan::CreatePipeline(PipelineType type) { Result EngineVulkan::SetShader(ShaderType type, const std::vector<uint32_t>& data) { - if (type == ShaderType::kCompute) - return Result("Vulkan::Compute Pipeline Not Implemented"); - VkShaderModuleCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; info.codeSize = data.size() * sizeof(uint32_t); @@ -252,8 +255,12 @@ Result EngineVulkan::DoDrawArrays(const DrawArraysCommand* command) { return pipeline_->AsGraphics()->Draw(command); } -Result EngineVulkan::DoCompute(const ComputeCommand*) { - return Result("Vulkan::DoCompute Not Implemented"); +Result EngineVulkan::DoCompute(const ComputeCommand* command) { + if (pipeline_->IsGraphics()) + return Result("Vulkan: Compute called for graphics pipeline."); + + return pipeline_->AsCompute()->Compute(command->GetX(), command->GetY(), + command->GetZ()); } Result EngineVulkan::DoEntryPoint(const EntryPointCommand*) { diff --git a/src/vulkan/graphics_pipeline.cc b/src/vulkan/graphics_pipeline.cc index 2b61bdc..f330e8c 100644 --- a/src/vulkan/graphics_pipeline.cc +++ b/src/vulkan/graphics_pipeline.cc @@ -103,18 +103,19 @@ VkPrimitiveTopology ToVkTopology(Topology topology) { } // namespace GraphicsPipeline::GraphicsPipeline( - PipelineType type, VkDevice device, const VkPhysicalDeviceMemoryProperties& properties, VkFormat color_format, VkFormat depth_stencil_format, uint32_t fence_timeout_ms, - std::vector<VkPipelineShaderStageCreateInfo> shader_stage_info) - : Pipeline(type, device, properties), + const std::vector<VkPipelineShaderStageCreateInfo>& shader_stage_info) + : Pipeline(PipelineType::kGraphics, + device, + properties, + fence_timeout_ms, + shader_stage_info), color_format_(color_format), - depth_stencil_format_(depth_stencil_format), - shader_stage_info_(shader_stage_info), - fence_timeout_ms_(fence_timeout_ms) {} + depth_stencil_format_(depth_stencil_format) {} GraphicsPipeline::~GraphicsPipeline() = default; @@ -250,10 +251,12 @@ Result GraphicsPipeline::CreateVkGraphicsPipeline( viewport_info.scissorCount = 1; viewport_info.pScissors = &scissor; + const auto& shader_stage_info = GetShaderStageInfo(); + VkGraphicsPipelineCreateInfo pipeline_info = {}; pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipeline_info.stageCount = static_cast<uint32_t>(shader_stage_info_.size()); - pipeline_info.pStages = shader_stage_info_.data(); + pipeline_info.stageCount = static_cast<uint32_t>(shader_stage_info.size()); + pipeline_info.pStages = shader_stage_info.data(); pipeline_info.pVertexInputState = &vertex_input_info; pipeline_info.pInputAssemblyState = &input_assembly_info; pipeline_info.pViewportState = &viewport_info; @@ -519,7 +522,7 @@ Result GraphicsPipeline::ProcessCommands() { if (!r.IsSuccess()) return r; - return command_->SubmitAndReset(fence_timeout_ms_); + return command_->SubmitAndReset(GetFenceTimeout()); } void GraphicsPipeline::Shutdown() { @@ -527,7 +530,7 @@ void GraphicsPipeline::Shutdown() { Result r = command_->End(); if (r.IsSuccess()) - command_->SubmitAndReset(fence_timeout_ms_); + command_->SubmitAndReset(GetFenceTimeout()); Pipeline::Shutdown(); frame_->Shutdown(); diff --git a/src/vulkan/graphics_pipeline.h b/src/vulkan/graphics_pipeline.h index 8368a11..d9c2ef8 100644 --- a/src/vulkan/graphics_pipeline.h +++ b/src/vulkan/graphics_pipeline.h @@ -35,20 +35,18 @@ namespace vulkan { class GraphicsPipeline : public Pipeline { public: - GraphicsPipeline(PipelineType type, - VkDevice device, + GraphicsPipeline(VkDevice device, const VkPhysicalDeviceMemoryProperties& properties, VkFormat color_format, VkFormat depth_stencil_format, uint32_t fence_timeout_ms, - std::vector<VkPipelineShaderStageCreateInfo>); + const std::vector<VkPipelineShaderStageCreateInfo>&); ~GraphicsPipeline() override; Result Initialize(uint32_t width, uint32_t height, VkCommandPool pool, VkQueue queue); - void Shutdown() override; void SetBuffer(BufferType type, uint8_t location, @@ -70,6 +68,9 @@ class GraphicsPipeline : public Pipeline { const FrameBuffer* GetFrame() const { return frame_.get(); } + // Pipeline + void Shutdown() override; + private: enum class RenderPassState : uint8_t { kActive = 0, @@ -104,7 +105,6 @@ class GraphicsPipeline : public Pipeline { std::vector<VkPipelineShaderStageCreateInfo> shader_stage_info_; - uint32_t fence_timeout_ms_ = 100; uint32_t frame_width_ = 0; uint32_t frame_height_ = 0; diff --git a/src/vulkan/pipeline.cc b/src/vulkan/pipeline.cc index 5c92ef0..34b54d4 100644 --- a/src/vulkan/pipeline.cc +++ b/src/vulkan/pipeline.cc @@ -20,16 +20,24 @@ #include "src/command.h" #include "src/make_unique.h" +#include "src/vulkan/compute_pipeline.h" #include "src/vulkan/graphics_pipeline.h" #include "src/vulkan/storage_buffer_descriptor.h" namespace amber { namespace vulkan { -Pipeline::Pipeline(PipelineType type, - VkDevice device, - const VkPhysicalDeviceMemoryProperties& properties) - : device_(device), memory_properties_(properties), pipeline_type_(type) {} +Pipeline::Pipeline( + PipelineType type, + VkDevice device, + const VkPhysicalDeviceMemoryProperties& properties, + uint32_t fence_timeout_ms, + const std::vector<VkPipelineShaderStageCreateInfo>& shader_stage_info) + : device_(device), + memory_properties_(properties), + pipeline_type_(type), + fence_timeout_ms_(fence_timeout_ms), + shader_stage_info_(shader_stage_info) {} Pipeline::~Pipeline() = default; @@ -37,6 +45,10 @@ GraphicsPipeline* Pipeline::AsGraphics() { return static_cast<GraphicsPipeline*>(this); } +ComputePipeline* Pipeline::AsCompute() { + return static_cast<ComputePipeline*>(this); +} + Result Pipeline::InitializeCommandBuffer(VkCommandPool pool, VkQueue queue) { command_ = MakeUnique<CommandBuffer>(device_, pool, queue); Result r = command_->Initialize(); @@ -47,11 +59,16 @@ Result Pipeline::InitializeCommandBuffer(VkCommandPool pool, VkQueue queue) { } void Pipeline::Shutdown() { + Result r = command_->End(); + if (r.IsSuccess()) + command_->SubmitAndReset(fence_timeout_ms_); + // TODO(jaebaek): destroy pipeline_cache_ and pipeline_ DestoryDescriptorPools(); DestoryDescriptorSetLayouts(); command_->Shutdown(); vkDestroyPipelineLayout(device_, pipeline_layout_, nullptr); + vkDestroyPipeline(device_, pipeline_, nullptr); } void Pipeline::DestoryDescriptorSetLayouts() { diff --git a/src/vulkan/pipeline.h b/src/vulkan/pipeline.h index 18c787b..0b806bf 100644 --- a/src/vulkan/pipeline.h +++ b/src/vulkan/pipeline.h @@ -30,6 +30,7 @@ class BufferCommand; namespace vulkan { +class ComputePipeline; class GraphicsPipeline; class Pipeline { @@ -40,15 +41,19 @@ class Pipeline { bool IsCompute() const { return pipeline_type_ == PipelineType::kCompute; } GraphicsPipeline* AsGraphics(); + ComputePipeline* AsCompute(); Result AddDescriptor(const BufferCommand*); virtual void Shutdown(); protected: - Pipeline(PipelineType type, - VkDevice device, - const VkPhysicalDeviceMemoryProperties& properties); + Pipeline( + PipelineType type, + VkDevice device, + const VkPhysicalDeviceMemoryProperties& properties, + uint32_t fence_timeout_ms, + const std::vector<VkPipelineShaderStageCreateInfo>& shader_stage_info); Result InitializeCommandBuffer(VkCommandPool pool, VkQueue queue); Result CreateVkDescriptorRelatedObjects(); @@ -56,6 +61,13 @@ class Pipeline { void BindVkPipeline(); void BindVkDescriptorSets(); + const std::vector<VkPipelineShaderStageCreateInfo>& GetShaderStageInfo() + const { + return shader_stage_info_; + } + + uint32_t GetFenceTimeout() const { return fence_timeout_ms_; } + VkPipelineCache pipeline_cache_ = VK_NULL_HANDLE; VkPipeline pipeline_ = VK_NULL_HANDLE; VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE; @@ -80,6 +92,8 @@ class Pipeline { PipelineType pipeline_type_; std::vector<std::unique_ptr<Descriptor>> descriptors_; + std::vector<VkPipelineShaderStageCreateInfo> shader_stage_info_; + uint32_t fence_timeout_ms_ = 100; }; } // namespace vulkan diff --git a/tests/cases/compute_nothing.amber b/tests/cases/compute_nothing.amber new file mode 100644 index 0000000..e296ef8 --- /dev/null +++ b/tests/cases/compute_nothing.amber @@ -0,0 +1,22 @@ +# Copyright 2018 The Amber Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[compute shader] +#version 430 + +void main() { +} + +[test] +compute 4 1 1 |