Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/gpgmm/vk/FunctionsVk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ namespace gpgmm::vk {
GPGMM_DYNAMIC_GET_DEVICE_FUNC(AllocateMemory);
GPGMM_DYNAMIC_GET_DEVICE_FUNC(FreeMemory);
GPGMM_DYNAMIC_GET_DEVICE_FUNC(BindBufferMemory);
GPGMM_DYNAMIC_GET_DEVICE_FUNC(BindImageMemory);
GPGMM_DYNAMIC_GET_DEVICE_FUNC(GetBufferMemoryRequirements);
GPGMM_DYNAMIC_GET_DEVICE_FUNC(GetImageMemoryRequirements);
GPGMM_DYNAMIC_GET_DEVICE_FUNC(CreateBuffer);
GPGMM_DYNAMIC_GET_DEVICE_FUNC(DestroyBuffer);
GPGMM_DYNAMIC_GET_DEVICE_FUNC(CreateImage);
GPGMM_DYNAMIC_GET_DEVICE_FUNC(DestroyBuffer);
GPGMM_DYNAMIC_GET_DEVICE_FUNC(DestroyImage);
// TODO
}
Expand All @@ -60,11 +61,12 @@ namespace gpgmm::vk {
GPGMM_STATIC_GET_FUNC(AllocateMemory);
GPGMM_STATIC_GET_FUNC(FreeMemory);
GPGMM_STATIC_GET_FUNC(BindBufferMemory);
GPGMM_STATIC_GET_FUNC(BindImageMemory);
GPGMM_STATIC_GET_FUNC(GetBufferMemoryRequirements);
GPGMM_STATIC_GET_FUNC(GetImageMemoryRequirements);
GPGMM_STATIC_GET_FUNC(CreateBuffer);
GPGMM_STATIC_GET_FUNC(DestroyBuffer);
GPGMM_STATIC_GET_FUNC(CreateImage);
GPGMM_STATIC_GET_FUNC(DestroyBuffer);
GPGMM_STATIC_GET_FUNC(DestroyImage);
// TODO
}
Expand All @@ -75,11 +77,12 @@ namespace gpgmm::vk {
AllocateMemory = vkFunctions->AllocateMemory;
FreeMemory = vkFunctions->FreeMemory;
BindBufferMemory = vkFunctions->BindBufferMemory;
BindImageMemory = vkFunctions->BindImageMemory;
GetBufferMemoryRequirements = vkFunctions->GetBufferMemoryRequirements;
GetImageMemoryRequirements = vkFunctions->GetImageMemoryRequirements;
CreateBuffer = vkFunctions->CreateBuffer;
DestroyBuffer = vkFunctions->DestroyBuffer;
CreateImage = vkFunctions->CreateImage;
DestroyBuffer = vkFunctions->DestroyBuffer;
DestroyImage = vkFunctions->DestroyImage;
}

Expand All @@ -89,11 +92,12 @@ namespace gpgmm::vk {
ASSERT(vkFunctions.AllocateMemory != nullptr);
ASSERT(vkFunctions.FreeMemory != nullptr);
ASSERT(vkFunctions.BindBufferMemory != nullptr);
ASSERT(vkFunctions.BindImageMemory != nullptr);
ASSERT(vkFunctions.GetBufferMemoryRequirements != nullptr);
ASSERT(vkFunctions.GetImageMemoryRequirements != nullptr);
ASSERT(vkFunctions.CreateBuffer != nullptr);
ASSERT(vkFunctions.DestroyBuffer != nullptr);
ASSERT(vkFunctions.CreateImage != nullptr);
ASSERT(vkFunctions.DestroyBuffer != nullptr);
ASSERT(vkFunctions.DestroyImage != nullptr);
}

