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 @@ ...@@ -18,7 +18,7 @@
namespace rx 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) ...@@ -32,6 +32,7 @@ void BufferVk::destroy(const gl::Context *context)
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
renderer->enqueueGarbageOrDeleteNow(*this, std::move(mBuffer)); renderer->enqueueGarbageOrDeleteNow(*this, std::move(mBuffer));
renderer->enqueueGarbageOrDeleteNow(*this, std::move(mBufferMemory));
} }
gl::Error BufferVk::setData(const gl::Context *context, gl::Error BufferVk::setData(const gl::Context *context,
...@@ -43,50 +44,27 @@ 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); ContextVk *contextVk = GetImplAs<ContextVk>(context);
auto device = contextVk->getDevice(); auto device = contextVk->getDevice();
// TODO(jmadill): Proper usage bit implementation. Likely will involve multiple backing buffers if (size > mCurrentRequiredSize)
// like in D3D11. {
VkBufferCreateInfo createInfo; // TODO(jmadill): Proper usage bit implementation. Likely will involve multiple backing
createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; // buffers like in D3D11.
createInfo.pNext = nullptr; VkBufferCreateInfo createInfo;
createInfo.flags = 0; createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
createInfo.size = size; createInfo.pNext = nullptr;
createInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; createInfo.flags = 0;
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; createInfo.size = size;
createInfo.queueFamilyIndexCount = 0; createInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
createInfo.pQueueFamilyIndices = nullptr; createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.queueFamilyIndexCount = 0;
vk::Buffer newBuffer; createInfo.pQueueFamilyIndices = nullptr;
ANGLE_TRY(newBuffer.init(device, createInfo));
vk::Buffer newBuffer;
// Find a compatible memory pool index. If the index doesn't change, we could cache it. ANGLE_TRY(newBuffer.init(device, createInfo));
// Not finding a valid memory pool means an out-of-spec driver, or internal error. mBuffer.retain(device, std::move(newBuffer));
// TODO(jmadill): More efficient memory allocation.
VkMemoryRequirements memoryRequirements; ANGLE_TRY(vk::AllocateBufferMemory(contextVk, size, &mBuffer, &mBufferMemory,
vkGetBufferMemoryRequirements(device, newBuffer.getHandle(), &memoryRequirements); &mCurrentRequiredSize));
}
// 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 (data) if (data)
{ {
...@@ -103,7 +81,7 @@ gl::Error BufferVk::setSubData(const gl::Context *context, ...@@ -103,7 +81,7 @@ gl::Error BufferVk::setSubData(const gl::Context *context,
size_t offset) size_t offset)
{ {
ASSERT(mBuffer.getHandle() != VK_NULL_HANDLE); 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(); VkDevice device = GetImplAs<ContextVk>(context)->getDevice();
...@@ -125,12 +103,12 @@ gl::Error BufferVk::copySubData(const gl::Context *context, ...@@ -125,12 +103,12 @@ gl::Error BufferVk::copySubData(const gl::Context *context,
gl::Error BufferVk::map(const gl::Context *context, GLenum access, void **mapPtr) gl::Error BufferVk::map(const gl::Context *context, GLenum access, void **mapPtr)
{ {
ASSERT(mBuffer.getHandle() != VK_NULL_HANDLE); 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(); VkDevice device = GetImplAs<ContextVk>(context)->getDevice();
ANGLE_TRY(mBuffer.getMemory().map(device, 0, mState.getSize(), 0, ANGLE_TRY(
reinterpret_cast<uint8_t **>(mapPtr))); mBufferMemory.map(device, 0, mState.getSize(), 0, reinterpret_cast<uint8_t **>(mapPtr)));
return gl::NoError(); return gl::NoError();
} }
...@@ -142,12 +120,11 @@ gl::Error BufferVk::mapRange(const gl::Context *context, ...@@ -142,12 +120,11 @@ gl::Error BufferVk::mapRange(const gl::Context *context,
void **mapPtr) void **mapPtr)
{ {
ASSERT(mBuffer.getHandle() != VK_NULL_HANDLE); 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(); VkDevice device = GetImplAs<ContextVk>(context)->getDevice();
ANGLE_TRY( ANGLE_TRY(mBufferMemory.map(device, offset, length, 0, reinterpret_cast<uint8_t **>(mapPtr)));
mBuffer.getMemory().map(device, offset, length, 0, reinterpret_cast<uint8_t **>(mapPtr)));
return gl::NoError(); return gl::NoError();
} }
...@@ -155,11 +132,11 @@ gl::Error BufferVk::mapRange(const gl::Context *context, ...@@ -155,11 +132,11 @@ gl::Error BufferVk::mapRange(const gl::Context *context,
gl::Error BufferVk::unmap(const gl::Context *context, GLboolean *result) gl::Error BufferVk::unmap(const gl::Context *context, GLboolean *result)
{ {
ASSERT(mBuffer.getHandle() != VK_NULL_HANDLE); 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(); VkDevice device = GetImplAs<ContextVk>(context)->getDevice();
mBuffer.getMemory().unmap(device); mBufferMemory.unmap(device);
return gl::NoError(); return gl::NoError();
} }
...@@ -179,7 +156,7 @@ gl::Error BufferVk::getIndexRange(const gl::Context *context, ...@@ -179,7 +156,7 @@ gl::Error BufferVk::getIndexRange(const gl::Context *context,
const gl::Type &typeInfo = gl::GetTypeInfo(type); const gl::Type &typeInfo = gl::GetTypeInfo(type);
uint8_t *mapPointer = nullptr; 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); *outRange = gl::ComputeIndexRange(type, mapPointer, count, primitiveRestartEnabled);
...@@ -189,12 +166,12 @@ gl::Error BufferVk::getIndexRange(const gl::Context *context, ...@@ -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) vk::Error BufferVk::setDataImpl(VkDevice device, const uint8_t *data, size_t size, size_t offset)
{ {
uint8_t *mapPointer = nullptr; 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); ASSERT(mapPointer);
memcpy(mapPointer, data, size); memcpy(mapPointer, data, size);
mBuffer.getMemory().unmap(device); mBufferMemory.unmap(device);
return vk::NoError(); return vk::NoError();
} }
......
...@@ -59,7 +59,8 @@ class BufferVk : public BufferImpl, public ResourceVk ...@@ -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::Error setDataImpl(VkDevice device, const uint8_t *data, size_t size, size_t offset);
vk::Buffer mBuffer; vk::Buffer mBuffer;
size_t mRequiredSize; vk::DeviceMemory mBufferMemory;
size_t mCurrentRequiredSize;
}; };
} // namespace rx } // namespace rx
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "renderervk_utils.h" #include "renderervk_utils.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h" #include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx namespace rx
...@@ -796,19 +797,11 @@ void Buffer::destroy(VkDevice device) ...@@ -796,19 +797,11 @@ void Buffer::destroy(VkDevice device)
{ {
if (valid()) if (valid())
{ {
mMemory.destroy(device);
vkDestroyBuffer(device, mHandle, nullptr); vkDestroyBuffer(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE; 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) Error Buffer::init(VkDevice device, const VkBufferCreateInfo &createInfo)
{ {
ASSERT(!valid()); ASSERT(!valid());
...@@ -816,10 +809,10 @@ Error Buffer::init(VkDevice device, const VkBufferCreateInfo &createInfo) ...@@ -816,10 +809,10 @@ Error Buffer::init(VkDevice device, const VkBufferCreateInfo &createInfo)
return NoError(); return NoError();
} }
Error Buffer::bindMemory(VkDevice device) Error Buffer::bindMemory(VkDevice device, const DeviceMemory &deviceMemory)
{ {
ASSERT(valid() && mMemory.valid()); ASSERT(valid() && deviceMemory.valid());
ANGLE_VK_TRY(vkBindBufferMemory(device, mHandle, mMemory.getHandle(), 0)); ANGLE_VK_TRY(vkBindBufferMemory(device, mHandle, deviceMemory.getHandle(), 0));
return NoError(); return NoError();
} }
...@@ -945,8 +938,6 @@ uint32_t MemoryProperties::findCompatibleMemoryIndex(uint32_t bitMask, uint32_t ...@@ -945,8 +938,6 @@ uint32_t MemoryProperties::findCompatibleMemoryIndex(uint32_t bitMask, uint32_t
return std::numeric_limits<uint32_t>::max(); return std::numeric_limits<uint32_t>::max();
} }
} // namespace vk
Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps, Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps,
const VkMemoryRequirements &requirements, const VkMemoryRequirements &requirements,
uint32_t propertyFlagMask) uint32_t propertyFlagMask)
...@@ -964,6 +955,47 @@ Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memory ...@@ -964,6 +955,47 @@ Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memory
return Optional<uint32_t>::Invalid(); 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 namespace gl_vk
{ {
VkPrimitiveTopology GetPrimitiveTopology(GLenum mode) VkPrimitiveTopology GetPrimitiveTopology(GLenum mode)
......
...@@ -29,6 +29,8 @@ struct Rectangle; ...@@ -29,6 +29,8 @@ struct Rectangle;
namespace rx namespace rx
{ {
class ContextVk;
const char *VulkanResultString(VkResult result); const char *VulkanResultString(VkResult result);
bool HasStandardValidationLayer(const std::vector<VkLayerProperties> &layerProps); bool HasStandardValidationLayer(const std::vector<VkLayerProperties> &layerProps);
...@@ -382,16 +384,10 @@ class Buffer final : public WrappedObject<Buffer, VkBuffer> ...@@ -382,16 +384,10 @@ class Buffer final : public WrappedObject<Buffer, VkBuffer>
public: public:
Buffer(); Buffer();
void destroy(VkDevice device); void destroy(VkDevice device);
void retain(VkDevice device, Buffer &&other); using WrappedObject::retain;
Error init(VkDevice device, const VkBufferCreateInfo &createInfo); Error init(VkDevice device, const VkBufferCreateInfo &createInfo);
Error bindMemory(VkDevice device); Error bindMemory(VkDevice device, const DeviceMemory &deviceMemory);
DeviceMemory &getMemory() { return mMemory; }
const DeviceMemory &getMemory() const { return mMemory; }
private:
DeviceMemory mMemory;
}; };
class ShaderModule final : public WrappedObject<ShaderModule, VkShaderModule> class ShaderModule final : public WrappedObject<ShaderModule, VkShaderModule>
...@@ -502,12 +498,18 @@ class GarbageObject final : public IGarbageObject ...@@ -502,12 +498,18 @@ class GarbageObject final : public IGarbageObject
T mObject; T mObject;
}; };
} // namespace vk
Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps, Optional<uint32_t> FindMemoryType(const VkPhysicalDeviceMemoryProperties &memoryProps,
const VkMemoryRequirements &requirements, const VkMemoryRequirements &requirements,
uint32_t propertyFlagMask); 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 namespace gl_vk
{ {
VkPrimitiveTopology GetPrimitiveTopology(GLenum mode); 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