1 /* Copyright (c) 2017-2018 Hans-Kristian Arntzen
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be
12 * included in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #include "image.hpp"
24 #include "device.hpp"
25 #include "buffer.hpp"
26
27 using namespace std;
28
29 namespace Vulkan
30 {
31
ImageView(Device * device,VkImageView view,const ImageViewCreateInfo & info)32 ImageView::ImageView(Device *device, VkImageView view, const ImageViewCreateInfo &info)
33 : Cookie(device)
34 , device(device)
35 , view(view)
36 , info(info)
37 {
38 }
39
get_render_target_view(unsigned layer) const40 VkImageView ImageView::get_render_target_view(unsigned layer) const
41 {
42 // Transient images just have one layer.
43 if (info.image->get_create_info().domain == ImageDomain::Transient)
44 return view;
45
46 VK_ASSERT(layer < get_create_info().layers);
47
48 if (render_target_views.empty())
49 return view;
50 else
51 {
52 VK_ASSERT(layer < render_target_views.size());
53 return render_target_views[layer];
54 }
55 }
56
~ImageView()57 ImageView::~ImageView()
58 {
59 if (internal_sync)
60 {
61 device->destroy_image_view_nolock(view);
62 if (depth_view != VK_NULL_HANDLE)
63 device->destroy_image_view_nolock(depth_view);
64 if (stencil_view != VK_NULL_HANDLE)
65 device->destroy_image_view_nolock(stencil_view);
66 if (unorm_view != VK_NULL_HANDLE)
67 device->destroy_image_view_nolock(unorm_view);
68 if (srgb_view != VK_NULL_HANDLE)
69 device->destroy_image_view_nolock(srgb_view);
70
71 for (auto &view : render_target_views)
72 device->destroy_image_view_nolock(view);
73 }
74 else
75 {
76 device->destroy_image_view(view);
77 if (depth_view != VK_NULL_HANDLE)
78 device->destroy_image_view(depth_view);
79 if (stencil_view != VK_NULL_HANDLE)
80 device->destroy_image_view(stencil_view);
81 if (unorm_view != VK_NULL_HANDLE)
82 device->destroy_image_view(unorm_view);
83 if (srgb_view != VK_NULL_HANDLE)
84 device->destroy_image_view(srgb_view);
85
86 for (auto &view : render_target_views)
87 device->destroy_image_view(view);
88 }
89 }
90
Image(Device * device,VkImage image,VkImageView default_view,const DeviceAllocation & alloc,const ImageCreateInfo & create_info)91 Image::Image(Device *device, VkImage image, VkImageView default_view, const DeviceAllocation &alloc,
92 const ImageCreateInfo &create_info)
93 : Cookie(device)
94 , device(device)
95 , image(image)
96 , alloc(alloc)
97 , create_info(create_info)
98 {
99 if (default_view != VK_NULL_HANDLE)
100 {
101 ImageViewCreateInfo info;
102 info.image = this;
103 info.format = create_info.format;
104 info.base_level = 0;
105 info.levels = create_info.levels;
106 info.base_layer = 0;
107 info.layers = create_info.layers;
108 view = ImageViewHandle(device->handle_pool.image_views.allocate(device, default_view, info));
109 }
110 }
111
~Image()112 Image::~Image()
113 {
114 if (alloc.get_memory())
115 {
116 if (internal_sync)
117 {
118 device->destroy_image_nolock(image);
119 device->free_memory_nolock(alloc);
120 }
121 else
122 {
123 device->destroy_image(image);
124 device->free_memory(alloc);
125 }
126 }
127 }
128
get_host_visible_buffer() const129 const Buffer &LinearHostImage::get_host_visible_buffer() const
130 {
131 return *cpu_image;
132 }
133
need_staging_copy() const134 bool LinearHostImage::need_staging_copy() const
135 {
136 return gpu_image->get_create_info().domain != ImageDomain::LinearHostCached &&
137 gpu_image->get_create_info().domain != ImageDomain::LinearHost;
138 }
139
get_host_visible_allocation() const140 const DeviceAllocation &LinearHostImage::get_host_visible_allocation() const
141 {
142 return need_staging_copy() ? cpu_image->get_allocation() : gpu_image->get_allocation();
143 }
144
get_view() const145 const ImageView &LinearHostImage::get_view() const
146 {
147 return gpu_image->get_view();
148 }
149
get_image() const150 const Image &LinearHostImage::get_image() const
151 {
152 return *gpu_image;
153 }
154
get_offset() const155 size_t LinearHostImage::get_offset() const
156 {
157 return row_offset;
158 }
159
get_row_pitch_bytes() const160 size_t LinearHostImage::get_row_pitch_bytes() const
161 {
162 return row_pitch;
163 }
164
get_used_pipeline_stages() const165 VkPipelineStageFlags LinearHostImage::get_used_pipeline_stages() const
166 {
167 return stages;
168 }
169
LinearHostImage(Device * device,ImageHandle gpu_image_,BufferHandle cpu_image_,VkPipelineStageFlags stages)170 LinearHostImage::LinearHostImage(Device *device, ImageHandle gpu_image_, BufferHandle cpu_image_, VkPipelineStageFlags stages)
171 : device(device), gpu_image(move(gpu_image_)), cpu_image(move(cpu_image_)), stages(stages)
172 {
173 if (gpu_image->get_create_info().domain == ImageDomain::LinearHostCached ||
174 gpu_image->get_create_info().domain == ImageDomain::LinearHost)
175 {
176 VkImageSubresource sub = {};
177 sub.aspectMask = format_to_aspect_mask(gpu_image->get_format());
178 VkSubresourceLayout layout;
179 vkGetImageSubresourceLayout(device->get_device(), gpu_image->get_image(), &sub, &layout);
180 row_pitch = layout.rowPitch;
181 row_offset = layout.offset;
182 }
183 else
184 {
185 row_pitch = gpu_image->get_width() * TextureFormatLayout::format_block_size(gpu_image->get_format());
186 row_offset = 0;
187 }
188 }
189
operator ()(ImageView * view)190 void ImageViewDeleter::operator()(ImageView *view)
191 {
192 view->device->handle_pool.image_views.free(view);
193 }
194
operator ()(Image * image)195 void ImageDeleter::operator()(Image *image)
196 {
197 image->device->handle_pool.images.free(image);
198 }
199
operator ()(LinearHostImage * image)200 void LinearHostImageDeleter::operator()(LinearHostImage *image)
201 {
202 image->device->handle_pool.linear_images.free(image);
203 }
204 }
205