init
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
/* Copyright (c) 2019-2025, Arm Limited and Contributors
|
||||
* Copyright (c) 2021-2025, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "builder_base.h"
|
||||
#include "common/vk_common.h"
|
||||
#include "core/allocated.h"
|
||||
|
||||
namespace vkb
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
template <vkb::BindingType bindingType>
|
||||
class Buffer;
|
||||
template <vkb::BindingType bindingType>
|
||||
using BufferPtr = std::unique_ptr<Buffer<bindingType>>;
|
||||
template <vkb::BindingType bindingType>
|
||||
class Device;
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
struct BufferBuilder
|
||||
: public vkb::allocated::BuilderBase<bindingType,
|
||||
BufferBuilder<bindingType>,
|
||||
typename std::conditional<bindingType == vkb::BindingType::Cpp, vk::BufferCreateInfo, VkBufferCreateInfo>::type>
|
||||
{
|
||||
public:
|
||||
using BufferCreateFlagsType = typename std::conditional<bindingType == vkb::BindingType::Cpp, vk::BufferCreateFlags, VkBufferCreateFlags>::type;
|
||||
using BufferCreateInfoType = typename std::conditional<bindingType == vkb::BindingType::Cpp, vk::BufferCreateInfo, VkBufferCreateInfo>::type;
|
||||
using BufferUsageFlagsType = typename std::conditional<bindingType == vkb::BindingType::Cpp, vk::BufferUsageFlags, VkBufferUsageFlags>::type;
|
||||
using DeviceSizeType = typename std::conditional<bindingType == vkb::BindingType::Cpp, vk::DeviceSize, VkDeviceSize>::type;
|
||||
using SharingModeType = typename std::conditional<bindingType == vkb::BindingType::Cpp, vk::SharingMode, VkSharingMode>::type;
|
||||
|
||||
private:
|
||||
using ParentType = vkb::allocated::BuilderBase<bindingType, BufferBuilder<bindingType>, BufferCreateInfoType>;
|
||||
|
||||
public:
|
||||
BufferBuilder(DeviceSizeType size);
|
||||
|
||||
Buffer<bindingType> build(vkb::core::Device<bindingType> &device) const;
|
||||
BufferPtr<bindingType> build_unique(vkb::core::Device<bindingType> &device) const;
|
||||
BufferBuilder &with_flags(BufferCreateFlagsType flags);
|
||||
BufferBuilder &with_usage(BufferUsageFlagsType usage);
|
||||
};
|
||||
|
||||
using BufferBuilderC = BufferBuilder<vkb::BindingType::C>;
|
||||
using BufferBuilderCpp = BufferBuilder<vkb::BindingType::Cpp>;
|
||||
|
||||
template <>
|
||||
inline BufferBuilder<vkb::BindingType::Cpp>::BufferBuilder(vk::DeviceSize size) :
|
||||
ParentType(BufferCreateInfoType{.size = size})
|
||||
{
|
||||
}
|
||||
|
||||
template <>
|
||||
inline BufferBuilder<vkb::BindingType::C>::BufferBuilder(VkDeviceSize size) :
|
||||
ParentType(VkBufferCreateInfo{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, nullptr, 0, size})
|
||||
{}
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
inline Buffer<bindingType> BufferBuilder<bindingType>::build(vkb::core::Device<bindingType> &device) const
|
||||
{
|
||||
return Buffer<bindingType>{device, *this};
|
||||
}
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
inline BufferPtr<bindingType> BufferBuilder<bindingType>::build_unique(vkb::core::Device<bindingType> &device) const
|
||||
{
|
||||
return std::make_unique<Buffer<bindingType>>(device, *this);
|
||||
}
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
inline BufferBuilder<bindingType> &BufferBuilder<bindingType>::with_flags(BufferCreateFlagsType flags)
|
||||
{
|
||||
this->create_info.flags = flags;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
inline BufferBuilder<bindingType> &BufferBuilder<bindingType>::with_usage(BufferUsageFlagsType usage)
|
||||
{
|
||||
this->get_create_info().usage = usage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*=========================================================*/
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
class Buffer
|
||||
: public vkb::allocated::Allocated<bindingType, typename std::conditional<bindingType == vkb::BindingType::Cpp, vk::Buffer, VkBuffer>::type>
|
||||
{
|
||||
public:
|
||||
using BufferType = typename std::conditional<bindingType == vkb::BindingType::Cpp, vk::Buffer, VkBuffer>::type;
|
||||
using BufferUsageFlagsType = typename std::conditional<bindingType == vkb::BindingType::Cpp, vk::BufferUsageFlags, VkBufferUsageFlags>::type;
|
||||
using DeviceSizeType = typename std::conditional<bindingType == vkb::BindingType::Cpp, vk::DeviceSize, VkDeviceSize>::type;
|
||||
|
||||
private:
|
||||
using ParentType = vkb::allocated::Allocated<bindingType, BufferType>;
|
||||
|
||||
public:
|
||||
static Buffer<bindingType> create_staging_buffer(vkb::core::Device<bindingType> &device, DeviceSizeType size, const void *data);
|
||||
|
||||
template <typename T>
|
||||
static Buffer create_staging_buffer(vkb::core::Device<bindingType> &device, std::vector<T> const &data);
|
||||
|
||||
template <typename T>
|
||||
static Buffer create_staging_buffer(vkb::core::Device<bindingType> &device, const T &data);
|
||||
|
||||
Buffer() = delete;
|
||||
Buffer(const Buffer &) = delete;
|
||||
Buffer(Buffer &&other) = default;
|
||||
Buffer &operator=(const Buffer &) = delete;
|
||||
Buffer &operator=(Buffer &&) = default;
|
||||
|
||||
/**
|
||||
* @brief Creates a buffer using VMA
|
||||
* @param device A valid Vulkan device
|
||||
* @param size The size in bytes of the buffer
|
||||
* @param buffer_usage The usage flags for the VkBuffer
|
||||
* @param memory_usage The memory usage of the buffer
|
||||
* @param flags The allocation create flags
|
||||
* @param queue_family_indices optional queue family indices
|
||||
*/
|
||||
// [[deprecated("Use the BufferBuilder ctor instead")]]
|
||||
Buffer(vkb::core::Device<bindingType> &device,
|
||||
DeviceSizeType size,
|
||||
BufferUsageFlagsType buffer_usage,
|
||||
VmaMemoryUsage memory_usage,
|
||||
VmaAllocationCreateFlags flags = VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT,
|
||||
const std::vector<uint32_t> &queue_family_indices = {});
|
||||
|
||||
Buffer(vkb::core::Device<bindingType> &device, BufferBuilder<bindingType> const &builder);
|
||||
|
||||
~Buffer();
|
||||
|
||||
/**
|
||||
* @return Return the buffer's device address (note: requires that the buffer has been created with the VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT usage fla)
|
||||
*/
|
||||
uint64_t get_device_address() const;
|
||||
|
||||
/**
|
||||
* @return The size of the buffer
|
||||
*/
|
||||
DeviceSizeType get_size() const;
|
||||
|
||||
private:
|
||||
static Buffer<vkb::BindingType::Cpp> create_staging_buffer_impl(vkb::core::DeviceCpp &device, vk::DeviceSize size, const void *data);
|
||||
|
||||
private:
|
||||
vk::DeviceSize size = 0;
|
||||
};
|
||||
|
||||
using BufferC = Buffer<vkb::BindingType::C>;
|
||||
using BufferCpp = Buffer<vkb::BindingType::Cpp>;
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
template <typename T>
|
||||
inline Buffer<bindingType> Buffer<bindingType>::create_staging_buffer(vkb::core::Device<bindingType> &device, const T &data)
|
||||
{
|
||||
return create_staging_buffer(device, sizeof(T), &data);
|
||||
}
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
inline Buffer<bindingType> Buffer<bindingType>::create_staging_buffer(vkb::core::Device<bindingType> &device, DeviceSizeType size, const void *data)
|
||||
{
|
||||
if constexpr (bindingType == vkb::BindingType::Cpp)
|
||||
{
|
||||
return create_staging_buffer_impl(device, size, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
BufferCpp buffer = create_staging_buffer_impl(reinterpret_cast<vkb::core::DeviceCpp &>(device), static_cast<vk::DeviceSize>(size), data);
|
||||
return std::move(*reinterpret_cast<BufferC *>(&buffer));
|
||||
}
|
||||
}
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
inline BufferCpp Buffer<bindingType>::create_staging_buffer_impl(vkb::core::DeviceCpp &device, vk::DeviceSize size, const void *data)
|
||||
{
|
||||
BufferBuilderCpp builder(size);
|
||||
builder.with_vma_flags(VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT)
|
||||
.with_usage(vk::BufferUsageFlagBits::eTransferSrc);
|
||||
BufferCpp result(device, builder);
|
||||
if (data != nullptr)
|
||||
{
|
||||
result.update(data, size);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
template <typename T>
|
||||
inline Buffer<bindingType> Buffer<bindingType>::create_staging_buffer(vkb::core::Device<bindingType> &device, std::vector<T> const &data)
|
||||
{
|
||||
return create_staging_buffer(device, data.size() * sizeof(T), data.data());
|
||||
}
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
inline Buffer<bindingType>::Buffer(vkb::core::Device<bindingType> &device,
|
||||
DeviceSizeType size,
|
||||
BufferUsageFlagsType buffer_usage,
|
||||
VmaMemoryUsage memory_usage,
|
||||
VmaAllocationCreateFlags flags,
|
||||
const std::vector<uint32_t> &queue_family_indices) :
|
||||
Buffer(device,
|
||||
BufferBuilder<bindingType>(size)
|
||||
.with_usage(buffer_usage)
|
||||
.with_vma_usage(memory_usage)
|
||||
.with_vma_flags(flags)
|
||||
.with_queue_families(queue_family_indices)
|
||||
.with_implicit_sharing_mode())
|
||||
{}
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
inline Buffer<bindingType>::Buffer(vkb::core::Device<bindingType> &device, const BufferBuilder<bindingType> &builder) :
|
||||
ParentType(builder.get_allocation_create_info(), nullptr, &device), size(builder.get_create_info().size)
|
||||
{
|
||||
this->set_handle(this->create_buffer(builder.get_create_info()));
|
||||
if (!builder.get_debug_name().empty())
|
||||
{
|
||||
this->set_debug_name(builder.get_debug_name());
|
||||
}
|
||||
}
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
inline Buffer<bindingType>::~Buffer()
|
||||
{
|
||||
this->destroy_buffer(this->get_handle());
|
||||
}
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
inline uint64_t Buffer<bindingType>::get_device_address() const
|
||||
{
|
||||
if constexpr (bindingType == vkb::BindingType::Cpp)
|
||||
{
|
||||
return this->get_device().get_handle().getBufferAddressKHR({.buffer = this->get_handle()});
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<vk::Device>(this->get_device().get_handle()).getBufferAddressKHR({.buffer = static_cast<vk::Buffer>(this->get_handle())});
|
||||
}
|
||||
}
|
||||
|
||||
template <vkb::BindingType bindingType>
|
||||
inline typename Buffer<bindingType>::DeviceSizeType Buffer<bindingType>::get_size() const
|
||||
{
|
||||
if constexpr (bindingType == vkb::BindingType::Cpp)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<VkDeviceSize>(size);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace core
|
||||
} // namespace vkb
|
||||
Reference in New Issue
Block a user