Expand Down
3 changes: 2 additions & 1 deletion src/gpgmm/vk/FunctionsVk.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,15 @@ namespace gpgmm::vk {
PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties = nullptr;
PFN_vkAllocateMemory AllocateMemory = nullptr;
PFN_vkBindBufferMemory BindBufferMemory = nullptr;
PFN_vkBindImageMemory BindImageMemory = nullptr;
PFN_vkFreeMemory FreeMemory = nullptr;
PFN_vkMapMemory MapMemory = nullptr;
PFN_vkGetBufferMemoryRequirements GetBufferMemoryRequirements = nullptr;
PFN_vkGetImageMemoryRequirements GetImageMemoryRequirements = nullptr;
PFN_vkCreateBuffer CreateBuffer = nullptr;
PFN_vkDestroyBuffer DestroyBuffer = nullptr;
PFN_vkCreateImage CreateImage = nullptr;
PFN_vkDestroyImage DestroyImage = nullptr;
PFN_vkDestroyBuffer DestroyBuffer = nullptr;
};

// ASSERTs if any Vulkan function is left unset.
Expand Down
84 changes: 83 additions & 1 deletion src/gpgmm/vk/ResourceAllocatorVk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,74 @@ namespace gpgmm::vk {
allocator->DeallocateMemory(allocation);
}

VkResult gpCreateImage(GpResourceAllocator allocator,
const VkImageCreateInfo* pImageCreateInfo,
VkImage* imageOut,
const GpResourceAllocationCreateInfo* pAllocationCreateInfo,
GpResourceAllocation* allocationOut) {
*allocationOut = VK_NULL_HANDLE;
*imageOut = VK_NULL_HANDLE;

if (allocator == VK_NULL_HANDLE) {
return VK_INCOMPLETE;
}

// Create the image.
VkImage image = VK_NULL_HANDLE;
ReturnIfFailed(
allocator->GetFunctions().CreateImage(allocator->GetDevice(), pImageCreateInfo,
/*allocationCallbacks*/ nullptr, &image));

VkMemoryRequirements requirements = {};
allocator->GetImageMemoryRequirements(image, &requirements);
if (requirements.size == 0) {
return VK_INCOMPLETE;
}

// Create memory for the image.
GpResourceAllocation allocation = VK_NULL_HANDLE;
VkResult result =
allocator->TryAllocateMemory(requirements, *pAllocationCreateInfo, &allocation);
if (result != VK_SUCCESS) {
allocator->GetFunctions().DestroyImage(allocator->GetDevice(), image,
/*allocationCallbacks*/ nullptr);
return result;
}

// Associate memory with the buffer.
result = allocator->GetFunctions().BindImageMemory(
allocator->GetDevice(), image, ToBackend(allocation->GetMemory())->GetDeviceMemory(),
allocation->GetOffset());
if (result != VK_SUCCESS) {
allocator->GetFunctions().DestroyImage(allocator->GetDevice(), image,
/*allocationCallbacks*/ nullptr);
allocator->DeallocateMemory(allocation);
return result;
}

*allocationOut = allocation;
*imageOut = image;

return VK_SUCCESS;
}

void gpDestroyImage(GpResourceAllocator allocator,
VkImage image,
GpResourceAllocation allocation) {
if (allocator == VK_NULL_HANDLE || image == VK_NULL_HANDLE) {
return;
}

allocator->GetFunctions().DestroyImage(allocator->GetDevice(), image,
/*allocationCallbacks*/ nullptr);

if (allocation == VK_NULL_HANDLE) {
return;
}

allocator->DeallocateMemory(allocation);
}

// GpResourceAllocation_T

GpResourceAllocation_T::GpResourceAllocation_T(const MemoryAllocation& allocation)
Expand Down Expand Up @@ -146,8 +214,17 @@ namespace gpgmm::vk {
caps.reset(ptr);
}

GpAllocatorCreateInfo newInfo = info;
newInfo.MemoryGrowthFactor = (newInfo.MemoryGrowthFactor >= 1.0)
? newInfo.MemoryGrowthFactor
: kDefaultMemoryGrowthFactor;

newInfo.MemoryFragmentationLimit = (newInfo.MemoryFragmentationLimit > 0)
? newInfo.MemoryFragmentationLimit
: kDefaultFragmentationLimit;

