aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaebaek Seo <duke.acacia@gmail.com>2018-11-26 22:39:31 -0500
committerGitHub <noreply@github.com>2018-11-26 22:39:31 -0500
commit3a6f620e15e9c14ab6fd71e974549e61c2ca9d6e (patch)
treecd6ea5142c725dde8c01da7431a976550f593761
parentda1d01dfca44f24ab1e344f7c531d57735a499ac (diff)
downloadamber-3a6f620e15e9c14ab6fd71e974549e61c2ca9d6e.tar.gz
Vulkan: add compute pipeline (#98)
Fixes #13
-rw-r--r--src/vulkan/CMakeLists.txt1
-rw-r--r--src/vulkan/compute_pipeline.cc85
-rw-r--r--src/vulkan/compute_pipeline.h47
-rw-r--r--src/vulkan/engine_vulkan.cc23
-rw-r--r--src/vulkan/graphics_pipeline.cc23
-rw-r--r--src/vulkan/graphics_pipeline.h10
-rw-r--r--src/vulkan/pipeline.cc25
-rw-r--r--src/vulkan/pipeline.h20
-rw-r--r--tests/cases/compute_nothing.amber22
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