diff options
-rw-r--r-- | src/vulkan/pipeline.cc | 221 | ||||
-rw-r--r-- | src/vulkan/pipeline.h | 18 | ||||
-rw-r--r-- | tests/cases/compute_nothing_with_ssbo.amber | 37 | ||||
-rw-r--r-- | tests/cases/multiple_ssbo_with_sparse_descriptor_set_in_compute_pipeline.amber | 116 |
4 files changed, 282 insertions, 110 deletions
diff --git a/src/vulkan/pipeline.cc b/src/vulkan/pipeline.cc index 2acda73..252f4ea 100644 --- a/src/vulkan/pipeline.cc +++ b/src/vulkan/pipeline.cc @@ -65,75 +65,57 @@ void Pipeline::Shutdown() { if (r.IsSuccess()) command_->SubmitAndReset(fence_timeout_ms_); - DestoryDescriptorPools(); - DestoryDescriptorSetLayouts(); + for (auto& info : descriptor_set_info_) { + vkDestroyDescriptorSetLayout(device_, info.layout, nullptr); + if (info.empty) + continue; + + vkDestroyDescriptorPool(device_, info.pool, nullptr); + + for (auto& desc : info.descriptors_) + desc->Shutdown(); + } + command_->Shutdown(); vkDestroyPipelineLayout(device_, pipeline_layout_, nullptr); - for (size_t i = 0; i < descriptors_.size(); ++i) - descriptors_[i]->Shutdown(); vkDestroyPipeline(device_, pipeline_, nullptr); } -void Pipeline::DestoryDescriptorSetLayouts() { - for (size_t i = 0; i < descriptor_set_layouts_.size(); ++i) { - vkDestroyDescriptorSetLayout(device_, descriptor_set_layouts_[i], nullptr); - } - descriptor_set_layouts_.clear(); -} - Result Pipeline::CreateDescriptorSetLayouts() { - std::sort(descriptors_.begin(), descriptors_.end()); + for (auto& info : descriptor_set_info_) { + VkDescriptorSetLayoutCreateInfo desc_info = {}; + desc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - size_t i = 0; - while (i < descriptors_.size()) { + // If there are no descriptors for this descriptor set we only + // need to create its layout and there will be no bindings. std::vector<VkDescriptorSetLayoutBinding> bindings; - for (const uint32_t current_desc = descriptors_[i]->GetDescriptorSet(); - i < descriptors_.size() && - current_desc == descriptors_[i]->GetDescriptorSet(); - ++i) { + for (auto& desc : info.descriptors_) { bindings.emplace_back(); - bindings.back().binding = descriptors_[i]->GetBinding(); - bindings.back().descriptorType = - ToVkDescriptorType(descriptors_[i]->GetType()); + bindings.back().binding = desc->GetBinding(); + bindings.back().descriptorType = ToVkDescriptorType(desc->GetType()); bindings.back().descriptorCount = 1; - // TODO(jaebaek): Amber script must contain which stages use each - // descriptor. Set .stageFlags attribute based on it. bindings.back().stageFlags = VK_SHADER_STAGE_ALL; - // TODO(jaebaek): Properly set .pImmutableSamplers attribute. } - - VkDescriptorSetLayoutCreateInfo desc_info = {}; - desc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - desc_info.bindingCount = static_cast<uint32_t>(bindings.size()); + desc_info.bindingCount = bindings.size(); desc_info.pBindings = bindings.data(); - VkDescriptorSetLayout desc_layout = VK_NULL_HANDLE; if (vkCreateDescriptorSetLayout(device_, &desc_info, nullptr, - &desc_layout) != VK_SUCCESS) { + &info.layout) != VK_SUCCESS) { return Result("Vulkan::Calling vkCreateDescriptorSetLayout Fail"); } - descriptor_set_layouts_.push_back(desc_layout); } return {}; } -void Pipeline::DestoryDescriptorPools() { - for (size_t i = 0; i < descriptor_pools_.size(); ++i) { - vkDestroyDescriptorPool(device_, descriptor_pools_[i], nullptr); - } - descriptor_pools_.clear(); -} - Result Pipeline::CreateDescriptorPools() { - size_t i = 0; - while (i < descriptors_.size()) { + for (auto& info : descriptor_set_info_) { + if (info.empty) + continue; + std::vector<VkDescriptorPoolSize> pool_sizes; - for (const uint32_t current_desc = descriptors_[i]->GetDescriptorSet(); - i < descriptors_.size() && - current_desc == descriptors_[i]->GetDescriptorSet(); - ++i) { - auto type = ToVkDescriptorType(descriptors_[i]->GetType()); + for (auto& desc : info.descriptors_) { + auto type = ToVkDescriptorType(desc->GetType()); auto it = find_if(pool_sizes.begin(), pool_sizes.end(), [&type](const VkDescriptorPoolSize& size) { return size.type == type; @@ -154,42 +136,47 @@ Result Pipeline::CreateDescriptorPools() { pool_info.poolSizeCount = static_cast<uint32_t>(pool_sizes.size()); pool_info.pPoolSizes = pool_sizes.data(); - VkDescriptorPool desc_pool = VK_NULL_HANDLE; - if (vkCreateDescriptorPool(device_, &pool_info, nullptr, &desc_pool) != + if (vkCreateDescriptorPool(device_, &pool_info, nullptr, &info.pool) != VK_SUCCESS) { return Result("Vulkan::Calling vkCreateDescriptorPool Fail"); } - descriptor_pools_.push_back(desc_pool); } return {}; } Result Pipeline::CreateDescriptorSets() { - for (size_t i = 0; i < descriptor_set_layouts_.size(); ++i) { + for (size_t i = 0; i < descriptor_set_info_.size(); ++i) { + if (descriptor_set_info_[i].empty) + continue; + VkDescriptorSetAllocateInfo desc_set_info = {}; desc_set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - desc_set_info.descriptorPool = descriptor_pools_[i]; + desc_set_info.descriptorPool = descriptor_set_info_[i].pool; desc_set_info.descriptorSetCount = 1; - desc_set_info.pSetLayouts = &descriptor_set_layouts_[i]; + desc_set_info.pSetLayouts = &descriptor_set_info_[i].layout; VkDescriptorSet desc_set = VK_NULL_HANDLE; if (vkAllocateDescriptorSets(device_, &desc_set_info, &desc_set) != VK_SUCCESS) { return Result("Vulkan::Calling vkAllocateDescriptorSets Fail"); } - descriptor_sets_.push_back(desc_set); + descriptor_set_info_[i].vk_desc_set = desc_set; } return {}; } Result Pipeline::CreatePipelineLayout() { + std::vector<VkDescriptorSetLayout> descriptor_set_layouts; + for (const auto& desc_set : descriptor_set_info_) + descriptor_set_layouts.push_back(desc_set.layout); + VkPipelineLayoutCreateInfo pipeline_layout_info = {}; pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipeline_layout_info.setLayoutCount = - static_cast<uint32_t>(descriptor_set_layouts_.size()); - pipeline_layout_info.pSetLayouts = descriptor_set_layouts_.data(); + static_cast<uint32_t>(descriptor_set_layouts.size()); + pipeline_layout_info.pSetLayouts = descriptor_set_layouts.data(); // TODO(jaebaek): Push constant for pipeline_layout_info. if (vkCreatePipelineLayout(device_, &pipeline_layout_info, nullptr, @@ -204,7 +191,6 @@ Result Pipeline::CreateVkDescriptorRelatedObjectsIfNeeded() { if (descriptor_related_objects_already_created_) return {}; - // TODO(jaebaek): Update SSBO dynamically. Result r = CreateDescriptorSetLayouts(); if (!r.IsSuccess()) return r; @@ -217,49 +203,59 @@ Result Pipeline::CreateVkDescriptorRelatedObjectsIfNeeded() { if (!r.IsSuccess()) return r; - return CreatePipelineLayout(); + r = CreatePipelineLayout(); + if (!r.IsSuccess()) + return r; + + descriptor_related_objects_already_created_ = true; + return {}; } Result Pipeline::UpdateDescriptorSetsIfNeeded() { - for (size_t i = 0, j = 0; - i < descriptors_.size() && j < descriptor_sets_.size(); ++j) { - for (const uint32_t current_desc = descriptors_[i]->GetDescriptorSet(); - i < descriptors_.size() && - current_desc == descriptors_[i]->GetDescriptorSet(); - ++i) { - Result r = - descriptors_[i]->UpdateDescriptorSetIfNeeded(descriptor_sets_[j]); + for (auto& info : descriptor_set_info_) { + for (auto& desc : info.descriptors_) { + Result r = desc->UpdateDescriptorSetIfNeeded(info.vk_desc_set); if (!r.IsSuccess()) return r; } } - descriptor_related_objects_already_created_ = true; return {}; } Result Pipeline::AddDescriptor(const BufferCommand* buffer_command) { + if (buffer_command == nullptr) + return Result("Pipeline::AddDescriptor BufferCommand is nullptr"); + if (!buffer_command->IsSSBO() && !buffer_command->IsUniform()) return Result("Pipeline::AddDescriptor not supported buffer type"); - Descriptor* desc = nullptr; - for (size_t i = 0; i < descriptors_.size(); ++i) { - if (descriptors_[i]->GetDescriptorSet() == - buffer_command->GetDescriptorSet() && - descriptors_[i]->GetBinding() == buffer_command->GetBinding()) { - desc = descriptors_[i].get(); + const uint32_t desc_set = buffer_command->GetDescriptorSet(); + if (desc_set >= descriptor_set_info_.size()) { + for (size_t i = descriptor_set_info_.size(); + i <= static_cast<size_t>(desc_set); ++i) { + descriptor_set_info_.emplace_back(); } } + descriptor_set_info_[desc_set].empty = false; + + auto& descriptors = descriptor_set_info_[desc_set].descriptors_; + Descriptor* desc = nullptr; + for (auto& descriptor : descriptors) { + if (descriptor->GetBinding() == buffer_command->GetBinding()) + desc = descriptor.get(); + } + if (desc == nullptr) { auto desc_type = buffer_command->IsSSBO() ? DescriptorType::kStorageBuffer : DescriptorType::kUniformBuffer; auto buffer_desc = MakeUnique<BufferDescriptor>( desc_type, device_, buffer_command->GetDescriptorSet(), buffer_command->GetBinding()); - descriptors_.push_back(std::move(buffer_desc)); + descriptors.push_back(std::move(buffer_desc)); - desc = descriptors_.back().get(); + desc = descriptors.back().get(); } if (buffer_command->IsSSBO() && !desc->IsStorageBuffer()) { @@ -282,15 +278,17 @@ Result Pipeline::AddDescriptor(const BufferCommand* buffer_command) { } Result Pipeline::SendDescriptorDataToDeviceIfNeeded() { - if (descriptors_.size() == 0) - return {}; - bool data_send_needed = false; - for (const auto& desc : descriptors_) { - if (desc->HasDataNotSent()) { - data_send_needed = true; - break; + for (auto& info : descriptor_set_info_) { + for (auto& desc : info.descriptors_) { + if (desc->HasDataNotSent()) { + data_send_needed = true; + break; + } } + + if (data_send_needed) + break; } if (!data_send_needed) @@ -300,11 +298,13 @@ Result Pipeline::SendDescriptorDataToDeviceIfNeeded() { if (!r.IsSuccess()) return r; - for (const auto& desc : descriptors_) { - r = desc->CreateOrResizeIfNeeded(command_->GetCommandBuffer(), - memory_properties_); - if (!r.IsSuccess()) - return r; + for (auto& info : descriptor_set_info_) { + for (auto& desc : info.descriptors_) { + r = desc->CreateOrResizeIfNeeded(command_->GetCommandBuffer(), + memory_properties_); + if (!r.IsSuccess()) + return r; + } } r = command_->End(); @@ -325,20 +325,25 @@ Result Pipeline::SendDescriptorDataToDeviceIfNeeded() { if (!r.IsSuccess()) return r; - for (const auto& desc : descriptors_) { - desc->UpdateResourceIfNeeded(command_->GetCommandBuffer()); + for (auto& info : descriptor_set_info_) { + for (auto& desc : info.descriptors_) + desc->UpdateResourceIfNeeded(command_->GetCommandBuffer()); } return {}; } void Pipeline::BindVkDescriptorSets() { - vkCmdBindDescriptorSets(command_->GetCommandBuffer(), - IsGraphics() ? VK_PIPELINE_BIND_POINT_GRAPHICS - : VK_PIPELINE_BIND_POINT_COMPUTE, - pipeline_layout_, 0, - static_cast<uint32_t>(descriptor_sets_.size()), - descriptor_sets_.data(), 0, nullptr); + for (size_t i = 0; i < descriptor_set_info_.size(); ++i) { + if (descriptor_set_info_[i].empty) + continue; + + vkCmdBindDescriptorSets(command_->GetCommandBuffer(), + IsGraphics() ? VK_PIPELINE_BIND_POINT_GRAPHICS + : VK_PIPELINE_BIND_POINT_COMPUTE, + pipeline_layout_, i, 1, + &descriptor_set_info_[i].vk_desc_set, 0, nullptr); + } } void Pipeline::BindVkPipeline() { @@ -350,15 +355,20 @@ void Pipeline::BindVkPipeline() { Result Pipeline::CopyDescriptorToHost(const uint32_t descriptor_set, const uint32_t binding) { + if (descriptor_set_info_.size() <= descriptor_set) { + return Result( + "Pipeline::CopyDescriptorToHost no Descriptor class has given " + "descriptor set: " + + std::to_string(descriptor_set)); + } + Result r = command_->BeginIfNotInRecording(); if (!r.IsSuccess()) return r; - for (size_t i = 0; i < descriptors_.size(); ++i) { - if (descriptors_[i]->GetDescriptorSet() == descriptor_set && - descriptors_[i]->GetBinding() == binding) { - return descriptors_[i]->SendDataToHostIfNeeded( - command_->GetCommandBuffer()); + for (auto& desc : descriptor_set_info_[descriptor_set].descriptors_) { + if (desc->GetBinding() == binding) { + return desc->SendDataToHostIfNeeded(command_->GetCommandBuffer()); } } @@ -371,10 +381,17 @@ Result Pipeline::GetDescriptorInfo(const uint32_t descriptor_set, const uint32_t binding, ResourceInfo* info) { assert(info); - for (size_t i = 0; i < descriptors_.size(); ++i) { - if (descriptors_[i]->GetDescriptorSet() == descriptor_set && - descriptors_[i]->GetBinding() == binding) { - *info = descriptors_[i]->GetResourceInfo(); + + if (descriptor_set_info_.size() <= descriptor_set) { + return Result( + "Pipeline::CopyDescriptorToHost no Descriptor class has given " + "descriptor set: " + + std::to_string(descriptor_set)); + } + + for (auto& desc : descriptor_set_info_[descriptor_set].descriptors_) { + if (desc->GetBinding() == binding) { + *info = desc->GetResourceInfo(); return {}; } } diff --git a/src/vulkan/pipeline.h b/src/vulkan/pipeline.h index a9f65ed..3b9b3a1 100644 --- a/src/vulkan/pipeline.h +++ b/src/vulkan/pipeline.h @@ -83,29 +83,31 @@ class Pipeline { VkPipeline pipeline_ = VK_NULL_HANDLE; VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE; - std::vector<VkDescriptorSetLayout> descriptor_set_layouts_; - std::vector<VkDescriptorPool> descriptor_pools_; - std::vector<VkDescriptorSet> descriptor_sets_; - VkDevice device_ = VK_NULL_HANDLE; VkPhysicalDeviceMemoryProperties memory_properties_; std::unique_ptr<CommandBuffer> command_; private: + struct DescriptorSetInfo { + bool empty = true; + VkDescriptorSetLayout layout = VK_NULL_HANDLE; + VkDescriptorPool pool = VK_NULL_HANDLE; + VkDescriptorSet vk_desc_set = VK_NULL_HANDLE; + std::vector<std::unique_ptr<Descriptor>> descriptors_; + }; + Result CreatePipelineLayout(); Result CreateDescriptorSetLayouts(); Result CreateDescriptorPools(); Result CreateDescriptorSets(); - void DestoryDescriptorSetLayouts(); - void DestoryDescriptorPools(); - PipelineType pipeline_type_; - std::vector<std::unique_ptr<Descriptor>> descriptors_; + std::vector<DescriptorSetInfo> descriptor_set_info_; std::vector<VkPipelineShaderStageCreateInfo> shader_stage_info_; uint32_t fence_timeout_ms_ = 100; bool descriptor_related_objects_already_created_ = false; + bool need_sort_descriptors_ = true; }; } // namespace vulkan diff --git a/tests/cases/compute_nothing_with_ssbo.amber b/tests/cases/compute_nothing_with_ssbo.amber new file mode 100644 index 0000000..050cc00 --- /dev/null +++ b/tests/cases/compute_nothing_with_ssbo.amber @@ -0,0 +1,37 @@ +# 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 + +layout(set = 1, binding = 2) buffer block1 { + float data_set1_binding2[11]; +}; + +void main() { +} + +[test] +ssbo 1:2 subdata vec4 0 0.1 0.2 0.3 0.4 +compute 4 1 1 +probe ssbo float 1:2 0 ~= 0.1 0.2 0.3 0.4 + + +ssbo 1:2 subdata float 0 0.57 0.56 0.55 0.54 \ + 0.53 0.52 0.51 0.50 \ + 0.49 0.48 0.47 +compute 4 1 1 +probe ssbo float 1:2 0 ~= 0.57 0.56 0.55 0.54 \ + 0.53 0.52 0.51 0.50 \ + 0.49 0.48 0.47 diff --git a/tests/cases/multiple_ssbo_with_sparse_descriptor_set_in_compute_pipeline.amber b/tests/cases/multiple_ssbo_with_sparse_descriptor_set_in_compute_pipeline.amber new file mode 100644 index 0000000..d5f15cf --- /dev/null +++ b/tests/cases/multiple_ssbo_with_sparse_descriptor_set_in_compute_pipeline.amber @@ -0,0 +1,116 @@ +# 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 + +layout(set = 1, binding = 0) buffer block1 { + float data_set1_binding0[11]; + float data_set1_binding0_result[11]; +}; + +layout(set = 1, binding = 2) buffer block2 { + float data_set1_binding2[11]; + float data_set1_binding2_result[11]; +}; + +layout(set = 3, binding = 1) buffer block3 { + float data_set3_binding1[11]; + float data_set3_binding1_result[11]; +}; + +layout(set = 5, binding = 3) buffer block4 { + float data_set5_binding3[11]; + float data_set5_binding3_result[11]; +}; + +void main() { + for (int i = 0; i < 11; ++i) { + data_set1_binding0_result[i] = data_set1_binding2[i]; + data_set1_binding2_result[i] = data_set3_binding1[i]; + data_set3_binding1_result[i] = data_set5_binding3[i]; + data_set5_binding3_result[i] = data_set1_binding0[i]; + } +} + +[test] +ssbo 1:0 subdata vec4 0 0.1 0.2 0.3 0.4 +ssbo 1:2 subdata vec4 0 0.1 0.2 0.3 0.4 +ssbo 3:1 subdata vec4 0 0.1 0.2 0.3 0.4 +ssbo 5:3 subdata vec4 0 0.1 0.2 0.3 0.4 + +compute 4 1 1 + +probe ssbo float 1:0 0 ~= 0.1 0.2 0.3 0.4 +probe ssbo float 1:2 0 ~= 0.1 0.2 0.3 0.4 +probe ssbo float 3:1 0 ~= 0.1 0.2 0.3 0.4 +probe ssbo float 5:3 0 ~= 0.1 0.2 0.3 0.4 + +ssbo 1:0 subdata float 0 0.1 0.2 0.3 0.4 \ + 0.5 0.6 0.7 0.8 \ + 0.9 0.10 0.11 \ + 0.1 0.2 0.3 0.4 \ + 0.5 0.6 0.7 0.8 \ + 0.9 0.10 0.11 + +ssbo 1:2 subdata float 0 0.57 0.56 0.55 0.54 \ + 0.53 0.52 0.51 0.50 \ + 0.49 0.48 0.47 \ + 0.57 0.56 0.55 0.54 \ + 0.53 0.52 0.51 0.50 \ + 0.49 0.48 0.47 + +ssbo 3:1 subdata float 0 0.21 0.22 0.23 0.24 \ + 0.25 0.26 0.27 0.28 \ + 0.29 0.30 0.31 \ + 0.21 0.22 0.23 0.24 \ + 0.25 0.26 0.27 0.28 \ + 0.29 0.30 0.31 + +ssbo 5:3 subdata float 0 0.23 0.229 0.228 0.227 \ + 0.226 0.225 0.224 0.223 \ + 0.222 0.221 0.22 \ + 0.23 0.229 0.228 0.227 \ + 0.226 0.225 0.224 0.223 \ + 0.222 0.221 0.22 + +compute 4 1 1 + +probe ssbo float 1:0 0 ~= 0.1 0.2 0.3 0.4 \ + 0.5 0.6 0.7 0.8 \ + 0.9 0.10 0.11 +probe ssbo float 1:0 44 ~= 0.57 0.56 0.55 0.54 \ + 0.53 0.52 0.51 0.50 \ + 0.49 0.48 0.47 + +probe ssbo float 1:2 0 ~= 0.57 0.56 0.55 0.54 \ + 0.53 0.52 0.51 0.50 \ + 0.49 0.48 0.47 +probe ssbo float 1:2 44 ~= 0.21 0.22 0.23 0.24 \ + 0.25 0.26 0.27 0.28 \ + 0.29 0.30 0.31 + +probe ssbo float 3:1 0 ~= 0.21 0.22 0.23 0.24 \ + 0.25 0.26 0.27 0.28 \ + 0.29 0.30 0.31 +probe ssbo float 3:1 44 ~= 0.23 0.229 0.228 0.227 \ + 0.226 0.225 0.224 0.223 \ + 0.222 0.221 0.22 + +probe ssbo float 5:3 0 ~= 0.23 0.229 0.228 0.227 \ + 0.226 0.225 0.224 0.223 \ + 0.222 0.221 0.22 +probe ssbo float 5:3 44 ~= 0.1 0.2 0.3 0.4 \ + 0.5 0.6 0.7 0.8 \ + 0.9 0.10 0.11 |