BufferVk.h#

The PVRVk class, an object wrapping memory that is directly(non-image) accessible to the shaders.

Includes#

  • PVRVk/DeviceMemoryVk.h

  • PVRVk/DeviceVk.h

Included By#

Namespaces#

Classes#

Source Code#

#pragma once
#include "PVRVk/DeviceVk.h"
#include "PVRVk/DeviceMemoryVk.h"

namespace pvrvk {
struct BufferCreateInfo
{
public:
    BufferCreateInfo()
        : _flags(BufferCreateFlags::e_NONE), _size(0), _sharingMode(SharingMode::e_EXCLUSIVE), _usageFlags(BufferUsageFlags::e_NONE), _numQueueFamilyIndices(0),
          _queueFamilyIndices(nullptr)
    {}

    BufferCreateInfo(pvrvk::DeviceSize size, pvrvk::BufferUsageFlags usageFlags, pvrvk::BufferCreateFlags flags = pvrvk::BufferCreateFlags::e_NONE,
        SharingMode sharingMode = SharingMode::e_EXCLUSIVE, const uint32_t* queueFamilyIndices = nullptr, uint32_t numQueueFamilyIndices = 0)
        : _flags(flags), _size(size), _sharingMode(sharingMode), _usageFlags(usageFlags), _numQueueFamilyIndices(numQueueFamilyIndices), _queueFamilyIndices(queueFamilyIndices)
    {}

    inline BufferCreateFlags getFlags() const { return _flags; }
    inline void setFlags(BufferCreateFlags flags) { this->_flags = flags; }
    inline DeviceSize getSize() const { return _size; }
    inline void setSize(DeviceSize size) { this->_size = size; }
    inline SharingMode getSharingMode() const { return _sharingMode; }
    inline void setSharingMode(SharingMode sharingMode) { this->_sharingMode = sharingMode; }
    inline BufferUsageFlags getUsageFlags() const { return _usageFlags; }
    inline void setUsageFlags(BufferUsageFlags usageFlags) { this->_usageFlags = usageFlags; }
    inline uint32_t getNumQueueFamilyIndices() const { return _numQueueFamilyIndices; }
    inline void setNumQueueFamilyIndices(uint32_t numQueueFamilyIndices) { this->_numQueueFamilyIndices = numQueueFamilyIndices; }
    inline const uint32_t* getQueueFamilyIndices() const { return _queueFamilyIndices; }

private:
    BufferCreateFlags _flags;
    DeviceSize _size;
    SharingMode _sharingMode;
    BufferUsageFlags _usageFlags;
    uint32_t _numQueueFamilyIndices;
    const uint32_t* _queueFamilyIndices;
};

namespace impl {
class Buffer_ : public PVRVkDeviceObjectBase<VkBuffer, ObjectType::e_BUFFER>, public DeviceObjectDebugUtils<Buffer_>
{
private:
    friend class Device_;

    class make_shared_enabler
    {
    protected:
        make_shared_enabler() {}
        friend class Buffer_;
    };

    static Buffer constructShared(const DeviceWeakPtr& device, const BufferCreateInfo& createInfo) { return std::make_shared<Buffer_>(make_shared_enabler{}, device, createInfo); }

    BufferCreateInfo _createInfo;
    MemoryRequirements _memRequirements;
    VkDeviceSize _memoryOffset;
    DeviceMemory _deviceMemory;

public:
    DECLARE_NO_COPY_SEMANTICS(Buffer_)
    Buffer_(make_shared_enabler, const DeviceWeakPtr& device, const BufferCreateInfo& createInfo);

    ~Buffer_();

    DeviceMemory& getDeviceMemory() { return _deviceMemory; }

    inline BufferCreateFlags getFlags() const { return _createInfo.getFlags(); }

    inline bool hasCreateFlag(pvrvk::BufferCreateFlags flags) const { return (_createInfo.getFlags() & flags) == flags; }

    inline bool hasUsageFlag(pvrvk::BufferUsageFlags flags) const { return (_createInfo.getUsageFlags() & flags) == flags; }

    inline DeviceSize getSize() const { return _createInfo.getSize(); }

    inline SharingMode getSharingMode() const { return _createInfo.getSharingMode(); }

    inline BufferUsageFlags getUsageFlags() const { return _createInfo.getUsageFlags(); }

    inline uint32_t getNumQueueFamilyIndices() const { return _createInfo.getNumQueueFamilyIndices(); }

    inline const uint32_t* getQueueFamilyIndices() const { return _createInfo.getQueueFamilyIndices(); }

    void bindMemory(DeviceMemory deviceMemory, VkDeviceSize offset)
    {
        if (isSparseBuffer()) { throw ErrorValidationFailedEXT("Cannot call bindMemory on a sparse buffer"); }

        if (_deviceMemory) { throw ErrorValidationFailedEXT("Cannot bind a memory block as Buffer already has a memory block bound"); }
        _memoryOffset = offset;
        _deviceMemory = deviceMemory;

        vkThrowIfFailed(static_cast<Result>(getDevice()->getVkBindings().vkBindBufferMemory(getDevice()->getVkHandle(), getVkHandle(), _deviceMemory->getVkHandle(), offset)),
            "Failed to bind memory to buffer");
    }

