Added VMA
This commit is contained in:
@@ -24,6 +24,7 @@ target_compile_definitions(${ENGINE_NAME} PUBLIC
|
|||||||
|
|
||||||
target_link_libraries(${ENGINE_NAME} PUBLIC
|
target_link_libraries(${ENGINE_NAME} PUBLIC
|
||||||
vulkan
|
vulkan
|
||||||
|
vma
|
||||||
shaderc
|
shaderc
|
||||||
glfw
|
glfw
|
||||||
glm
|
glm
|
||||||
|
|||||||
@@ -28,26 +28,32 @@ Buffer::Buffer(Device& device, vk::DeviceSize instanceSize, u32 instanceCount,
|
|||||||
alignmentSize = getAlignment(instanceSize, minOffsetAlignment);
|
alignmentSize = getAlignment(instanceSize, minOffsetAlignment);
|
||||||
bufferSize = alignmentSize * instanceCount;
|
bufferSize = alignmentSize * instanceCount;
|
||||||
device.createBuffer(bufferSize, usageFlags, memoryPropertyFlags, buffer,
|
device.createBuffer(bufferSize, usageFlags, memoryPropertyFlags, buffer,
|
||||||
memory);
|
allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::~Buffer() {
|
Buffer::~Buffer() {
|
||||||
unmap();
|
unmap();
|
||||||
this->device.get()->destroyBuffer(this->buffer);
|
vmaDestroyBuffer(this->device.getAllocator(), this->buffer, this->allocation);
|
||||||
this->device.get()->freeMemory(this->memory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VMA always maps the whole allocation, so `size` only exists to keep the
|
||||||
|
// interface; `offset` is applied to the returned pointer.
|
||||||
vk::Result Buffer::map(vk::DeviceSize size, vk::DeviceSize offset) {
|
vk::Result Buffer::map(vk::DeviceSize size, vk::DeviceSize offset) {
|
||||||
SOPHIA_ASSERT(buffer && memory, "Called map on buffer before create");
|
SOPHIA_ASSERT(buffer && allocation, "Called map on buffer before create");
|
||||||
|
(void)size;
|
||||||
|
|
||||||
vk::MemoryMapFlags emptyFlag{};
|
void* base = nullptr;
|
||||||
return this->device.get()->mapMemory(this->memory, offset, size, emptyFlag,
|
vk::Result result = static_cast<vk::Result>(
|
||||||
&this->mapped);
|
vmaMapMemory(this->device.getAllocator(), this->allocation, &base));
|
||||||
|
if (result == vk::Result::eSuccess) {
|
||||||
|
this->mapped = static_cast<char*>(base) + offset;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::unmap() {
|
void Buffer::unmap() {
|
||||||
if (mapped) {
|
if (mapped) {
|
||||||
this->device.get()->unmapMemory(this->memory);
|
vmaUnmapMemory(this->device.getAllocator(), this->allocation);
|
||||||
mapped = nullptr;
|
mapped = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,19 +72,13 @@ void Buffer::writeToBuffer(void* data, vk::DeviceSize size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
vk::Result Buffer::flush(vk::DeviceSize size, vk::DeviceSize offset) {
|
vk::Result Buffer::flush(vk::DeviceSize size, vk::DeviceSize offset) {
|
||||||
vk::MappedMemoryRange mappedRange = {};
|
return static_cast<vk::Result>(vmaFlushAllocation(
|
||||||
mappedRange.memory = memory;
|
this->device.getAllocator(), this->allocation, offset, size));
|
||||||
mappedRange.offset = offset;
|
|
||||||
mappedRange.size = size;
|
|
||||||
return this->device.get()->flushMappedMemoryRanges(1, &mappedRange);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::Result Buffer::invalidate(vk::DeviceSize size, vk::DeviceSize offset) {
|
vk::Result Buffer::invalidate(vk::DeviceSize size, vk::DeviceSize offset) {
|
||||||
vk::MappedMemoryRange mappedRange = {};
|
return static_cast<vk::Result>(vmaInvalidateAllocation(
|
||||||
mappedRange.memory = memory;
|
this->device.getAllocator(), this->allocation, offset, size));
|
||||||
mappedRange.offset = offset;
|
|
||||||
mappedRange.size = size;
|
|
||||||
return this->device.get()->invalidateMappedMemoryRanges(1, &mappedRange);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::DescriptorBufferInfo Buffer::descriptorInfo(vk::DeviceSize size,
|
vk::DescriptorBufferInfo Buffer::descriptorInfo(vk::DeviceSize size,
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class Buffer {
|
|||||||
Device& device;
|
Device& device;
|
||||||
void* mapped = nullptr;
|
void* mapped = nullptr;
|
||||||
vk::Buffer buffer = VK_NULL_HANDLE;
|
vk::Buffer buffer = VK_NULL_HANDLE;
|
||||||
vk::DeviceMemory memory = VK_NULL_HANDLE;
|
VmaAllocation allocation = VK_NULL_HANDLE;
|
||||||
|
|
||||||
vk::DeviceSize bufferSize;
|
vk::DeviceSize bufferSize;
|
||||||
uint32_t instanceCount;
|
uint32_t instanceCount;
|
||||||
|
|||||||
@@ -69,10 +69,14 @@ Device::Device(Window* window)
|
|||||||
}
|
}
|
||||||
pickPhysicalDevice();
|
pickPhysicalDevice();
|
||||||
createLogicalDevice();
|
createLogicalDevice();
|
||||||
|
createAllocator();
|
||||||
createCommandPool();
|
createCommandPool();
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
|
vmaDestroyAllocator(this->allocator);
|
||||||
|
log::trace("destroyed VmaAllocator");
|
||||||
|
|
||||||
if (this->enableValidationLayers) {
|
if (this->enableValidationLayers) {
|
||||||
destroyDebugUtilsMessengerEXT(this->instance.get(), this->debugMessenger,
|
destroyDebugUtilsMessengerEXT(this->instance.get(), this->debugMessenger,
|
||||||
nullptr);
|
nullptr);
|
||||||
@@ -88,22 +92,6 @@ Device::~Device() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Device::findMemoryType(u32 typeFilter, vk::MemoryPropertyFlags properties) {
|
|
||||||
vk::PhysicalDeviceMemoryProperties memoryProperties =
|
|
||||||
this->physicalDevice.getMemoryProperties();
|
|
||||||
|
|
||||||
for (u32 i = 0; i < memoryProperties.memoryTypeCount; i++) {
|
|
||||||
if ((typeFilter & (1 << i)) &&
|
|
||||||
(memoryProperties.memoryTypes[i].propertyFlags & properties) ==
|
|
||||||
properties) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log::fatal("failed to find suitable memory type");
|
|
||||||
throw std::runtime_error("failed to find suitable memory type");
|
|
||||||
}
|
|
||||||
|
|
||||||
vk::Format Device::findSupportedFormat(
|
vk::Format Device::findSupportedFormat(
|
||||||
const std::vector<vk::Format>& candidates, vk::ImageTiling tiling,
|
const std::vector<vk::Format>& candidates, vk::ImageTiling tiling,
|
||||||
vk::FormatFeatureFlags features) {
|
vk::FormatFeatureFlags features) {
|
||||||
@@ -125,35 +113,26 @@ vk::Format Device::findSupportedFormat(
|
|||||||
|
|
||||||
void Device::createBuffer(vk::DeviceSize size, vk::BufferUsageFlags usage,
|
void Device::createBuffer(vk::DeviceSize size, vk::BufferUsageFlags usage,
|
||||||
vk::MemoryPropertyFlags properties,
|
vk::MemoryPropertyFlags properties,
|
||||||
vk::Buffer& buffer, vk::DeviceMemory& bufferMemory) {
|
vk::Buffer& buffer, VmaAllocation& allocation) {
|
||||||
vk::BufferCreateInfo bufferInfo = {};
|
vk::BufferCreateInfo bufferInfo = {};
|
||||||
bufferInfo.size = size;
|
bufferInfo.size = size;
|
||||||
bufferInfo.usage = usage;
|
bufferInfo.usage = usage;
|
||||||
bufferInfo.sharingMode = vk::SharingMode::eExclusive;
|
bufferInfo.sharingMode = vk::SharingMode::eExclusive;
|
||||||
|
|
||||||
try {
|
VmaAllocationCreateInfo allocInfo = {};
|
||||||
buffer = this->device->createBuffer(bufferInfo);
|
allocInfo.requiredFlags = static_cast<VkMemoryPropertyFlags>(properties);
|
||||||
} catch (const vk::SystemError& error) {
|
|
||||||
log::fatal("failed to create vertex buffer");
|
VkBuffer rawBuffer = VK_NULL_HANDLE;
|
||||||
throw std::runtime_error("failed to create vertex buffer");
|
VkResult result = vmaCreateBuffer(
|
||||||
|
this->allocator, &static_cast<const VkBufferCreateInfo&>(bufferInfo),
|
||||||
|
&allocInfo, &rawBuffer, &allocation, nullptr);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
log::fatal("failed to create buffer. Error: ",
|
||||||
|
vk::to_string(static_cast<vk::Result>(result)));
|
||||||
|
throw std::runtime_error("failed to create buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::MemoryRequirements memoryRequirements =
|
buffer = rawBuffer;
|
||||||
this->device->getBufferMemoryRequirements(buffer);
|
|
||||||
|
|
||||||
vk::MemoryAllocateInfo allocInfo = {};
|
|
||||||
allocInfo.allocationSize = memoryRequirements.size;
|
|
||||||
allocInfo.memoryTypeIndex =
|
|
||||||
findMemoryType(memoryRequirements.memoryTypeBits, properties);
|
|
||||||
|
|
||||||
try {
|
|
||||||
bufferMemory = this->device->allocateMemory(allocInfo);
|
|
||||||
} catch (const vk::SystemError& error) {
|
|
||||||
log::fatal("failed to allocate vertex buffer memory");
|
|
||||||
throw std::runtime_error("failed to allocate vertex buffer memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
this->device->bindBufferMemory(buffer, bufferMemory, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::CommandBuffer Device::beginSingleTimeCommands() {
|
vk::CommandBuffer Device::beginSingleTimeCommands() {
|
||||||
@@ -220,43 +199,21 @@ void Device::copyBuffer(vk::Buffer sourceBuffer, vk::Buffer destinationBuffer,
|
|||||||
|
|
||||||
void Device::createImageWithInfo(const vk::ImageCreateInfo& imageInfo,
|
void Device::createImageWithInfo(const vk::ImageCreateInfo& imageInfo,
|
||||||
vk::MemoryPropertyFlags properties,
|
vk::MemoryPropertyFlags properties,
|
||||||
vk::Image& image,
|
vk::Image& image, VmaAllocation& allocation) {
|
||||||
vk::DeviceMemory& imageMemory) {
|
VmaAllocationCreateInfo allocInfo = {};
|
||||||
try {
|
allocInfo.requiredFlags = static_cast<VkMemoryPropertyFlags>(properties);
|
||||||
vk::Result result = this->device->createImage(&imageInfo, nullptr, &image);
|
|
||||||
if (result != vk::Result::eSuccess) {
|
VkImage rawImage = VK_NULL_HANDLE;
|
||||||
throw vk::SystemError(result);
|
VkResult result = vmaCreateImage(
|
||||||
}
|
this->allocator, &static_cast<const VkImageCreateInfo&>(imageInfo),
|
||||||
} catch (const vk::SystemError& error) {
|
&allocInfo, &rawImage, &allocation, nullptr);
|
||||||
log::fatal("failed to create image. Error: ", error.what());
|
if (result != VK_SUCCESS) {
|
||||||
|
log::fatal("failed to create image. Error: ",
|
||||||
|
vk::to_string(static_cast<vk::Result>(result)));
|
||||||
throw std::runtime_error("failed to create image");
|
throw std::runtime_error("failed to create image");
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::MemoryRequirements memoryRequirements =
|
image = rawImage;
|
||||||
this->device->getImageMemoryRequirements(image);
|
|
||||||
|
|
||||||
vk::MemoryAllocateInfo allocateInfo{};
|
|
||||||
allocateInfo.allocationSize = memoryRequirements.size;
|
|
||||||
allocateInfo.memoryTypeIndex =
|
|
||||||
findMemoryType(memoryRequirements.memoryTypeBits, properties);
|
|
||||||
|
|
||||||
try {
|
|
||||||
vk::Result result =
|
|
||||||
this->device->allocateMemory(&allocateInfo, nullptr, &imageMemory);
|
|
||||||
if (result != vk::Result::eSuccess) {
|
|
||||||
throw vk::SystemError(result);
|
|
||||||
}
|
|
||||||
} catch (const vk::SystemError& error) {
|
|
||||||
log::fatal("failed to allocate image memory. Error: ", error.what());
|
|
||||||
throw std::runtime_error("failed to allocate image memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
this->device->bindImageMemory(image, imageMemory, 0);
|
|
||||||
} catch (const vk::SystemError& error) {
|
|
||||||
log::fatal("failed to bind image memory. Error: ", error.what());
|
|
||||||
throw std::runtime_error("failed to bind image memory");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::populateImGuiInitInfo(ImGui_ImplVulkan_InitInfo& initInfo) {
|
void Device::populateImGuiInitInfo(ImGui_ImplVulkan_InitInfo& initInfo) {
|
||||||
@@ -514,6 +471,20 @@ void Device::createLogicalDevice() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Device::createAllocator() {
|
||||||
|
VmaAllocatorCreateInfo createInfo = {};
|
||||||
|
createInfo.vulkanApiVersion = SOPHIA_VULKAN_API_VERSION;
|
||||||
|
createInfo.instance = this->instance.get();
|
||||||
|
createInfo.physicalDevice = this->physicalDevice;
|
||||||
|
createInfo.device = this->device.get();
|
||||||
|
|
||||||
|
if (vmaCreateAllocator(&createInfo, &this->allocator) != VK_SUCCESS) {
|
||||||
|
log::fatal("failed to create VmaAllocator");
|
||||||
|
throw std::runtime_error("failed to create VmaAllocator");
|
||||||
|
}
|
||||||
|
log::trace("created VmaAllocator");
|
||||||
|
}
|
||||||
|
|
||||||
SwapchainSupportDetails Device::querySwapchainSupport(
|
SwapchainSupportDetails Device::querySwapchainSupport(
|
||||||
vk::PhysicalDevice device) {
|
vk::PhysicalDevice device) {
|
||||||
SwapchainSupportDetails details;
|
SwapchainSupportDetails details;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <imgui_impl_vulkan.h>
|
#include <imgui_impl_vulkan.h>
|
||||||
|
#include <vk_mem_alloc.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -47,6 +48,7 @@ class Device {
|
|||||||
|
|
||||||
void waitIdle() { this->device->waitIdle(); }
|
void waitIdle() { this->device->waitIdle(); }
|
||||||
|
|
||||||
|
VmaAllocator getAllocator() const { return this->allocator; }
|
||||||
vk::CommandPool getCommandPool() const { return this->commandPool; }
|
vk::CommandPool getCommandPool() const { return this->commandPool; }
|
||||||
vk::SurfaceKHR getSurface() const { return surface; }
|
vk::SurfaceKHR getSurface() const { return surface; }
|
||||||
vk::Queue getGraphicsQueue() const { return graphicsQueue; }
|
vk::Queue getGraphicsQueue() const { return graphicsQueue; }
|
||||||
@@ -60,15 +62,13 @@ class Device {
|
|||||||
return querySwapchainSupport(this->physicalDevice);
|
return querySwapchainSupport(this->physicalDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 findMemoryType(u32 typeFilter, vk::MemoryPropertyFlags properties);
|
|
||||||
|
|
||||||
vk::Format findSupportedFormat(const std::vector<vk::Format>& candidates,
|
vk::Format findSupportedFormat(const std::vector<vk::Format>& candidates,
|
||||||
vk::ImageTiling tiling,
|
vk::ImageTiling tiling,
|
||||||
vk::FormatFeatureFlags features);
|
vk::FormatFeatureFlags features);
|
||||||
|
|
||||||
void createBuffer(vk::DeviceSize size, vk::BufferUsageFlags usage,
|
void createBuffer(vk::DeviceSize size, vk::BufferUsageFlags usage,
|
||||||
vk::MemoryPropertyFlags properties, vk::Buffer& buffer,
|
vk::MemoryPropertyFlags properties, vk::Buffer& buffer,
|
||||||
vk::DeviceMemory& bufferMemory);
|
VmaAllocation& allocation);
|
||||||
|
|
||||||
vk::CommandBuffer beginSingleTimeCommands();
|
vk::CommandBuffer beginSingleTimeCommands();
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ class Device {
|
|||||||
|
|
||||||
void createImageWithInfo(const vk::ImageCreateInfo& imageInfo,
|
void createImageWithInfo(const vk::ImageCreateInfo& imageInfo,
|
||||||
vk::MemoryPropertyFlags properties, vk::Image& image,
|
vk::MemoryPropertyFlags properties, vk::Image& image,
|
||||||
vk::DeviceMemory& imageMemory);
|
VmaAllocation& allocation);
|
||||||
|
|
||||||
void populateImGuiInitInfo(ImGui_ImplVulkan_InitInfo& initInfo);
|
void populateImGuiInitInfo(ImGui_ImplVulkan_InitInfo& initInfo);
|
||||||
|
|
||||||
@@ -100,6 +100,7 @@ class Device {
|
|||||||
SwapchainSupportDetails querySwapchainSupport(vk::PhysicalDevice device);
|
SwapchainSupportDetails querySwapchainSupport(vk::PhysicalDevice device);
|
||||||
|
|
||||||
void createLogicalDevice();
|
void createLogicalDevice();
|
||||||
|
void createAllocator();
|
||||||
void createCommandPool();
|
void createCommandPool();
|
||||||
|
|
||||||
vk::UniqueInstance instance;
|
vk::UniqueInstance instance;
|
||||||
@@ -111,6 +112,8 @@ class Device {
|
|||||||
vk::PhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
vk::PhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
||||||
vk::UniqueDevice device;
|
vk::UniqueDevice device;
|
||||||
|
|
||||||
|
VmaAllocator allocator = VK_NULL_HANDLE;
|
||||||
|
|
||||||
vk::Queue graphicsQueue;
|
vk::Queue graphicsQueue;
|
||||||
vk::Queue presentQueue;
|
vk::Queue presentQueue;
|
||||||
|
|
||||||
|
|||||||
+34
-20
@@ -3,11 +3,35 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sophia/util/logger.hpp>
|
#include <sophia/util/logger.hpp>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "vulkan/device.hpp"
|
#include "vulkan/device.hpp"
|
||||||
|
|
||||||
namespace sophia {
|
namespace sophia {
|
||||||
|
|
||||||
|
Image::Image(Image&& other) noexcept
|
||||||
|
: device{other.device},
|
||||||
|
externalImage{other.externalImage},
|
||||||
|
image{std::exchange(other.image, nullptr)},
|
||||||
|
allocation{std::exchange(other.allocation, VK_NULL_HANDLE)},
|
||||||
|
view{std::move(other.view)},
|
||||||
|
sampler{std::move(other.sampler)},
|
||||||
|
format{other.format},
|
||||||
|
extent{other.extent},
|
||||||
|
aspectMask{other.aspectMask},
|
||||||
|
mipLevels{other.mipLevels},
|
||||||
|
arrayLayers{other.arrayLayers},
|
||||||
|
layout{other.layout} {}
|
||||||
|
|
||||||
|
Image::~Image() {
|
||||||
|
this->sampler.reset();
|
||||||
|
this->view.reset();
|
||||||
|
|
||||||
|
if (this->image) {
|
||||||
|
vmaDestroyImage(this->device.getAllocator(), this->image, this->allocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vk::ImageSubresourceRange Image::getSubresourceRange() const {
|
vk::ImageSubresourceRange Image::getSubresourceRange() const {
|
||||||
return vk::ImageSubresourceRange{this->aspectMask, 0, this->mipLevels, 0,
|
return vk::ImageSubresourceRange{this->aspectMask, 0, this->mipLevels, 0,
|
||||||
this->arrayLayers};
|
this->arrayLayers};
|
||||||
@@ -194,35 +218,26 @@ std::unique_ptr<Image> Image::Builder::build() {
|
|||||||
imageInfo.sharingMode = vk::SharingMode::eExclusive;
|
imageInfo.sharingMode = vk::SharingMode::eExclusive;
|
||||||
imageInfo.samples = this->samples;
|
imageInfo.samples = this->samples;
|
||||||
|
|
||||||
result->image = this->device.get()->createImageUnique(imageInfo);
|
this->device.createImageWithInfo(imageInfo, this->memoryProperties,
|
||||||
|
result->image, result->allocation);
|
||||||
vk::MemoryRequirements memoryRequirements =
|
|
||||||
this->device.get()->getImageMemoryRequirements(result->image.get());
|
|
||||||
|
|
||||||
vk::MemoryAllocateInfo allocInfo{};
|
|
||||||
allocInfo.allocationSize = memoryRequirements.size;
|
|
||||||
allocInfo.memoryTypeIndex = this->device.findMemoryType(
|
|
||||||
memoryRequirements.memoryTypeBits, this->memoryProperties);
|
|
||||||
|
|
||||||
result->memory = this->device.get()->allocateMemoryUnique(allocInfo);
|
|
||||||
this->device.get()->bindImageMemory(result->image.get(),
|
|
||||||
result->memory.get(), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->isExternalImage && this->initialData != nullptr) {
|
if (!this->isExternalImage && this->initialData != nullptr) {
|
||||||
|
VmaAllocator allocator = this->device.getAllocator();
|
||||||
|
|
||||||
vk::Buffer stagingBuffer;
|
vk::Buffer stagingBuffer;
|
||||||
vk::DeviceMemory stagingMemory;
|
VmaAllocation stagingAllocation;
|
||||||
this->device.createBuffer(this->initialDataSize,
|
this->device.createBuffer(this->initialDataSize,
|
||||||
vk::BufferUsageFlagBits::eTransferSrc,
|
vk::BufferUsageFlagBits::eTransferSrc,
|
||||||
vk::MemoryPropertyFlagBits::eHostVisible |
|
vk::MemoryPropertyFlagBits::eHostVisible |
|
||||||
vk::MemoryPropertyFlagBits::eHostCoherent,
|
vk::MemoryPropertyFlagBits::eHostCoherent,
|
||||||
stagingBuffer, stagingMemory);
|
stagingBuffer, stagingAllocation);
|
||||||
|
|
||||||
void* mapped =
|
void* mapped = nullptr;
|
||||||
this->device.get()->mapMemory(stagingMemory, 0, this->initialDataSize);
|
vmaMapMemory(allocator, stagingAllocation, &mapped);
|
||||||
memcpy(mapped, this->initialData,
|
memcpy(mapped, this->initialData,
|
||||||
static_cast<size_t>(this->initialDataSize));
|
static_cast<size_t>(this->initialDataSize));
|
||||||
this->device.get()->unmapMemory(stagingMemory);
|
vmaUnmapMemory(allocator, stagingAllocation);
|
||||||
|
|
||||||
vk::BufferImageCopy region{};
|
vk::BufferImageCopy region{};
|
||||||
region.bufferOffset = 0;
|
region.bufferOffset = 0;
|
||||||
@@ -247,8 +262,7 @@ std::unique_ptr<Image> Image::Builder::build() {
|
|||||||
}
|
}
|
||||||
this->device.endSingleTimeCommands(commandBuffer);
|
this->device.endSingleTimeCommands(commandBuffer);
|
||||||
|
|
||||||
this->device.get()->destroyBuffer(stagingBuffer);
|
vmaDestroyBuffer(allocator, stagingBuffer, stagingAllocation);
|
||||||
this->device.get()->freeMemory(stagingMemory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->createView) {
|
if (this->createView) {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vk_mem_alloc.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sophia/types.hpp>
|
#include <sophia/types.hpp>
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
@@ -16,11 +18,12 @@ class Image {
|
|||||||
|
|
||||||
Image(const Image&) = delete;
|
Image(const Image&) = delete;
|
||||||
Image& operator=(const Image&) = delete;
|
Image& operator=(const Image&) = delete;
|
||||||
Image(Image&&) = default;
|
Image(Image&& other) noexcept;
|
||||||
Image& operator=(Image&&) = delete;
|
Image& operator=(Image&&) = delete;
|
||||||
|
~Image();
|
||||||
|
|
||||||
vk::Image get() const {
|
vk::Image get() const {
|
||||||
return this->image ? this->image.get() : this->externalImage;
|
return this->image ? this->image : this->externalImage;
|
||||||
}
|
}
|
||||||
vk::ImageView getView() const { return this->view.get(); }
|
vk::ImageView getView() const { return this->view.get(); }
|
||||||
vk::Sampler getSampler() const { return this->sampler.get(); }
|
vk::Sampler getSampler() const { return this->sampler.get(); }
|
||||||
@@ -56,8 +59,8 @@ class Image {
|
|||||||
Device& device;
|
Device& device;
|
||||||
|
|
||||||
vk::Image externalImage;
|
vk::Image externalImage;
|
||||||
vk::UniqueImage image;
|
vk::Image image;
|
||||||
vk::UniqueDeviceMemory memory;
|
VmaAllocation allocation = VK_NULL_HANDLE;
|
||||||
vk::UniqueImageView view;
|
vk::UniqueImageView view;
|
||||||
vk::UniqueSampler sampler;
|
vk::UniqueSampler sampler;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#define VMA_IMPLEMENTATION
|
||||||
|
#include <vk_mem_alloc.h>
|
||||||
Vendored
+5
@@ -17,6 +17,11 @@ target_link_libraries(vulkan INTERFACE
|
|||||||
Vulkan::shaderc_combined
|
Vulkan::shaderc_combined
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 2. VMA (header-only, ships with the Vulkan SDK)
|
||||||
|
add_library(vma INTERFACE)
|
||||||
|
target_include_directories(vma INTERFACE ${Vulkan_INCLUDE_DIRS}/vma)
|
||||||
|
target_link_libraries(vma INTERFACE vulkan)
|
||||||
|
|
||||||
# 3. GLFW (static)
|
# 3. GLFW (static)
|
||||||
option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF)
|
option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF)
|
||||||
option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF)
|
option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF)
|
||||||
|
|||||||
Reference in New Issue
Block a user