Commit 234be194 by Charlie Lao Committed by Commit Bot

Vulkan: Move mEmptyBuffer from program to ContextVk

And merge that with TheNUllBuffer as well so that you only have one dummy buffer per context. Bug: b/161391337 Change-Id: I75fddb5c48393876e745ff237e11d9c5672ae10e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2300707 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 0df0b79c
......@@ -748,6 +748,8 @@ void ContextVk::onDestroy(const gl::Context *context)
mDriverUniformsDescriptorPool.destroy(device);
mEmptyBuffer.release(mRenderer);
for (vk::DynamicBuffer &defaultBuffer : mDefaultAttribBuffers)
{
defaultBuffer.destroy(mRenderer);
......@@ -880,6 +882,22 @@ angle::Result ContextVk::initialize()
TRACE_EVENT_PHASE_BEGIN, eventName));
}
// Initialize an "empty" buffer for use with default uniform blocks where there are no uniforms,
// or atomic counter buffer array indices that are unused.
constexpr VkBufferUsageFlags kEmptyBufferUsage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
VkBufferCreateInfo emptyBufferInfo = {};
emptyBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
emptyBufferInfo.flags = 0;
emptyBufferInfo.size = 16;
emptyBufferInfo.usage = kEmptyBufferUsage;
emptyBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
emptyBufferInfo.queueFamilyIndexCount = 0;
emptyBufferInfo.pQueueFamilyIndices = nullptr;
constexpr VkMemoryPropertyFlags kMemoryType = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(mEmptyBuffer.init(this, emptyBufferInfo, kMemoryType));
return angle::Result::Continue;
}
......
......@@ -586,6 +586,8 @@ class ContextVk : public ContextImpl, public vk::Context
return mWriteInfos[oldSize];
}
vk::BufferHelper &getEmptyBuffer() { return mEmptyBuffer; }
private:
// Dirty bits.
enum DirtyBitType : size_t
......@@ -1061,6 +1063,12 @@ class ContextVk : public ContextImpl, public vk::Context
ShareGroupVk *mShareGroupVk;
// This is a special "empty" placeholder buffer for use when we just need a dummy buffer but not
// the data. Examples are shader that has no uniform or doesn't use all slots in the atomic
// counter buffer array, or places where there is no vertex buffer since Vulkan does not allow
// binding a null vertex buffer.
vk::BufferHelper mEmptyBuffer;
std::vector<std::string> mCommandBufferDiagnostics;
};
......
......@@ -166,16 +166,12 @@ ProgramExecutableVk::~ProgramExecutableVk() = default;
void ProgramExecutableVk::reset(ContextVk *contextVk)
{
RendererVk *renderer = contextVk->getRenderer();
for (auto &descriptorSetLayout : mDescriptorSetLayouts)
{
descriptorSetLayout.reset();
}
mPipelineLayout.reset();
mEmptyBuffer.release(renderer);
mDescriptorSets.clear();
mEmptyDescriptorSets.fill(VK_NULL_HANDLE);
mNumDefaultUniformDescriptors = 0;
......@@ -863,24 +859,7 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon
mDynamicBufferOffsets.resize(glExecutable.getLinkedShaderStageCount());
// Initialize an "empty" buffer for use with default uniform blocks where there are no uniforms,
// or atomic counter buffer array indices that are unused.
constexpr VkBufferUsageFlags kEmptyBufferUsage =
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
VkBufferCreateInfo emptyBufferInfo = {};
emptyBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
emptyBufferInfo.flags = 0;
emptyBufferInfo.size = 4;
emptyBufferInfo.usage = kEmptyBufferUsage;
emptyBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
emptyBufferInfo.queueFamilyIndexCount = 0;
emptyBufferInfo.pQueueFamilyIndices = nullptr;
constexpr VkMemoryPropertyFlags kMemoryType = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
angle::Result status = mEmptyBuffer.init(contextVk, emptyBufferInfo, kMemoryType);
return status;
return angle::Result::Continue;
}
void ProgramExecutableVk::updateDefaultUniformsDescriptorSet(
......@@ -906,9 +885,10 @@ void ProgramExecutableVk::updateDefaultUniformsDescriptorSet(
}
else
{
mEmptyBuffer.retain(&contextVk->getResourceUseList());
bufferInfo.buffer = mEmptyBuffer.getBuffer().getHandle();
mDescriptorBuffersCache.emplace_back(&mEmptyBuffer);
vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer();
emptyBuffer.retain(&contextVk->getResourceUseList());
bufferInfo.buffer = emptyBuffer.getBuffer().getHandle();
mDescriptorBuffersCache.emplace_back(&emptyBuffer);
}
bufferInfo.offset = 0;
......@@ -1078,14 +1058,15 @@ void ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet(
}
// Bind the empty buffer to every array slot that's unused.
mEmptyBuffer.retain(&contextVk->getResourceUseList());
vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer();
emptyBuffer.retain(&contextVk->getResourceUseList());
size_t count = (~writtenBindings).count();
VkDescriptorBufferInfo *bufferInfos = &contextVk->allocBufferInfos(count);
VkWriteDescriptorSet *writeInfos = &contextVk->allocWriteInfos(count);
size_t writeCount = 0;
for (size_t binding : ~writtenBindings)
{
bufferInfos[writeCount].buffer = mEmptyBuffer.getBuffer().getHandle();
bufferInfos[writeCount].buffer = emptyBuffer.getBuffer().getHandle();
bufferInfos[writeCount].offset = 0;
bufferInfos[writeCount].range = VK_WHOLE_SIZE;
......@@ -1265,7 +1246,7 @@ void ProgramExecutableVk::updateTransformFeedbackDescriptorSetImpl(
{
TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback);
transformFeedbackVk->initDescriptorSet(
contextVk, executable.getTransformFeedbackBufferCount(), &mEmptyBuffer,
contextVk, executable.getTransformFeedbackBufferCount(),
mDescriptorSets[kUniformsAndXfbDescriptorSetIndex]);
}
return;
......
......@@ -212,13 +212,6 @@ class ProgramExecutableVk
const gl::ShaderType shaderType,
ContextVk *contextVk);
// This is a special "empty" placeholder buffer for when a shader has no uniforms or doesn't
// use all slots in the atomic counter buffer array.
//
// It is necessary because we want to keep a compatible pipeline layout in all cases,
// and Vulkan does not tolerate having null handles in a descriptor set.
vk::BufferHelper mEmptyBuffer;
// Descriptor sets for uniform blocks and textures for this program.
std::vector<VkDescriptorSet> mDescriptorSets;
vk::DescriptorSetLayoutArray<VkDescriptorSet> mEmptyDescriptorSets;
......
......@@ -493,7 +493,6 @@ void RendererVk::onDestroy()
mPipelineCache.destroy(mDevice);
mSamplerCache.destroy(this);
mYuvConversionCache.destroy(this);
mTheNullBuffer.destroy(this);
mAllocator.destroy();
......@@ -821,16 +820,6 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
// Store the physical device memory properties so we can find the right memory pools.
mMemoryProperties.init(mPhysicalDevice);
// Must be initialized after the allocator and memory properties.
{
VkBufferCreateInfo bufferCreateInfo = {};
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferCreateInfo.size = 16;
bufferCreateInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
ANGLE_TRY(mTheNullBuffer.init(displayVk, kInvalidBufferSerial, bufferCreateInfo,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
}
if (!mGlslangInitialized)
{
GlslangInitialize();
......
......@@ -257,8 +257,6 @@ class RendererVk : angle::NonCopyable
}
void waitForWorkerThreadIdle() { mCommandProcessor.waitForWorkComplete(); }
vk::BufferHelper &getNullBuffer() { return mTheNullBuffer; }
bool getEnableValidationLayers() const { return mEnableValidationLayers; }
private:
......@@ -386,9 +384,6 @@ class RendererVk : angle::NonCopyable
SamplerCache mSamplerCache;
SamplerYcbcrConversionCache mYuvConversionCache;
vk::ActiveHandleCounter mActiveHandleCounts;
// Vulkan does not allow binding a null vertex buffer. We use a dummy as a placeholder.
vk::BufferHelper mTheNullBuffer;
};
} // namespace rx
......
......@@ -72,7 +72,7 @@ angle::Result TransformFeedbackVk::begin(const gl::Context *context,
else
{
// This can happen in error conditions.
vk::BufferHelper &nullBuffer = contextVk->getRenderer()->getNullBuffer();
vk::BufferHelper &nullBuffer = contextVk->getEmptyBuffer();
mBufferHelpers[bufferIndex] = &nullBuffer;
mBufferOffsets[bufferIndex] = 0;
mBufferSizes[bufferIndex] = nullBuffer.getSize();
......@@ -190,13 +190,13 @@ void TransformFeedbackVk::updateDescriptorSetLayout(
void TransformFeedbackVk::initDescriptorSet(ContextVk *contextVk,
size_t xfbBufferCount,
vk::BufferHelper *emptyBuffer,
VkDescriptorSet descSet) const
{
if (!contextVk->getFeatures().emulateTransformFeedback.enabled)
return;
VkDescriptorBufferInfo *descriptorBufferInfo = &contextVk->allocBufferInfos(xfbBufferCount);
vk::BufferHelper *emptyBuffer = &contextVk->getEmptyBuffer();
for (size_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
{
......
......@@ -49,7 +49,6 @@ class TransformFeedbackVk : public TransformFeedbackImpl
vk::DescriptorSetLayoutDesc *descSetLayoutOut) const;
void initDescriptorSet(ContextVk *contextVk,
size_t xfbBufferCount,
vk::BufferHelper *emptyBuffer,
VkDescriptorSet descSet) const;
void updateDescriptorSet(ContextVk *contextVk,
const gl::ProgramState &programState,
......
......@@ -121,14 +121,13 @@ VertexArrayVk::VertexArrayVk(ContextVk *contextVk, const gl::VertexArrayState &s
mLineLoopHelper(contextVk->getRenderer()),
mDirtyLineLoopTranslation(true)
{
RendererVk *renderer = contextVk->getRenderer();
vk::BufferHelper &nullBuffer = renderer->getNullBuffer();
RendererVk *renderer = contextVk->getRenderer();
vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer();
mCurrentArrayBufferHandles.fill(nullBuffer.getBuffer().getHandle());
mCurrentArrayBufferHandles.fill(emptyBuffer.getBuffer().getHandle());
mCurrentArrayBufferOffsets.fill(0);
mCurrentArrayBufferRelativeOffsets.fill(0);
mCurrentArrayBuffers.fill(&nullBuffer);
mCurrentArrayBuffers.fill(&emptyBuffer);
mDynamicVertexData.init(renderer, vk::kVertexBufferUsageFlags, vk::kVertexBufferAlignment,
kDynamicVertexDataSize, true);
......@@ -619,10 +618,10 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
{
if (bufferVk->getSize() == 0)
{
vk::BufferHelper &nullBuffer = renderer->getNullBuffer();
vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer();
mCurrentArrayBuffers[attribIndex] = &nullBuffer;
mCurrentArrayBufferHandles[attribIndex] = nullBuffer.getBuffer().getHandle();
mCurrentArrayBuffers[attribIndex] = &emptyBuffer;
mCurrentArrayBufferHandles[attribIndex] = emptyBuffer.getBuffer().getHandle();
mCurrentArrayBufferOffsets[attribIndex] = 0;
stride = 0;
}
......@@ -643,9 +642,9 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
}
else
{
vk::BufferHelper &nullBuffer = renderer->getNullBuffer();
mCurrentArrayBuffers[attribIndex] = &nullBuffer;
mCurrentArrayBufferHandles[attribIndex] = nullBuffer.getBuffer().getHandle();
vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer();
mCurrentArrayBuffers[attribIndex] = &emptyBuffer;
mCurrentArrayBufferHandles[attribIndex] = emptyBuffer.getBuffer().getHandle();
mCurrentArrayBufferOffsets[attribIndex] = 0;
// Client side buffer will be transfered to a tightly packed buffer later
stride = vertexFormat.actualBufferFormat().pixelBytes;
......@@ -676,9 +675,9 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
contextVk->invalidateDefaultAttribute(attribIndex);
// These will be filled out by the ContextVk.
vk::BufferHelper &nullBuffer = renderer->getNullBuffer();
mCurrentArrayBuffers[attribIndex] = &nullBuffer;
mCurrentArrayBufferHandles[attribIndex] = nullBuffer.getBuffer().getHandle();
vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer();
mCurrentArrayBuffers[attribIndex] = &emptyBuffer;
mCurrentArrayBufferHandles[attribIndex] = emptyBuffer.getBuffer().getHandle();
mCurrentArrayBufferOffsets[attribIndex] = 0;
mCurrentArrayBufferStrides[attribIndex] = 0;
mCurrentArrayBufferRelativeOffsets[attribIndex] = 0;
......
......@@ -2189,14 +2189,13 @@ BufferHelper::BufferHelper()
BufferHelper::~BufferHelper() = default;
angle::Result BufferHelper::init(Context *context,
BufferSerial serial,
angle::Result BufferHelper::init(ContextVk *contextVk,
const VkBufferCreateInfo &requestedCreateInfo,
VkMemoryPropertyFlags memoryPropertyFlags)
{
RendererVk *renderer = context->getRenderer();
RendererVk *renderer = contextVk->getRenderer();
mSerial = serial;
mSerial = contextVk->generateBufferSerial();
mSize = requestedCreateInfo.size;
VkBufferCreateInfo modifiedCreateInfo;
......@@ -2221,18 +2220,18 @@ angle::Result BufferHelper::init(Context *context,
// Check that the allocation is not too large.
uint32_t memoryTypeIndex = 0;
ANGLE_VK_TRY(context, allocator.findMemoryTypeIndexForBufferInfo(
*createInfo, requiredFlags, preferredFlags, persistentlyMapped,
&memoryTypeIndex));
ANGLE_VK_TRY(contextVk, allocator.findMemoryTypeIndexForBufferInfo(
*createInfo, requiredFlags, preferredFlags, persistentlyMapped,
&memoryTypeIndex));
VkDeviceSize heapSize =
renderer->getMemoryProperties().getHeapSizeForMemoryType(memoryTypeIndex);
ANGLE_VK_CHECK(context, createInfo->size <= heapSize, VK_ERROR_OUT_OF_DEVICE_MEMORY);
ANGLE_VK_CHECK(contextVk, createInfo->size <= heapSize, VK_ERROR_OUT_OF_DEVICE_MEMORY);
ANGLE_VK_TRY(context, allocator.createBuffer(*createInfo, requiredFlags, preferredFlags,
persistentlyMapped, &memoryTypeIndex, &mBuffer,
&mAllocation));
ANGLE_VK_TRY(contextVk, allocator.createBuffer(*createInfo, requiredFlags, preferredFlags,
persistentlyMapped, &memoryTypeIndex, &mBuffer,
&mAllocation));
allocator.getMemoryTypeProperties(memoryTypeIndex, &mMemoryPropertyFlags);
mCurrentQueueFamilyIndex = renderer->getQueueFamilyIndex();
......@@ -2245,14 +2244,14 @@ angle::Result BufferHelper::init(Context *context,
if ((mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0 &&
(requestedCreateInfo.usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT) != 0)
{
ANGLE_TRY(initializeNonZeroMemory(context, createInfo->size));
ANGLE_TRY(initializeNonZeroMemory(contextVk, createInfo->size));
}
else if ((mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
{
// Can map the memory.
// Pick an arbitrary value to initialize non-zero memory for sanitization.
constexpr int kNonZeroInitValue = 55;
ANGLE_TRY(InitMappableAllocation(context, allocator, &mAllocation, mSize,
ANGLE_TRY(InitMappableAllocation(contextVk, allocator, &mAllocation, mSize,
kNonZeroInitValue, mMemoryPropertyFlags));
}
}
......@@ -2260,14 +2259,6 @@ angle::Result BufferHelper::init(Context *context,
return angle::Result::Continue;
}
angle::Result BufferHelper::init(ContextVk *contextVk,
const VkBufferCreateInfo &createInfo,
VkMemoryPropertyFlags memoryPropertyFlags)
{
BufferSerial serial = contextVk->generateBufferSerial();
return init(contextVk, serial, createInfo, memoryPropertyFlags);
}
angle::Result BufferHelper::initializeNonZeroMemory(Context *context, VkDeviceSize size)
{
// Staging buffer memory is non-zero-initialized in 'init'.
......
......@@ -700,10 +700,6 @@ class BufferHelper final : public Resource
angle::Result init(ContextVk *contextVk,
const VkBufferCreateInfo &createInfo,
VkMemoryPropertyFlags memoryPropertyFlags);
angle::Result init(Context *context,
BufferSerial serial,
const VkBufferCreateInfo &createInfo,
VkMemoryPropertyFlags memoryPropertyFlags);
void destroy(RendererVk *renderer);
void release(RendererVk *renderer);
......
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