Commit 8270ebbd by Jamie Madill Committed by Commit Bot

Vulkan: Refactor and clean up XFB code.

This is a refactor-only change mostly. It makes the classes work more similarly to how the other classes in the Vk back-end work. Also removes some redundant code. Moves the buffer caching into begin for a more dirty-bits like approach. Bug: angleproject:4622 Change-Id: I34ac13e1d05b48e3267937c760d195493a76ed02 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2191172 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent ab8d424a
......@@ -1435,29 +1435,27 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
ASSERT(executable);
if (executable->hasTransformFeedbackOutput() && mState.isTransformFeedbackActive())
if (!executable->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActive())
{
size_t bufferCount = executable->getTransformFeedbackBufferCount(mState);
const std::vector<gl::OffsetBindingPointer<gl::Buffer>> &xfbBuffers =
mState.getCurrentTransformFeedback()->getIndexedBuffers();
for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
{
const gl::OffsetBindingPointer<gl::Buffer> &xfbBuffer = xfbBuffers[bufferIndex];
gl::Buffer *buffer = xfbBuffer.get();
ASSERT(buffer != nullptr);
BufferVk *bufferVk = vk::GetImpl(buffer);
vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
return angle::Result::Continue;
}
mRenderPassCommands.bufferWrite(&mResourceUseList, VK_ACCESS_SHADER_WRITE_BIT,
vk::PipelineStage::VertexShader, &bufferHelper);
}
TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
size_t bufferCount = executable->getTransformFeedbackBufferCount(mState);
const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &bufferHelpers =
transformFeedbackVk->getBufferHelpers();
// TODO(http://anglebug.com/3570): Need to update to handle Program Pipelines
ANGLE_TRY(mProgram->getExecutable().updateTransformFeedbackDescriptorSet(
mProgram->getState(), mProgram->getDefaultUniformBlocks(), this));
for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
{
vk::BufferHelper *bufferHelper = bufferHelpers[bufferIndex];
ASSERT(bufferHelper);
mRenderPassCommands.bufferWrite(&mResourceUseList, VK_ACCESS_SHADER_WRITE_BIT,
vk::PipelineStage::VertexShader, bufferHelper);
}
return angle::Result::Continue;
// TODO(http://anglebug.com/3570): Need to update to handle Program Pipelines
return mProgram->getExecutable().updateTransformFeedbackDescriptorSet(
mProgram->getState(), mProgram->getDefaultUniformBlocks(), this);
}
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension(
......@@ -1470,36 +1468,31 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension(
if (!executable->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActive())
return angle::Result::Continue;
size_t bufferIndex = 0;
TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
size_t bufferCount = executable->getTransformFeedbackBufferCount(mState);
size_t bufferCount = executable->getTransformFeedbackBufferCount(mState);
gl::TransformFeedbackBuffersArray<VkBuffer> bufferHandles;
const std::vector<gl::OffsetBindingPointer<gl::Buffer>> &xfbBuffers =
mState.getCurrentTransformFeedback()->getIndexedBuffers();
const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &bufferHelpers =
transformFeedbackVk->getBufferHelpers();
for (bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
{
const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = xfbBuffers[bufferIndex];
gl::Buffer *buffer = bufferBinding.get();
ASSERT(buffer != nullptr);
BufferVk *bufferVk = vk::GetImpl(buffer);
vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
bufferHandles[bufferIndex] = bufferHelper.getBuffer().getHandle();
vk::BufferHelper *bufferHelper = bufferHelpers[bufferIndex];
ASSERT(bufferHelper);
mRenderPassCommands.bufferWrite(&mResourceUseList,
VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT,
vk::PipelineStage::TransformFeedback, &bufferHelper);
vk::PipelineStage::TransformFeedback, bufferHelper);
}
const TransformFeedbackBufferRange &xfbBufferRangeExtension =
transformFeedbackVk->getTransformFeedbackBufferRange();
const gl::TransformFeedbackBuffersArray<VkBuffer> &bufferHandles =
transformFeedbackVk->getBufferHandles();
const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferOffsets =
transformFeedbackVk->getBufferOffsets();
const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferSizes =
transformFeedbackVk->getBufferSizes();
commandBuffer->bindTransformFeedbackBuffers(
static_cast<uint32_t>(bufferCount), bufferHandles.data(),
xfbBufferRangeExtension.offsets.data(), xfbBufferRangeExtension.sizes.data());
commandBuffer->bindTransformFeedbackBuffers(static_cast<uint32_t>(bufferCount),
bufferHandles.data(), bufferOffsets.data(),
bufferSizes.data());
return angle::Result::Continue;
}
......@@ -1511,7 +1504,9 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Con
ASSERT(executable);
if (!executable->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActiveUnpaused())
{
return angle::Result::Continue;
}
TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
......@@ -1520,12 +1515,10 @@ angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Con
const gl::TransformFeedbackBuffersArray<VkBuffer> &counterBufferHandles =
transformFeedbackVk->getCounterBufferHandles();
bool rebindBuffer = transformFeedbackVk->getTransformFeedbackBufferRebindState();
bool rebindBuffers = transformFeedbackVk->getAndResetBufferRebindState();
mRenderPassCommands.beginTransformFeedback(bufferCount, counterBufferHandles.data(),
rebindBuffer);
transformFeedbackVk->unsetTransformFeedbackBufferRebindState();
rebindBuffers);
return angle::Result::Continue;
}
......@@ -3191,16 +3184,11 @@ void ContextVk::invalidateCurrentTransformFeedbackBuffers()
}
}
void ContextVk::invalidateCurrentTransformFeedbackState()
{
mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_STATE);
}
void ContextVk::onTransformFeedbackStateChanged()
{
if (getFeatures().supportsTransformFeedbackExtension.enabled)
{
invalidateCurrentTransformFeedbackState();
mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_STATE);
}
else if (getFeatures().emulateTransformFeedback.enabled)
{
......
......@@ -327,7 +327,6 @@ class ContextVk : public ContextImpl, public vk::Context
void onHostVisibleBufferWrite() { mIsAnyHostVisibleBufferWritten = true; }
void invalidateCurrentTransformFeedbackBuffers();
void invalidateCurrentTransformFeedbackState();
void onTransformFeedbackStateChanged();
// When UtilsVk issues draw or dispatch calls, it binds descriptor sets that the context is not
......
......@@ -24,10 +24,15 @@ namespace rx
{
TransformFeedbackVk::TransformFeedbackVk(const gl::TransformFeedbackState &state)
: TransformFeedbackImpl(state), mRebindTransformFeedbackBuffer(false)
{
mCounterBufferHandles.fill(0);
}
: TransformFeedbackImpl(state),
mRebindTransformFeedbackBuffer(false),
mBufferHelpers{},
mBufferHandles{},
mBufferOffsets{},
mBufferSizes{},
mAlignedBufferOffsets{},
mCounterBufferHandles{}
{}
TransformFeedbackVk::~TransformFeedbackVk() {}
......@@ -35,7 +40,7 @@ void TransformFeedbackVk::onDestroy(const gl::Context *context)
{
RendererVk *rendererVk = vk::GetImpl(context)->getRenderer();
for (vk::BufferHelper &bufferHelper : mCounterBuffer)
for (vk::BufferHelper &bufferHelper : mCounterBufferHelpers)
{
bufferHelper.release(rendererVk);
}
......@@ -48,6 +53,53 @@ angle::Result TransformFeedbackVk::begin(const gl::Context *context,
contextVk->onTransformFeedbackStateChanged();
const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
ASSERT(executable);
size_t xfbBufferCount = executable->getTransformFeedbackBufferCount(contextVk->getState());
for (size_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
{
const gl::OffsetBindingPointer<gl::Buffer> &binding = mState.getIndexedBuffer(bufferIndex);
ASSERT(binding.get());
mBufferHelpers[bufferIndex] = &vk::GetImpl(binding.get())->getBuffer();
mBufferHandles[bufferIndex] = mBufferHelpers[bufferIndex]->getBuffer().getHandle();
mBufferOffsets[bufferIndex] = binding.getOffset();
mBufferSizes[bufferIndex] = gl::GetBoundBufferAvailableSize(binding);
if (contextVk->getFeatures().supportsTransformFeedbackExtension.enabled)
{
if (mCounterBufferHandles[bufferIndex] == VK_NULL_HANDLE)
{
VkBufferCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
createInfo.size = 16;
createInfo.usage = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT;
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
vk::BufferHelper &bufferHelper = mCounterBufferHelpers[bufferIndex];
ANGLE_TRY(
bufferHelper.init(contextVk, createInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
mCounterBufferHandles[bufferIndex] = bufferHelper.getBuffer().getHandle();
}
}
else
{
ASSERT(contextVk->getFeatures().emulateTransformFeedback.enabled);
RendererVk *rendererVk = contextVk->getRenderer();
const VkDeviceSize offsetAlignment =
rendererVk->getPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
// Make sure there's no possible under/overflow with binding size.
static_assert(sizeof(VkDeviceSize) >= sizeof(binding.getSize()),
"VkDeviceSize too small");
// Set the offset as close as possible to the requested offset while remaining aligned.
mAlignedBufferOffsets[bufferIndex] =
(mBufferOffsets[bufferIndex] / offsetAlignment) * offsetAlignment;
}
}
if (contextVk->getFeatures().supportsTransformFeedbackExtension.enabled)
{
mRebindTransformFeedbackBuffer = true;
......@@ -113,50 +165,9 @@ angle::Result TransformFeedbackVk::bindIndexedBuffer(
{
ContextVk *contextVk = vk::GetImpl(context);
if (contextVk->getFeatures().supportsTransformFeedbackExtension.enabled)
{
// Save xfb buffer state
mTransformFeedbackBufferRange.offsets[index] = binding.getOffset();
mTransformFeedbackBufferRange.sizes[index] =
(binding.getSize()) ? binding.getSize() : VK_WHOLE_SIZE;
mRebindTransformFeedbackBuffer = true;
if (mCounterBufferHandles[index] == 0)
{
VkBufferCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
createInfo.size = 16;
createInfo.usage = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT;
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
ANGLE_TRY(mCounterBuffer[index].init(contextVk, createInfo,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
// Make sure the transform feedback buffers are bound to the program descriptor sets.
contextVk->invalidateCurrentTransformFeedbackBuffers();
mCounterBufferHandles[index] = mCounterBuffer[index].getBuffer().getHandle();
}
// Set dirty bit for update xfb buffer
contextVk->invalidateCurrentTransformFeedbackBuffers();
}
else if (contextVk->getFeatures().emulateTransformFeedback.enabled)
{
RendererVk *rendererVk = vk::GetImpl(context)->getRenderer();
const VkDeviceSize offsetAlignment =
rendererVk->getPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
// Make sure there's no possible under/overflow with binding size.
static_assert(sizeof(VkDeviceSize) >= sizeof(binding.getSize()), "VkDeviceSize too small");
mTransformFeedbackBufferRange.offsets[index] = binding.getOffset();
mTransformFeedbackBufferRange.sizes[index] = gl::GetBoundBufferAvailableSize(binding);
// Set the offset as close as possible to the requested offset while remaining aligned.
mTransformFeedbackBufferRange.alignedOffsets[index] =
(mTransformFeedbackBufferRange.offsets[index] / offsetAlignment) * offsetAlignment;
// Make sure the transform feedback buffers are bound to the program descriptor sets.
contextVk->invalidateCurrentTransformFeedbackBuffers();
}
return angle::Result::Continue;
}
......@@ -187,8 +198,7 @@ void TransformFeedbackVk::initDescriptorSet(ContextVk *contextVk,
if (!contextVk->getFeatures().emulateTransformFeedback.enabled)
return;
std::array<VkDescriptorBufferInfo, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS>
descriptorBufferInfo;
gl::TransformFeedbackBuffersArray<VkDescriptorBufferInfo> descriptorBufferInfo;
for (size_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
{
......@@ -208,8 +218,6 @@ void TransformFeedbackVk::updateDescriptorSet(ContextVk *contextVk,
if (!contextVk->getFeatures().emulateTransformFeedback.enabled)
return;
const std::vector<gl::OffsetBindingPointer<gl::Buffer>> &xfbBuffers =
mState.getIndexedBuffers();
const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
ASSERT(executable);
size_t xfbBufferCount = executable->getTransformFeedbackBufferCount(contextVk->getState());
......@@ -218,26 +226,18 @@ void TransformFeedbackVk::updateDescriptorSet(ContextVk *contextVk,
ASSERT(programState.getTransformFeedbackBufferMode() != GL_INTERLEAVED_ATTRIBS ||
xfbBufferCount == 1);
std::array<VkDescriptorBufferInfo, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS>
descriptorBufferInfo;
gl::TransformFeedbackBuffersArray<VkDescriptorBufferInfo> descriptorBufferInfo;
// Update buffer descriptor binding info for output buffers
for (size_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
{
VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[bufferIndex];
const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = xfbBuffers[bufferIndex];
gl::Buffer *buffer = bufferBinding.get();
ASSERT(buffer != nullptr);
vk::BufferHelper &bufferHelper = vk::GetImpl(buffer)->getBuffer();
bufferInfo.buffer = bufferHelper.getBuffer().getHandle();
bufferInfo.offset = mTransformFeedbackBufferRange.alignedOffsets[bufferIndex];
bufferInfo.range = mTransformFeedbackBufferRange.sizes[bufferIndex] +
(mTransformFeedbackBufferRange.offsets[bufferIndex] -
mTransformFeedbackBufferRange.alignedOffsets[bufferIndex]);
bufferInfo.range = (bufferInfo.range == 0) ? bufferHelper.getSize() : bufferInfo.range;
bufferInfo.buffer = mBufferHandles[bufferIndex];
bufferInfo.offset = mAlignedBufferOffsets[bufferIndex];
bufferInfo.range = mBufferSizes[bufferIndex] +
(mBufferOffsets[bufferIndex] - mAlignedBufferOffsets[bufferIndex]);
ASSERT(bufferInfo.range != 0);
}
writeDescriptorSet(contextVk, xfbBufferCount, descriptorBufferInfo.data(), descSet);
......@@ -267,8 +267,7 @@ void TransformFeedbackVk::getBufferOffsets(ContextVk *contextVk,
for (size_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
{
int64_t offsetFromDescriptor =
static_cast<int64_t>(mTransformFeedbackBufferRange.offsets[bufferIndex] -
mTransformFeedbackBufferRange.alignedOffsets[bufferIndex]);
static_cast<int64_t>(mBufferOffsets[bufferIndex] - mAlignedBufferOffsets[bufferIndex]);
int64_t drawCallVertexOffset = static_cast<int64_t>(verticesDrawn) - drawCallFirstVertex;
int64_t writeOffset =
......
......@@ -27,18 +27,6 @@ namespace vk
class DescriptorSetLayoutDesc;
}
// Cached buffer properties for faster descriptor set update and offset calculation.
struct TransformFeedbackBufferRange
{
// Offset as provided by OffsetBindingPointer.
gl::TransformFeedbackBuffersArray<VkDeviceSize> offsets;
// Size as provided by OffsetBindingPointer.
gl::TransformFeedbackBuffersArray<VkDeviceSize> sizes;
// Aligned offset usable for VkDescriptorBufferInfo. This value could be smaller than
// offset.
gl::TransformFeedbackBuffersArray<VkDeviceSize> alignedOffsets;
};
class TransformFeedbackVk : public TransformFeedbackImpl
{
public:
......@@ -71,13 +59,31 @@ class TransformFeedbackVk : public TransformFeedbackImpl
int32_t *offsetsOut,
size_t offsetsSize) const;
void unsetTransformFeedbackBufferRebindState() { mRebindTransformFeedbackBuffer = false; }
bool getAndResetBufferRebindState()
{
bool retVal = mRebindTransformFeedbackBuffer;
mRebindTransformFeedbackBuffer = false;
return retVal;
}
const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &getBufferHelpers() const
{
return mBufferHelpers;
}
const gl::TransformFeedbackBuffersArray<VkBuffer> &getBufferHandles() const
{
return mBufferHandles;
}
bool getTransformFeedbackBufferRebindState() const { return mRebindTransformFeedbackBuffer; }
const gl::TransformFeedbackBuffersArray<VkDeviceSize> &getBufferOffsets() const
{
return mBufferOffsets;
}
const TransformFeedbackBufferRange &getTransformFeedbackBufferRange() const
const gl::TransformFeedbackBuffersArray<VkDeviceSize> &getBufferSizes() const
{
return mTransformFeedbackBufferRange;
return mBufferSizes;
}
const gl::TransformFeedbackBuffersArray<VkBuffer> &getCounterBufferHandles() const
......@@ -97,9 +103,17 @@ class TransformFeedbackVk : public TransformFeedbackImpl
// value is true, vertex shader will record transform feedback varyings from the beginning
// of the buffer.
bool mRebindTransformFeedbackBuffer;
TransformFeedbackBufferRange mTransformFeedbackBufferRange;
gl::TransformFeedbackBuffersArray<vk::BufferHelper *> mBufferHelpers;
gl::TransformFeedbackBuffersArray<VkBuffer> mBufferHandles;
gl::TransformFeedbackBuffersArray<VkDeviceSize> mBufferOffsets;
gl::TransformFeedbackBuffersArray<VkDeviceSize> mBufferSizes;
// Aligned offset for emulation. Could be smaller than offset.
gl::TransformFeedbackBuffersArray<VkDeviceSize> mAlignedBufferOffsets;
// Counter buffer used for pause and resume.
gl::TransformFeedbackBuffersArray<vk::BufferHelper> mCounterBuffer;
gl::TransformFeedbackBuffersArray<vk::BufferHelper> mCounterBufferHelpers;
gl::TransformFeedbackBuffersArray<VkBuffer> mCounterBufferHandles;
};
......
......@@ -660,11 +660,11 @@ void CommandBufferHelper::beginRenderPass(const vk::Framebuffer &framebuffer,
void CommandBufferHelper::beginTransformFeedback(size_t validBufferCount,
const VkBuffer *counterBuffers,
bool rebindBuffer)
bool rebindBuffers)
{
ASSERT(mIsRenderPassCommandBuffer);
mValidTransformFeedbackBufferCount = static_cast<uint32_t>(validBufferCount);
mRebindTransformFeedbackBuffers = rebindBuffer;
mRebindTransformFeedbackBuffers = rebindBuffers;
for (size_t index = 0; index < validBufferCount; index++)
{
......
......@@ -890,7 +890,7 @@ struct CommandBufferHelper : angle::NonCopyable
void beginTransformFeedback(size_t validBufferCount,
const VkBuffer *counterBuffers,
bool rebindBuffer);
bool rebindBuffers);
void invalidateRenderPassColorAttachment(size_t attachmentIndex)
{
......
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