    BufferCreateInfo getCreateInfo() const { return _createInfo; }

    bool isSparseBuffer() const
    {
        return (_createInfo.getFlags() & (BufferCreateFlags::e_SPARSE_ALIASED_BIT | BufferCreateFlags::e_SPARSE_BINDING_BIT | BufferCreateFlags::e_SPARSE_RESIDENCY_BIT)) != 0;
    }

    const MemoryRequirements& getMemoryRequirement() const { return _memRequirements; }

    VkDeviceAddress getDeviceAddress(const Device device)
    {
        VkBufferDeviceAddressInfo bufferDeviceAddressInfo = { static_cast<VkStructureType>(StructureType::e_BUFFER_DEVICE_ADDRESS_INFO_KHR), nullptr, getVkHandle() };

        // Depending on the instance version, use the extension version or the core version
        if (device->getPhysicalDevice()->getInstance()->getCreateInfo().getApplicationInfo().getApiVersion() >= VK_MAKE_VERSION(1, 2, 0))
        {
            return device->getVkBindings().vkGetBufferDeviceAddress(device->getVkHandle(), &bufferDeviceAddressInfo);
        }
        else if (device->getEnabledExtensionTable().khrBufferDeviceAddressEnabled)
        {
            return device->getVkBindings().vkGetBufferDeviceAddressKHR(device->getVkHandle(), &bufferDeviceAddressInfo);
        }
        else if (device->getEnabledExtensionTable().extBufferDeviceAddressEnabled)
        {
            return device->getVkBindings().vkGetBufferDeviceAddressEXT(device->getVkHandle(), &bufferDeviceAddressInfo);
        }

        assert(false && "Cannot retrieve device address");
        return 0;
    }
};
} // namespace impl

struct BufferViewCreateInfo
{
public:
    BufferViewCreateInfo() : _format(Format::e_UNDEFINED), _offset(0), _range(VK_WHOLE_SIZE), _flags(BufferViewCreateFlags::e_NONE) {}

    BufferViewCreateInfo(const Buffer& buffer, Format format, DeviceSize offset = 0, DeviceSize range = VK_WHOLE_SIZE, BufferViewCreateFlags flags = BufferViewCreateFlags::e_NONE)
        : _buffer(buffer), _format(format), _offset(offset), _range(range), _flags(flags)
    {
        assert(range <= buffer->getSize() - offset);
    }

    inline BufferViewCreateFlags getFlags() const { return _flags; }
    inline void setFlags(BufferViewCreateFlags flags) { this->_flags = flags; }
    inline const Buffer& getBuffer() const { return _buffer; }
    inline void setBuffer(const Buffer& buffer) { this->_buffer = buffer; }
    inline Format getFormat() const { return _format; }
    inline void setFormat(Format format) { this->_format = format; }
    inline DeviceSize getOffset() const { return _offset; }
    inline void setOffset(DeviceSize offset) { this->_offset = offset; }
    inline DeviceSize getRange() const { return _range; }
    inline void setRange(DeviceSize range) { this->_range = range; }

private:
    Buffer _buffer;
    Format _format;
    DeviceSize _offset;
    DeviceSize _range;
    BufferViewCreateFlags _flags;
};

namespace impl {
class BufferView_ : public PVRVkDeviceObjectBase<VkBufferView, ObjectType::e_BUFFER_VIEW>, public DeviceObjectDebugUtils<BufferView_>
{
private:
    friend class Device_;

    class make_shared_enabler
    {
    protected:
        make_shared_enabler() {}
        friend class BufferView_;
    };

    static BufferView constructShared(const DeviceWeakPtr& device, const BufferViewCreateInfo& createInfo)
    {
        return std::make_shared<BufferView_>(make_shared_enabler{}, device, createInfo);
    }

    BufferViewCreateInfo _createInfo;

public:
    DECLARE_NO_COPY_SEMANTICS(BufferView_)

    BufferView_(make_shared_enabler, const DeviceWeakPtr& device, const BufferViewCreateInfo& createInfo);

    ~BufferView_();

    inline BufferViewCreateFlags getFlags() const { return _createInfo.getFlags(); }
    inline const Buffer& getBuffer() const { return _createInfo.getBuffer(); }
    inline Format getFormat() const { return _createInfo.getFormat(); }
    inline DeviceSize getOffset() const { return _createInfo.getOffset(); }
    inline DeviceSize getRange() const { return _createInfo.getRange(); }
    const BufferViewCreateInfo& getCreateInfo() const { return _createInfo; }
};
} // namespace impl
} // namespace pvrvk