Vulkan: Support non-pow2 buffer alignments

Bug: angleproject:2898
Change-Id: I7c8e548a1a449f48225516c37d830ecc201b064d
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1762496
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Shahbaz Youssefi 2019-08-20 14:55:43 -04:00 коммит произвёл Commit Bot
Родитель 1d83e1e8a1
Коммит c972435b15
3 изменённых файлов: 24 добавлений и 11 удалений

Просмотреть файл

@ -38,8 +38,9 @@ constexpr unsigned int kEmulatedAlphaValue = 1;
constexpr size_t kMinReadPixelsBufferSize = 128000;
// Alignment value to accommodate the largest known, for now, uncompressed Vulkan format
// VK_FORMAT_R64G64B64A64_SFLOAT
constexpr size_t kReadPixelsBufferAlignment = 32;
// VK_FORMAT_R64G64B64A64_SFLOAT, while supporting 3-component types such as
// VK_FORMAT_R16G16B16_SFLOAT.
constexpr size_t kReadPixelsBufferAlignment = 32 * 3;
// Clear values are only used when loadOp=Clear is set in clearWithRenderPassOp. When starting a
// new render pass, the clear value is set to an unlikely value (bright pink) to stand out better

Просмотреть файл

@ -330,7 +330,7 @@ angle::Result DynamicBuffer::allocate(ContextVk *contextVk,
VkDeviceSize *offsetOut,
bool *newBufferAllocatedOut)
{
size_t sizeToAllocate = roundUpPow2(sizeInBytes, mAlignment);
size_t sizeToAllocate = roundUp(sizeInBytes, mAlignment);
angle::base::CheckedNumeric<size_t> checkedNextWriteOffset = mNextAllocationOffset;
checkedNextWriteOffset += sizeToAllocate;
@ -546,17 +546,30 @@ void DynamicBuffer::updateAlignment(RendererVk *renderer, size_t alignment)
size_t atomSize =
static_cast<size_t>(renderer->getPhysicalDeviceProperties().limits.nonCoherentAtomSize);
// We need lcm(alignment, atomSize), we are assuming one divides the other so std::max() could
// be used instead.
ASSERT(alignment % atomSize == 0 || atomSize % alignment == 0);
alignment = std::max(alignment, atomSize);
ASSERT(gl::isPow2(alignment));
// We need lcm(alignment, atomSize). Usually, one divides the other so std::max() could be used
// instead. Only known case where this assumption breaks is for 3-component types with 16- or
// 32-bit channels, so that's special-cased to avoid a full-fledged lcm implementation.
if (gl::isPow2(alignment))
{
ASSERT(alignment % atomSize == 0 || atomSize % alignment == 0);
ASSERT(gl::isPow2(atomSize));
alignment = std::max(alignment, atomSize);
}
else
{
ASSERT(gl::isPow2(atomSize));
ASSERT(alignment % 3 == 0);
ASSERT(gl::isPow2(alignment / 3));
alignment = std::max(alignment / 3, atomSize) * 3;
}
// If alignment has changed, make sure the next allocation is done at an aligned offset.
if (alignment != mAlignment)
{
mNextAllocationOffset =
roundUpPow2(mNextAllocationOffset, static_cast<uint32_t>(alignment));
mNextAllocationOffset = roundUp(mNextAllocationOffset, static_cast<uint32_t>(alignment));
}
mAlignment = alignment;

Просмотреть файл

@ -93,7 +93,6 @@ class DynamicBuffer : angle::NonCopyable
BufferHelper *getCurrentBuffer() { return mBuffer; }
size_t getAlignment() { return mAlignment; }
void updateAlignment(RendererVk *renderer, size_t alignment);
// For testing only!