211 lines
5.1 KiB
C++
211 lines
5.1 KiB
C++
/* Copyright (c) 2019-2025, Arm Limited and Contributors
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* 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 "image.h"
|
|
|
|
#include "device.h"
|
|
#include "image_view.h"
|
|
|
|
namespace vkb
|
|
{
|
|
namespace
|
|
{
|
|
inline VkImageType find_image_type(VkExtent3D extent)
|
|
{
|
|
VkImageType result{};
|
|
|
|
uint32_t dim_num{0};
|
|
|
|
if (extent.width >= 1)
|
|
{
|
|
dim_num++;
|
|
}
|
|
|
|
if (extent.height >= 1)
|
|
{
|
|
dim_num++;
|
|
}
|
|
|
|
if (extent.depth > 1)
|
|
{
|
|
dim_num++;
|
|
}
|
|
|
|
switch (dim_num)
|
|
{
|
|
case 1:
|
|
result = VK_IMAGE_TYPE_1D;
|
|
break;
|
|
case 2:
|
|
result = VK_IMAGE_TYPE_2D;
|
|
break;
|
|
case 3:
|
|
result = VK_IMAGE_TYPE_3D;
|
|
break;
|
|
default:
|
|
throw std::runtime_error("No image type found.");
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
} // namespace
|
|
|
|
namespace core
|
|
{
|
|
|
|
Image ImageBuilder::build(vkb::core::DeviceC &device) const
|
|
{
|
|
return Image(device, *this);
|
|
}
|
|
|
|
ImagePtr ImageBuilder::build_unique(vkb::core::DeviceC &device) const
|
|
{
|
|
return std::make_unique<Image>(device, *this);
|
|
}
|
|
|
|
Image::Image(vkb::core::DeviceC &device,
|
|
const VkExtent3D &extent,
|
|
VkFormat format,
|
|
VkImageUsageFlags image_usage,
|
|
VmaMemoryUsage memory_usage,
|
|
VkSampleCountFlagBits sample_count,
|
|
const uint32_t mip_levels,
|
|
const uint32_t array_layers,
|
|
VkImageTiling tiling,
|
|
VkImageCreateFlags flags,
|
|
uint32_t num_queue_families,
|
|
const uint32_t *queue_families) :
|
|
// Pass through to the ImageBuilder ctor
|
|
Image(device,
|
|
ImageBuilder(extent)
|
|
.with_format(format)
|
|
.with_image_type(find_image_type(extent))
|
|
.with_usage(image_usage)
|
|
.with_mip_levels(mip_levels)
|
|
.with_array_layers(array_layers)
|
|
.with_tiling(tiling)
|
|
.with_flags(flags)
|
|
.with_vma_usage(memory_usage)
|
|
.with_sample_count(sample_count)
|
|
.with_queue_families(num_queue_families, queue_families)
|
|
.with_implicit_sharing_mode())
|
|
{
|
|
}
|
|
|
|
Image::Image(vkb::core::DeviceC &device, ImageBuilder const &builder) :
|
|
vkb::allocated::AllocatedC<VkImage>{builder.get_allocation_create_info(), VK_NULL_HANDLE, &device}, create_info(builder.get_create_info())
|
|
{
|
|
set_handle(create_image(create_info));
|
|
subresource.arrayLayer = create_info.arrayLayers;
|
|
subresource.mipLevel = create_info.mipLevels;
|
|
if (!builder.get_debug_name().empty())
|
|
{
|
|
set_debug_name(builder.get_debug_name());
|
|
}
|
|
}
|
|
|
|
Image::Image(
|
|
vkb::core::DeviceC &device, VkImage handle, const VkExtent3D &extent, VkFormat format, VkImageUsageFlags image_usage, VkSampleCountFlagBits sample_count) :
|
|
vkb::allocated::AllocatedC<VkImage>{handle, &device}
|
|
{
|
|
create_info.extent = extent;
|
|
create_info.imageType = find_image_type(extent);
|
|
create_info.format = format;
|
|
create_info.samples = sample_count;
|
|
create_info.usage = image_usage;
|
|
subresource.arrayLayer = create_info.arrayLayers = 1;
|
|
subresource.mipLevel = create_info.mipLevels = 1;
|
|
}
|
|
|
|
Image::Image(Image &&other) noexcept
|
|
:
|
|
vkb::allocated::AllocatedC<VkImage>{std::move(other)}, create_info{std::exchange(other.create_info, {})}, subresource{std::exchange(other.subresource, {})}, views(std::exchange(other.views, {}))
|
|
{
|
|
// Update image views references to this image to avoid dangling pointers
|
|
for (auto &view : views)
|
|
{
|
|
view->set_image(*this);
|
|
}
|
|
}
|
|
|
|
Image::~Image()
|
|
{
|
|
destroy_image(get_handle());
|
|
}
|
|
|
|
VkImageType Image::get_type() const
|
|
{
|
|
return create_info.imageType;
|
|
}
|
|
|
|
const VkExtent3D &Image::get_extent() const
|
|
{
|
|
return create_info.extent;
|
|
}
|
|
|
|
VkFormat Image::get_format() const
|
|
{
|
|
return create_info.format;
|
|
}
|
|
|
|
VkSampleCountFlagBits Image::get_sample_count() const
|
|
{
|
|
return create_info.samples;
|
|
}
|
|
|
|
VkImageUsageFlags Image::get_usage() const
|
|
{
|
|
return create_info.usage;
|
|
}
|
|
|
|
VkImageTiling Image::get_tiling() const
|
|
{
|
|
return create_info.tiling;
|
|
}
|
|
|
|
const VkImageSubresource &Image::get_subresource() const
|
|
{
|
|
return subresource;
|
|
}
|
|
|
|
uint32_t Image::get_array_layer_count() const
|
|
{
|
|
return create_info.arrayLayers;
|
|
}
|
|
|
|
std::unordered_set<ImageView *> &Image::get_views()
|
|
{
|
|
return views;
|
|
}
|
|
|
|
VkDeviceSize Image::get_image_required_size() const
|
|
{
|
|
VkMemoryRequirements memory_requirements;
|
|
|
|
vkGetImageMemoryRequirements(get_device().get_handle(), get_handle(), &memory_requirements);
|
|
|
|
return memory_requirements.size;
|
|
}
|
|
|
|
VkImageCompressionPropertiesEXT Image::get_applied_compression() const
|
|
{
|
|
return query_applied_compression(get_device().get_handle(), get_handle());
|
|
}
|
|
} // namespace core
|
|
} // namespace vkb
|