Commit ba2eaea2 by Jamie Madill Committed by Commit Bot

Refactor vk::Buffer memory allocation.

Add the code that finds the right memory information into a shared location. This will allow it to be reused with other points in the code. BUG=angleproject:2167 Change-Id: I72d0522e134666d0a00921cb5ef6bc093473afdf Reviewed-on: https://chromium-review.googlesource.com/717189 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 5ad26408
......@@ -18,7 +18,7 @@
namespace rx
{
BufferVk::BufferVk(const gl::BufferState &state) : BufferImpl(state), mRequiredSize(0)
BufferVk::BufferVk(const gl::BufferState &state) : BufferImpl(state), mCurrentRequiredSize(0)
{
}
......@@ -32,6 +32,7 @@ void BufferVk::destroy(const gl::Context *context)
RendererVk *renderer = contextVk->getRenderer();
renderer->enqueueGarbageOrDeleteNow(*this, std::move(mBuffer));
renderer->enqueueGarbageOrDeleteNow(*this, std::move(mBufferMemory));
}
gl::Error BufferVk::setData(const gl::Context *context,
......@@ -43,50 +44,27 @@ gl::Error BufferVk::setData(const gl::Context *context,
ContextVk *contextVk = GetImplAs<ContextVk>(context);
auto device = contextVk->getDevice();
// TODO(jmadill): Proper usage bit implementation. Likely will involve multiple backing buffers
// like in D3D11.
VkBufferCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.size = size;
createInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.queueFamilyIndexCount = 0;
createInfo.pQueueFamilyIndices = nullptr;
vk::Buffer newBuffer;
ANGLE_TRY(newBuffer.init(device, createInfo));
// Find a compatible memory pool index. If the index doesn't change, we could cache it.
// Not finding a valid memory pool means an out-of-spec driver, or internal error.
// TODO(jmadill): More efficient memory allocation.
VkMemoryRequirements memoryRequirements;
vkGetBufferMemoryRequirements(device, newBuffer.getHandle(), &memoryRequirements);
// The requirements size is not always equal to the specified API size.
ASSERT(memoryRequirements.size >= size);
mRequiredSize = static_cast<size_t>(memoryRequirements.size);
VkPhysicalDeviceMemoryProperties memoryProperties;
vkGetPhysicalDeviceMemoryProperties(contextVk->getRenderer()->getPhysicalDevice(),
&memoryProperties);
auto memoryTypeIndex =
FindMemoryType(memoryProperties, memoryRequirements,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
ANGLE_VK_CHECK(memoryTypeIndex.valid(), VK_ERROR_INCOMPATIBLE_DRIVER);
VkMemoryAllocateInfo allocInfo;
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.pNext = nullptr;
allocInfo.memoryTypeIndex = memoryTypeIndex.value();
allocInfo.allocationSize = memoryRequirements.size;
ANGLE_TRY(newBuffer.getMemory().allocate(device, allocInfo));
ANGLE_TRY(newBuffer.bindMemory(device));
mBuffer.retain(device, std::move(newBuffer));
if (size > mCurrentRequiredSize)
{
// TODO(jmadill): Proper usage bit implementation. Likely will involve multiple backing
// buffers like in D3D11.
VkBufferCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.size = size;
createInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.queueFamilyIndexCount = 0;
createInfo.pQueueFamilyIndices = nullptr;
vk::Buffer newBuffer;
ANGLE_TRY(newBuffer.init(device, createInfo));
mBuffer.retain(device, std::move(newBuffer));
ANGLE_TRY(vk::AllocateBufferMemory(contextVk, size, &mBuffer, &mBufferMemory,
&mCurrentRequiredSize));
}
if (data)
{
......@@ -103,7 +81,7 @@ gl::Error BufferVk::setSubData(const gl::Context *context,
size_t offset)
{
ASSERT(mBuffer.getHandle() != VK_NULL_HANDLE);
ASSERT(mBuffer.getMemory().getHandle() != VK_NULL_HANDLE);
ASSERT(mBufferMemory.getHandle() != VK_NULL_HANDLE);
VkDevice device = GetImplAs<ContextVk>(context)->getDevice();
......@@ -125,12 +103,12 @@ gl::Error BufferVk::copySubData(const gl::Context *context,
gl::Error BufferVk::map(const gl::Context *context, GLenum access, void **mapPtr)
{
ASSERT(mBuffer.getHandle() != VK_NULL_HANDLE);
ASSERT(mBuffer.getMemory().getHandle() != VK_NULL_HANDLE);
ASSERT(mBufferMemory.getHandle() != VK_NULL_HANDLE);
VkDevice device = GetImplAs<ContextVk>(context)->getDevice();
ANGLE_TRY(mBuffer.getMemory().map(device, 0, mState.getSize(), 0,
reinterpret_cast<uint8_t **>(mapPtr)));
ANGLE_TRY(
mBufferMemory.map(device, 0, mState.getSize(), 0, reinterpret_cast<uint8_t **>(mapPtr)));
return gl::NoError();
}
......@@ -142,12 +120,11 @@ gl::Error BufferVk::mapRange(const gl::Context *context,
void **mapPtr)
{
ASSERT(mBuffer.getHandle() != VK_NULL_HANDLE);
ASSERT(mBuffer.getMemory().getHandle() != VK_NULL_HANDLE);
ASSERT(mBufferMemory.getHandle() != VK_NULL_HANDLE);
VkDevice device = GetImplAs<ContextVk>(context)->getDevice();
ANGLE_TRY(
mBuffer.getMemory().map(device, offset, length, 0, reinterpret_cast<uint8_t **>(mapPtr)));
ANGLE_TRY(mBufferMemory.map(device, offset, length, 0, reinterpret_cast<uint8_t **>(mapPtr)));
return gl::NoError();
}
......@@ -155,11 +132,11 @@ gl::Error BufferVk::mapRange(const gl::Context *context,
gl::Error BufferVk::unmap(const gl::Context *context, GLboolean *result)
{
ASSERT(mBuffer.getHandle() != VK_NULL_HANDLE);
ASSERT(mBuffer.getMemory().getHandle() != VK_NULL_HANDLE);
ASSERT(mBufferMemory.getHandle() != VK_NULL_HANDLE);
VkDevice device = GetImplAs<ContextVk>(context)->getDevice();
mBuffer.getMemory().unmap(device);
mBufferMemory.unmap(device);
return gl::NoError();
}
......@@ -179,7 +156,7 @@ gl::Error BufferVk::getIndexRange(const gl::Context *context,
const gl::Type &typeInfo = gl::GetTypeInfo(type);
uint8_t *mapPointer = nullptr;
ANGLE_TRY(mBuffer.getMemory().map(device, offset, typeInfo.bytes * count, 0, &mapPointer));
ANGLE_TRY(mBufferMemory.map(device, offset, typeInfo.bytes * count, 0, &mapPointer));
*outRange = gl::ComputeIndexRange(type, mapPointer, count, primitiveRestartEnabled);
......@@ -189,12 +166,12 @@ gl::Error BufferVk::getIndexRange(const gl::Context *context,
vk::Error BufferVk::setDataImpl(VkDevice device, const uint8_t *data, size_t size, size_t offset)
{
uint8_t *mapPointer = nullptr;
ANGLE_TRY(mBuffer.getMemory().map(device, offset, size, 0, &mapPointer));
ANGLE_TRY(mBufferMemory.map(device, offset, size, 0, &mapPointer));
ASSERT(mapPointer);
memcpy(mapPointer, data, size);
mBuffer.getMemory().unmap(device);
mBufferMemory.unmap(device);
return vk::NoError();
}
......
......@@ -59,7 +59,8 @@ class BufferVk : public BufferImpl, public ResourceVk
vk::Error setDataImpl(VkDevice device, const uint8_t *data, size_t size, size_t offset);
vk::Buffer mBuffer;
size_t mRequiredSize;
vk::DeviceMemory mBufferMemory;
size_t mCurrentRequiredSize;
};
} // namespace rx
......
......@@ -9,6 +9,7 @@
#include "renderervk_utils.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx
......@@ -796,19 +797,11 @@ void Buffer::destroy(VkDevice device)
{
if (valid())
{
mMemory.destroy(device);
vkDestroyBuffer(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
void Buffer::retain(VkDevice device, Buffer &&other)
{
WrappedObject::retain(device, std::move(other));
mMemory.retain(device, std::move(other.mMemory));
}
Error Buffer::init(VkDevice device, const VkBufferCreateInfo &createInfo)
{
ASSERT(!valid());
......@@ -816,10 +809,10 @@ Error Buffer::init(VkDevice device, const VkBufferCreateInfo &createInfo)
return NoError();
}
Error Buffer::bindMemory(VkDevice device)
Error Buffer::bindMemory(VkDevice device, const DeviceMemory &deviceMemory)
{
ASSERT(valid() && mMemory.valid());
ANGLE_VK_TRY(vkBindBufferMemory(device, mHandle, mMemory.getHandle(), 0));
ASSERT(valid() && deviceMemory.valid());
ANGLE_VK_TRY(vkBindBufferMemory(device, mHandle, deviceMemory.getHandle(), 0));
return NoError();
}
......@@ -945,8 +938,6 @@ uint32_t MemoryProperties::findCompatibleMemoryIndex(uint32_t bitMask, uint32_t
return std::numeric_limits<uint32_t>::max();
}
} // namespace vk
Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps,
const VkMemoryRequirements &requirements,
uint32_t propertyFlagMask)
......@@ -964,6 +955,47 @@ Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memory
return Optional<uint32_t>::Invalid();
}
gl::Error AllocateBufferMemory(ContextVk *contextVk,
size_t size,
vk::Buffer *buffer,
vk::DeviceMemory *deviceMemoryOut,
size_t *requiredSizeOut)
{
VkDevice device = contextVk->getDevice();
// Find a compatible memory pool index. If the index doesn't change, we could cache it.
// Not finding a valid memory pool means an out-of-spec driver, or internal error.
// TODO(jmadill): More efficient memory allocation.
VkMemoryRequirements memoryRequirements;
vkGetBufferMemoryRequirements(device, buffer->getHandle(), &memoryRequirements);
// The requirements size is not always equal to the specified API size.
ASSERT(memoryRequirements.size >= size);
*requiredSizeOut = static_cast<size_t>(memoryRequirements.size);
VkPhysicalDeviceMemoryProperties memoryProperties;
vkGetPhysicalDeviceMemoryProperties(contextVk->getRenderer()->getPhysicalDevice(),
&memoryProperties);
auto memoryTypeIndex =
FindMemoryType(memoryProperties, memoryRequirements,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
ANGLE_VK_CHECK(memoryTypeIndex.valid(), VK_ERROR_INCOMPATIBLE_DRIVER);
VkMemoryAllocateInfo allocInfo;
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.pNext = nullptr;
allocInfo.memoryTypeIndex = memoryTypeIndex.value();
allocInfo.allocationSize = memoryRequirements.size;
ANGLE_TRY(deviceMemoryOut->allocate(device, allocInfo));
ANGLE_TRY(buffer->bindMemory(device, *deviceMemoryOut));
return gl::NoError();
}
} // namespace vk
namespace gl_vk
{
VkPrimitiveTopology GetPrimitiveTopology(GLenum mode)
......
......@@ -29,6 +29,8 @@ struct Rectangle;
namespace rx
{
class ContextVk;
const char *VulkanResultString(VkResult result);
bool HasStandardValidationLayer(const std::vector<VkLayerProperties> &layerProps);
......@@ -382,16 +384,10 @@ class Buffer final : public WrappedObject<Buffer, VkBuffer>
public:
Buffer();
void destroy(VkDevice device);
void retain(VkDevice device, Buffer &&other);
using WrappedObject::retain;
Error init(VkDevice device, const VkBufferCreateInfo &createInfo);
Error bindMemory(VkDevice device);
DeviceMemory &getMemory() { return mMemory; }
const DeviceMemory &getMemory() const { return mMemory; }
private:
DeviceMemory mMemory;
Error bindMemory(VkDevice device, const DeviceMemory &deviceMemory);
};
class ShaderModule final : public WrappedObject<ShaderModule, VkShaderModule>
......@@ -502,12 +498,18 @@ class GarbageObject final : public IGarbageObject
T mObject;
};
} // namespace vk
Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps,
const VkMemoryRequirements &requirements,
uint32_t propertyFlagMask);
gl::Error AllocateBufferMemory(ContextVk *contextVk,
size_t size,
vk::Buffer *buffer,
vk::DeviceMemory *deviceMemoryOut,
size_t *requiredSizeOut);
} // namespace vk
namespace gl_vk
{
VkPrimitiveTopology GetPrimitiveTopology(GLenum mode);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment