1 // Copyright 2019 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/image_descriptor.h"
16
17 #include <algorithm>
18 #include <unordered_map>
19 #include <utility>
20
21 #include "src/vulkan/device.h"
22 #include "src/vulkan/resource.h"
23
24 namespace amber {
25 namespace vulkan {
26
ImageDescriptor(Buffer * buffer,DescriptorType type,Device * device,uint32_t base_mip_level,uint32_t desc_set,uint32_t binding,Pipeline * pipeline)27 ImageDescriptor::ImageDescriptor(Buffer* buffer,
28 DescriptorType type,
29 Device* device,
30 uint32_t base_mip_level,
31 uint32_t desc_set,
32 uint32_t binding,
33 Pipeline* pipeline)
34 : BufferBackedDescriptor(buffer, type, device, desc_set, binding, pipeline),
35 base_mip_level_(base_mip_level),
36 vulkan_sampler_(device) {}
37
38 ImageDescriptor::~ImageDescriptor() = default;
39
CreateResourceIfNeeded()40 Result ImageDescriptor::CreateResourceIfNeeded() {
41 auto& transfer_resources = pipeline_->GetDescriptorTransferResources();
42
43 for (const auto& amber_buffer : GetAmberBuffers()) {
44 if (amber_buffer->ValuePtr()->empty())
45 continue;
46
47 // Check if the transfer image is already created.
48 if (transfer_resources.count(amber_buffer) > 0) {
49 continue;
50 }
51
52 // Default to 2D image.
53 VkImageType image_type = VK_IMAGE_TYPE_2D;
54 switch (amber_buffer->GetImageDimension()) {
55 case ImageDimension::k1D:
56 image_type = VK_IMAGE_TYPE_1D;
57 break;
58 case ImageDimension::k2D:
59 image_type = VK_IMAGE_TYPE_2D;
60 break;
61 case ImageDimension::k3D:
62 image_type = VK_IMAGE_TYPE_3D;
63 break;
64 default:
65 break;
66 }
67
68 Format* fmt = amber_buffer->GetFormat();
69 VkImageAspectFlags aspect = 0;
70 if (fmt->HasDepthComponent() && fmt->HasStencilComponent()) {
71 aspect = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
72 } else if (fmt->HasDepthComponent()) {
73 aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
74 } else if (fmt->HasStencilComponent()) {
75 aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
76 } else {
77 aspect = VK_IMAGE_ASPECT_COLOR_BIT;
78 }
79
80 VkImageUsageFlags usage =
81 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
82 if (type_ == DescriptorType::kStorageImage) {
83 usage |= VK_IMAGE_USAGE_STORAGE_BIT;
84 } else {
85 assert(type_ == DescriptorType::kSampledImage ||
86 type_ == DescriptorType::kCombinedImageSampler);
87 usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
88 }
89
90 auto transfer_image = MakeUnique<TransferImage>(
91 device_, *fmt, aspect, image_type, usage, amber_buffer->GetWidth(),
92 amber_buffer->GetHeight(), amber_buffer->GetDepth(),
93 amber_buffer->GetMipLevels(), base_mip_level_, VK_REMAINING_MIP_LEVELS,
94 amber_buffer->GetSamples());
95
96 // Store the transfer image to the pipeline's map of transfer images.
97 transfer_resources[amber_buffer] = std::move(transfer_image);
98 }
99
100 if (amber_sampler_) {
101 Result r = vulkan_sampler_.CreateSampler(amber_sampler_);
102 if (!r.IsSuccess())
103 return r;
104 }
105
106 is_descriptor_set_update_needed_ = true;
107 return {};
108 }
109
UpdateDescriptorSetIfNeeded(VkDescriptorSet descriptor_set)110 void ImageDescriptor::UpdateDescriptorSetIfNeeded(
111 VkDescriptorSet descriptor_set) {
112 if (!is_descriptor_set_update_needed_)
113 return;
114
115 // Always use general layout.
116 VkImageLayout layout = VK_IMAGE_LAYOUT_GENERAL;
117
118 std::vector<VkDescriptorImageInfo> image_infos;
119
120 // Create VkDescriptorImageInfo for every descriptor image.
121 for (const auto& amber_buffer : GetAmberBuffers()) {
122 const auto& image =
123 pipeline_->GetDescriptorTransferResources()[amber_buffer]
124 ->AsTransferImage();
125 VkDescriptorImageInfo image_info = {vulkan_sampler_.GetVkSampler(),
126 image->GetVkImageView(), layout};
127 image_infos.push_back(image_info);
128 }
129
130 VkWriteDescriptorSet write = VkWriteDescriptorSet();
131 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
132 write.dstSet = descriptor_set;
133 write.dstBinding = binding_;
134 write.dstArrayElement = 0;
135 write.descriptorCount = static_cast<uint32_t>(image_infos.size());
136 write.descriptorType = GetVkDescriptorType();
137 write.pImageInfo = image_infos.data();
138
139 device_->GetPtrs()->vkUpdateDescriptorSets(device_->GetVkDevice(), 1, &write,
140 0, nullptr);
141
142 is_descriptor_set_update_needed_ = false;
143 }
144
145 } // namespace vulkan
146 } // namespace amber
147