if (allocatorOut != VK_NULL_HANDLE) {
*allocatorOut = new GpResourceAllocator_T(info, vulkanFunctions, std::move(caps));
*allocatorOut = new GpResourceAllocator_T(newInfo, vulkanFunctions, std::move(caps));
}

return VK_SUCCESS;
Expand Down Expand Up @@ -223,6 +300,11 @@ namespace gpgmm::vk {
mVulkanFunctions.GetBufferMemoryRequirements(mDevice, buffer, requirementsOut);
}

void GpResourceAllocator_T::GetImageMemoryRequirements(VkImage image,
VkMemoryRequirements* requirementsOut) {
mVulkanFunctions.GetImageMemoryRequirements(mDevice, image, requirementsOut);
}

VkResult GpResourceAllocator_T::TryAllocateMemory(const VkMemoryRequirements& requirements,
const GpResourceAllocationCreateInfo& info,
GpResourceAllocation* allocationOut) {
Expand Down
27 changes: 27 additions & 0 deletions src/gpgmm/vk/ResourceAllocatorVk.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,32 @@ namespace gpgmm::vk {
VkBuffer buffer,
GpResourceAllocation allocation);

/** \brief Create a image allocation.

@param allocator A GpResourceAllocator used to create the image and allocation.
@param pImageCreateInfo A pointer to a VkImageCreateInfo that describes the image to create.
@param pImage A pointer to a VkImage that will be created using the allocation.
@param pAllocationCreateInfo A pointer to a GpResourceAllocationCreateInfo that describes the
allocation.
@param[out] allocationOut A pointer to GpResourceAllocation that represents the image
allocation.
*/
GPGMM_EXPORT VkResult gpCreateImage(GpResourceAllocator allocator,
const VkImageCreateInfo* pImageCreateInfo,
VkImage* pImage,
const GpResourceAllocationCreateInfo* pAllocationCreateInfo,
GpResourceAllocation* allocationOut);

/** \brief Destroy image allocation.

@param allocator A GpResourceAllocator used to create the image and allocation.
@param image A VkImage that was also created by the allocator.
@param allocation A GpResourceAllocation that was created by the allocator.
*/
GPGMM_EXPORT void gpDestroyImage(GpResourceAllocator allocator,
VkImage image,
GpResourceAllocation allocation);

struct GpResourceAllocation_T final : public MemoryAllocation {
GpResourceAllocation_T(const MemoryAllocation& allocation);
};
Expand All @@ -315,6 +341,7 @@ namespace gpgmm::vk {
void DeallocateMemory(GpResourceAllocation allocation);

void GetBufferMemoryRequirements(VkBuffer buffer, VkMemoryRequirements* requirementsOut);
void GetImageMemoryRequirements(VkImage image, VkMemoryRequirements* requirementsOut);

VkDevice GetDevice() const;
VulkanFunctions GetFunctions() const;
Expand Down
29 changes: 29 additions & 0 deletions src/tests/end2end/VKResourceAllocatorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,35 @@ TEST_F(VKResourceAllocatorTests, CreateBuffer) {
gpDestroyResourceAllocator(resourceAllocator);
}

TEST_F(VKResourceAllocatorTests, CreateImage) {
GpResourceAllocator resourceAllocator;
ASSERT_SUCCESS(gpCreateResourceAllocator(CreateBasicAllocatorInfo(), &resourceAllocator));

VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.extent.width = 1;
imageInfo.extent.height = 1;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.flags = 0;

GpResourceAllocationCreateInfo allocationInfo = {};

VkImage image;
GpResourceAllocation allocation;
ASSERT_SUCCESS(
gpCreateImage(resourceAllocator, &imageInfo, &image, &allocationInfo, &allocation));

gpDestroyImage(resourceAllocator, image, allocation);
gpDestroyResourceAllocator(resourceAllocator);
}

TEST_F(VKResourceAllocatorTests, CreateBufferManyDeallocateAtEnd) {
GpResourceAllocator resourceAllocator;
ASSERT_SUCCESS(gpCreateResourceAllocator(CreateBasicAllocatorInfo(), &resourceAllocator));
Expand Down