• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/vulkan/device.h"
18 #include "src/vulkan/resource.h"
19 
20 namespace amber {
21 namespace vulkan {
22 
ImageDescriptor(Buffer * buffer,DescriptorType type,Device * device,uint32_t base_mip_level,uint32_t desc_set,uint32_t binding)23 ImageDescriptor::ImageDescriptor(Buffer* buffer,
24                                  DescriptorType type,
25                                  Device* device,
26                                  uint32_t base_mip_level,
27                                  uint32_t desc_set,
28                                  uint32_t binding)
29     : BufferBackedDescriptor(buffer, type, device, desc_set, binding),
30       base_mip_level_(base_mip_level),
31       vulkan_sampler_(device) {}
32 
33 ImageDescriptor::~ImageDescriptor() = default;
34 
RecordCopyDataToResourceIfNeeded(CommandBuffer * command)35 Result ImageDescriptor::RecordCopyDataToResourceIfNeeded(
36     CommandBuffer* command) {
37   for (auto& image : transfer_images_) {
38     image->ImageBarrier(command, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
39                         VK_PIPELINE_STAGE_TRANSFER_BIT);
40   }
41 
42   Result r = BufferBackedDescriptor::RecordCopyDataToResourceIfNeeded(command);
43   if (!r.IsSuccess())
44     return r;
45 
46   // Just do this as early as possible.
47   for (auto& image : transfer_images_) {
48     image->ImageBarrier(command, VK_IMAGE_LAYOUT_GENERAL,
49                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
50   }
51 
52   return {};
53 }
54 
CreateResourceIfNeeded()55 Result ImageDescriptor::CreateResourceIfNeeded() {
56   if (!transfer_images_.empty()) {
57     return Result(
58         "Vulkan: ImageDescriptor::CreateResourceIfNeeded() must be called "
59         "only when |transfer_images| is empty");
60   }
61 
62   transfer_images_.reserve(GetAmberBuffers().size());
63 
64   for (const auto& amber_buffer : GetAmberBuffers()) {
65     if (amber_buffer->ValuePtr()->empty())
66       continue;
67 
68     // Default to 2D image.
69     VkImageType image_type = VK_IMAGE_TYPE_2D;
70     switch (amber_buffer->GetImageDimension()) {
71       case ImageDimension::k1D:
72         image_type = VK_IMAGE_TYPE_1D;
73         break;
74       case ImageDimension::k2D:
75         image_type = VK_IMAGE_TYPE_2D;
76         break;
77       case ImageDimension::k3D:
78         image_type = VK_IMAGE_TYPE_3D;
79         break;
80       default:
81         break;
82     }
83 
84     Format* fmt = amber_buffer->GetFormat();
85     VkImageAspectFlags aspect = 0;
86     if (fmt->HasDepthComponent() && fmt->HasStencilComponent()) {
87       aspect = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
88     } else if (fmt->HasDepthComponent()) {
89       aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
90     } else if (fmt->HasStencilComponent()) {
91       aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
92     } else {
93       aspect = VK_IMAGE_ASPECT_COLOR_BIT;
94     }
95 
96     transfer_images_.emplace_back(MakeUnique<TransferImage>(
97         device_, *fmt, aspect, image_type, amber_buffer->GetWidth(),
98         amber_buffer->GetHeight(), amber_buffer->GetDepth(),
99         amber_buffer->GetMipLevels(), base_mip_level_, VK_REMAINING_MIP_LEVELS,
100         amber_buffer->GetSamples()));
101     VkImageUsageFlags usage =
102         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
103 
104     if (type_ == DescriptorType::kStorageImage) {
105       usage |= VK_IMAGE_USAGE_STORAGE_BIT;
106     } else {
107       assert(type_ == DescriptorType::kSampledImage ||
108              type_ == DescriptorType::kCombinedImageSampler);
109       usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
110     }
111 
112     Result r = transfer_images_.back()->Initialize(usage);
113 
114     if (!r.IsSuccess())
115       return r;
116   }
117 
118   if (amber_sampler_) {
119     Result r = vulkan_sampler_.CreateSampler(amber_sampler_);
120     if (!r.IsSuccess())
121       return r;
122   }
123 
124   is_descriptor_set_update_needed_ = true;
125   return {};
126 }
127 
RecordCopyDataToHost(CommandBuffer * command)128 Result ImageDescriptor::RecordCopyDataToHost(CommandBuffer* command) {
129   if (!IsReadOnly()) {
130     for (auto& image : transfer_images_) {
131       image->ImageBarrier(command, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
132                           VK_PIPELINE_STAGE_TRANSFER_BIT);
133     }
134 
135     BufferBackedDescriptor::RecordCopyDataToHost(command);
136   }
137 
138   return {};
139 }
140 
MoveResourceToBufferOutput()141 Result ImageDescriptor::MoveResourceToBufferOutput() {
142   Result r = BufferBackedDescriptor::MoveResourceToBufferOutput();
143 
144   transfer_images_.clear();
145 
146   return r;
147 }
148 
UpdateDescriptorSetIfNeeded(VkDescriptorSet descriptor_set)149 void ImageDescriptor::UpdateDescriptorSetIfNeeded(
150     VkDescriptorSet descriptor_set) {
151   if (!is_descriptor_set_update_needed_)
152     return;
153 
154   // Always use general layout.
155   VkImageLayout layout = VK_IMAGE_LAYOUT_GENERAL;
156 
157   std::vector<VkDescriptorImageInfo> image_infos;
158 
159   for (const auto& image : transfer_images_) {
160     VkDescriptorImageInfo image_info = {vulkan_sampler_.GetVkSampler(),
161                                         image->GetVkImageView(), layout};
162     image_infos.push_back(image_info);
163   }
164 
165   VkWriteDescriptorSet write = VkWriteDescriptorSet();
166   write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
167   write.dstSet = descriptor_set;
168   write.dstBinding = binding_;
169   write.dstArrayElement = 0;
170   write.descriptorCount = static_cast<uint32_t>(image_infos.size());
171   write.descriptorType = GetVkDescriptorType();
172   write.pImageInfo = image_infos.data();
173 
174   device_->GetPtrs()->vkUpdateDescriptorSets(device_->GetVkDevice(), 1, &write,
175                                              0, nullptr);
176 
177   is_descriptor_set_update_needed_ = false;
178 }
179 
GetResources()180 std::vector<Resource*> ImageDescriptor::GetResources() {
181   std::vector<Resource*> ret;
182   for (auto& i : transfer_images_) {
183     ret.push_back(i.get());
184   }
185   return ret;
186 }
187 
188 }  // namespace vulkan
189 }  // namespace amber
190