Vulkan: Command graph linearization (Step 5).

Implements ES 3.1 support.

Bug: angleproject:4029
Change-Id: I3c08602cf4ec64621bfdb40cd40d142b666e6edf
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2046052
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Cody Northrop <cnorthrop@google.com>
This commit is contained in:
Jamie Madill 2020-02-11 09:35:38 -05:00 коммит произвёл Commit Bot
Родитель 72e9f4d73f
Коммит 3b82506abc
6 изменённых файлов: 142 добавлений и 73 удалений

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

@ -888,8 +888,16 @@ angle::Result ContextVk::setupIndirectDraw(const gl::Context *context,
GLsizei vertexCount = 0;
GLsizei instanceCount = 1;
vk::FramebufferHelper *framebuffer = mDrawFramebuffer->getFramebuffer();
indirectBuffer->onRead(this, framebuffer, VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
if (commandGraphEnabled())
{
vk::FramebufferHelper *framebuffer = mDrawFramebuffer->getFramebuffer();
indirectBuffer->onRead(this, framebuffer, VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
}
else
{
mRenderPassCommands.bufferRead(&mResourceUseList, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
indirectBuffer);
}
ANGLE_TRY(setupDraw(context, mode, firstVertex, vertexCount, instanceCount,
gl::DrawElementsType::InvalidEnum, nullptr, dirtyBitMask,
@ -998,7 +1006,19 @@ angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
angle::Result ContextVk::setupDispatch(const gl::Context *context,
vk::CommandBuffer **commandBufferOut)
{
ANGLE_TRY(mDispatcher.recordCommands(this, commandBufferOut));
if (commandGraphEnabled())
{
ANGLE_TRY(mDispatcher.recordCommands(this, commandBufferOut));
}
else
{
// |setupDispatch| and |setupDraw| are special in that they flush dirty bits. Therefore they
// don't use the same APIs to record commands as the functions outside ContextVk.
// The following ensures prior commands are flushed before we start processing dirty bits.
mOutsideRenderPassCommands.flushToPrimary(&mPrimaryCommands);
ANGLE_TRY(endRenderPass());
*commandBufferOut = &mOutsideRenderPassCommands.getCommandBuffer();
}
if (mProgram->dirtyUniforms())
{
@ -1089,9 +1109,11 @@ angle::Result ContextVk::handleDirtyComputePipeline(const gl::Context *context,
return angle::Result::Continue;
}
ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(const gl::Context *context,
vk::CommandBuffer *commandBuffer,
vk::CommandGraphResource *recorder)
ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
const gl::Context *context,
vk::CommandBuffer *commandBuffer,
vk::CommandGraphResource *recorder,
CommandBufferHelper *commandBufferHelper)
{
const gl::ActiveTextureMask &activeTextures = mProgram->getState().getActiveSamplersMask();
@ -1127,8 +1149,8 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(const gl::Context
}
else
{
mRenderPassCommands.imageRead(&mResourceUseList, image.getAspectFlags(), textureLayout,
&image);
commandBufferHelper->imageRead(&mResourceUseList, image.getAspectFlags(), textureLayout,
&image);
}
textureVk->onImageViewUse(&mResourceUseList);
@ -1154,13 +1176,15 @@ ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(const gl::Context
angle::Result ContextVk::handleDirtyGraphicsTextures(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
{
return handleDirtyTexturesImpl(context, commandBuffer, mDrawFramebuffer->getFramebuffer());
return handleDirtyTexturesImpl(context, commandBuffer, mDrawFramebuffer->getFramebuffer(),
&mRenderPassCommands);
}
angle::Result ContextVk::handleDirtyComputeTextures(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
{
return handleDirtyTexturesImpl(context, commandBuffer, &mDispatcher);
return handleDirtyTexturesImpl(context, commandBuffer, &mDispatcher,
&mOutsideRenderPassCommands);
}
angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(const gl::Context *context,
@ -1234,18 +1258,19 @@ angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(const gl::Context *conte
ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
const gl::Context *context,
vk::CommandBuffer *commandBuffer,
vk::CommandGraphResource *recorder)
vk::CommandGraphResource *recorder,
CommandBufferHelper *commandBufferHelper)
{
if (mProgram->hasImages())
{
ANGLE_TRY(updateActiveImages(context, recorder));
ANGLE_TRY(updateActiveImages(context, recorder, commandBufferHelper));
}
if (mProgram->hasUniformBuffers() || mProgram->hasStorageBuffers() ||
mProgram->hasAtomicCounterBuffers() || mProgram->hasImages())
{
ANGLE_TRY(mProgram->updateShaderResourcesDescriptorSet(this, &mResourceUseList,
&mRenderPassCommands, recorder));
commandBufferHelper, recorder));
}
return angle::Result::Continue;
}
@ -1254,13 +1279,14 @@ angle::Result ContextVk::handleDirtyGraphicsShaderResources(const gl::Context *c
vk::CommandBuffer *commandBuffer)
{
return handleDirtyShaderResourcesImpl(context, commandBuffer,
mDrawFramebuffer->getFramebuffer());
mDrawFramebuffer->getFramebuffer(), &mRenderPassCommands);
}
angle::Result ContextVk::handleDirtyComputeShaderResources(const gl::Context *context,
vk::CommandBuffer *commandBuffer)
{
return handleDirtyShaderResourcesImpl(context, commandBuffer, &mDispatcher);
return handleDirtyShaderResourcesImpl(context, commandBuffer, &mDispatcher,
&mOutsideRenderPassCommands);
}
angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
@ -2035,8 +2061,16 @@ angle::Result ContextVk::drawArraysIndirect(const gl::Context *context,
if (mVertexArray->getStreamingVertexAttribsMask().any())
{
vk::FramebufferHelper *framebuffer = mDrawFramebuffer->getFramebuffer();
currentIndirectBuf->onRead(this, framebuffer, VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
if (commandGraphEnabled())
{
vk::FramebufferHelper *framebuffer = mDrawFramebuffer->getFramebuffer();
currentIndirectBuf->onRead(this, framebuffer, VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
}
else
{
mRenderPassCommands.bufferRead(&mResourceUseList, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
currentIndirectBuf);
}
// We have instanced vertex attributes that need to be emulated for Vulkan.
// invalidate any cache and map the buffer so that we can read the indirect data.
@ -2089,8 +2123,16 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
if (mVertexArray->getStreamingVertexAttribsMask().any())
{
vk::FramebufferHelper *framebuffer = mDrawFramebuffer->getFramebuffer();
currentIndirectBuf->onRead(this, framebuffer, VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
if (commandGraphEnabled())
{
vk::FramebufferHelper *framebuffer = mDrawFramebuffer->getFramebuffer();
currentIndirectBuf->onRead(this, framebuffer, VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
}
else
{
mRenderPassCommands.bufferRead(&mResourceUseList, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
currentIndirectBuf);
}
// We have instanced vertex attributes that need to be emulated for Vulkan.
// invalidate any cache and map the buffer so that we can read the indirect data.
@ -3036,7 +3078,15 @@ angle::Result ContextVk::dispatchComputeIndirect(const gl::Context *context, GLi
gl::Buffer *glBuffer = getState().getTargetBuffer(gl::BufferBinding::DispatchIndirect);
vk::BufferHelper &buffer = vk::GetImpl(glBuffer)->getBuffer();
buffer.onRead(this, &mDispatcher, VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
if (commandGraphEnabled())
{
buffer.onRead(this, &mDispatcher, VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
}
else
{
mOutsideRenderPassCommands.bufferRead(&mResourceUseList,
VK_ACCESS_INDIRECT_COMMAND_READ_BIT, &buffer);
}
commandBuffer->dispatchIndirect(buffer.getBuffer(), indirect);
@ -3045,8 +3095,7 @@ angle::Result ContextVk::dispatchComputeIndirect(const gl::Context *context, GLi
angle::Result ContextVk::memoryBarrier(const gl::Context *context, GLbitfield barriers)
{
memoryBarrierImpl(barriers, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
return angle::Result::Continue;
return memoryBarrierImpl(barriers, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
angle::Result ContextVk::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
@ -3054,12 +3103,12 @@ angle::Result ContextVk::memoryBarrierByRegion(const gl::Context *context, GLbit
// Note: memoryBarrierByRegion is expected to affect only the fragment pipeline, but is
// otherwise similar to memoryBarrier.
memoryBarrierImpl(barriers, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
return angle::Result::Continue;
return memoryBarrierImpl(barriers, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}
void ContextVk::memoryBarrierImpl(GLbitfield barriers, VkPipelineStageFlags stageMask)
angle::Result ContextVk::memoryBarrierImpl(GLbitfield barriers, VkPipelineStageFlags stageMask)
{
// TOOD(jmadill): Clean up the comments with the refactor. http://anglebug.com/4029
// Note: most of the barriers specified here don't require us to issue a memory barrier, as
// the relevant resources already insert the appropriate barriers. They do however require
// the resource writing nodes to finish so future buffer barriers are placed correctly, as
@ -3092,9 +3141,18 @@ void ContextVk::memoryBarrierImpl(GLbitfield barriers, VkPipelineStageFlags stag
}
else
{
// TODO(jmadill): http://anglebug.com/4029
UNIMPLEMENTED();
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(getOutsideRenderPassCommandBuffer(&commandBuffer));
VkMemoryBarrier memoryBarrier = {};
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.srcAccessMask = srcAccess;
memoryBarrier.dstAccessMask = dstAccess;
commandBuffer->memoryBarrier(stageMask, stageMask, &memoryBarrier);
}
return angle::Result::Continue;
}
vk::DynamicQueryPool *ContextVk::getQueryPool(gl::QueryType queryType)
@ -3396,7 +3454,8 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
}
angle::Result ContextVk::updateActiveImages(const gl::Context *context,
vk::CommandGraphResource *recorder)
vk::CommandGraphResource *recorder,
CommandBufferHelper *commandBufferHelper)
{
const gl::State &glState = mState;
const gl::Program *program = glState.getProgram();
@ -3443,17 +3502,25 @@ angle::Result ContextVk::updateActiveImages(const gl::Context *context,
imageLayout = vk::ImageLayout::ComputeShaderWrite;
}
// Ensure the image is in the correct layout
if (image->isLayoutChangeNecessary(imageLayout))
VkImageAspectFlags aspectFlags = image->getAspectFlags();
if (commandGraphEnabled())
{
vk::CommandBuffer *layoutChange;
ANGLE_TRY(image->recordCommands(this, &layoutChange));
// Ensure the image is in the correct layout
if (image->isLayoutChangeNecessary(imageLayout))
{
vk::CommandBuffer *layoutChange;
ANGLE_TRY(image->recordCommands(this, &layoutChange));
VkImageAspectFlags aspectFlags = image->getAspectFlags();
image->changeLayout(aspectFlags, imageLayout, layoutChange);
image->changeLayout(aspectFlags, imageLayout, layoutChange);
}
image->addWriteDependency(this, recorder);
}
else
{
commandBufferHelper->imageWrite(&mResourceUseList, aspectFlags, imageLayout, image);
}
image->addWriteDependency(this, recorder);
}
return angle::Result::Continue;
@ -4001,22 +4068,14 @@ void CommandBufferHelper::executeBarriers(vk::PrimaryCommandBuffer *primary)
mGlobalMemoryBarrierStages = 0;
}
if (!mImageMemoryBarriers.empty())
{
srcStages |= mImageBarrierSrcStageMask;
dstStages |= mImageBarrierDstStageMask;
primary->pipelineBarrier(srcStages, dstStages, 0, memoryBarrierCount, &memoryBarrier, 0,
nullptr, static_cast<uint32_t>(mImageMemoryBarriers.size()),
mImageMemoryBarriers.data());
mImageMemoryBarriers.clear();
mImageBarrierSrcStageMask = 0;
mImageBarrierDstStageMask = 0;
}
else
{
primary->pipelineBarrier(srcStages, dstStages, 0, memoryBarrierCount, &memoryBarrier, 0,
nullptr, 0, nullptr);
}
srcStages |= mImageBarrierSrcStageMask;
dstStages |= mImageBarrierDstStageMask;
primary->pipelineBarrier(srcStages, dstStages, 0, memoryBarrierCount, &memoryBarrier, 0,
nullptr, static_cast<uint32_t>(mImageMemoryBarriers.size()),
mImageMemoryBarriers.data());
mImageMemoryBarriers.clear();
mImageBarrierSrcStageMask = 0;
mImageBarrierDstStageMask = 0;
}
OutsideRenderPassCommandBuffer::OutsideRenderPassCommandBuffer() = default;

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

@ -591,10 +591,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
angle::Result getOutsideRenderPassCommandBuffer(vk::CommandBuffer **commandBufferOut)
{
if (!mRenderPassCommands.empty())
{
ANGLE_TRY(endRenderPass());
}
ANGLE_TRY(endRenderPass());
*commandBufferOut = &mOutsideRenderPassCommands.getCommandBuffer();
return angle::Result::Continue;
}
@ -773,7 +770,8 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
angle::Result updateActiveTextures(const gl::Context *context);
angle::Result updateActiveImages(const gl::Context *context,
vk::CommandGraphResource *recorder);
vk::CommandGraphResource *recorder,
CommandBufferHelper *commandBufferHelper);
angle::Result updateDefaultAttribute(size_t attribIndex);
ANGLE_INLINE void invalidateCurrentGraphicsPipeline()
@ -833,10 +831,12 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
// Common parts of the common dirty bit handlers.
angle::Result handleDirtyTexturesImpl(const gl::Context *context,
vk::CommandBuffer *commandBuffer,
vk::CommandGraphResource *recorder);
vk::CommandGraphResource *recorder,
CommandBufferHelper *commandBufferHelper);
angle::Result handleDirtyShaderResourcesImpl(const gl::Context *context,
vk::CommandBuffer *commandBuffer,
vk::CommandGraphResource *recorder);
vk::CommandGraphResource *recorder,
CommandBufferHelper *commandBufferHelper);
void handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandBuffer,
VkPipelineBindPoint bindPoint,
const DriverUniformsDescriptorSet &driverUniforms);
@ -857,7 +857,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
angle::Result submitFrame(const VkSubmitInfo &submitInfo,
vk::PrimaryCommandBuffer &&commandBuffer);
angle::Result flushCommandGraph(vk::PrimaryCommandBuffer *commandBatch);
void memoryBarrierImpl(GLbitfield barriers, VkPipelineStageFlags stageMask);
angle::Result memoryBarrierImpl(GLbitfield barriers, VkPipelineStageFlags stageMask);
angle::Result synchronizeCpuGpuTime();
angle::Result traceGpuEventImpl(vk::PrimaryCommandBuffer *commandBuffer,

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

@ -1325,7 +1325,7 @@ void ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
void ProgramVk::updateBuffersDescriptorSet(ContextVk *contextVk,
vk::ResourceUseList *resourceUseList,
RenderPassCommandBuffer *renderPassCommands,
CommandBufferHelper *commandBufferHelper,
vk::CommandGraphResource *recorder,
const std::vector<gl::InterfaceBlock> &blocks,
VkDescriptorType descriptorType)
@ -1408,12 +1408,12 @@ void ProgramVk::updateBuffersDescriptorSet(ContextVk *contextVk,
{
// We set the SHADER_READ_BIT to be conservative.
VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
renderPassCommands->bufferWrite(resourceUseList, accessFlags, &bufferHelper);
commandBufferHelper->bufferWrite(resourceUseList, accessFlags, &bufferHelper);
}
else
{
renderPassCommands->bufferRead(resourceUseList, VK_ACCESS_UNIFORM_READ_BIT,
&bufferHelper);
commandBufferHelper->bufferRead(resourceUseList, VK_ACCESS_UNIFORM_READ_BIT,
&bufferHelper);
}
}
@ -1426,6 +1426,8 @@ void ProgramVk::updateBuffersDescriptorSet(ContextVk *contextVk,
}
void ProgramVk::updateAtomicCounterBuffersDescriptorSet(ContextVk *contextVk,
vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper,
vk::CommandGraphResource *recorder)
{
const gl::State &glState = contextVk->getState();
@ -1480,7 +1482,9 @@ void ProgramVk::updateAtomicCounterBuffersDescriptorSet(ContextVk *contextVk,
}
else
{
UNIMPLEMENTED();
commandBufferHelper->bufferWrite(resourceUseList,
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
&bufferHelper);
}
writtenBindings.set(binding);
@ -1593,16 +1597,17 @@ angle::Result ProgramVk::updateImagesDescriptorSet(ContextVk *contextVk,
angle::Result ProgramVk::updateShaderResourcesDescriptorSet(
ContextVk *contextVk,
vk::ResourceUseList *resourceUseList,
RenderPassCommandBuffer *renderPassCommands,
CommandBufferHelper *commandBufferHelper,
vk::CommandGraphResource *recorder)
{
ANGLE_TRY(allocateDescriptorSet(contextVk, kShaderResourceDescriptorSetIndex));
updateBuffersDescriptorSet(contextVk, resourceUseList, renderPassCommands, recorder,
updateBuffersDescriptorSet(contextVk, resourceUseList, commandBufferHelper, recorder,
mState.getUniformBlocks(), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
updateBuffersDescriptorSet(contextVk, resourceUseList, renderPassCommands, recorder,
updateBuffersDescriptorSet(contextVk, resourceUseList, commandBufferHelper, recorder,
mState.getShaderStorageBlocks(), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
updateAtomicCounterBuffersDescriptorSet(contextVk, recorder);
updateAtomicCounterBuffersDescriptorSet(contextVk, resourceUseList, commandBufferHelper,
recorder);
return updateImagesDescriptorSet(contextVk, recorder);
}

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

@ -110,7 +110,7 @@ class ProgramVk : public ProgramImpl
angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
angle::Result updateShaderResourcesDescriptorSet(ContextVk *contextVk,
vk::ResourceUseList *resourceUseList,
RenderPassCommandBuffer *renderPassCommands,
CommandBufferHelper *commandBufferHelper,
vk::CommandGraphResource *recorder);
angle::Result updateTransformFeedbackDescriptorSet(ContextVk *contextVk,
vk::FramebufferHelper *framebuffer);
@ -191,11 +191,13 @@ class ProgramVk : public ProgramImpl
void updateTransformFeedbackDescriptorSetImpl(ContextVk *contextVk);
void updateBuffersDescriptorSet(ContextVk *contextVk,
vk::ResourceUseList *resourceUseList,
RenderPassCommandBuffer *renderPassCommands,
CommandBufferHelper *commandBufferHelper,
vk::CommandGraphResource *recorder,
const std::vector<gl::InterfaceBlock> &blocks,
VkDescriptorType descriptorType);
void updateAtomicCounterBuffersDescriptorSet(ContextVk *contextVk,
vk::ResourceUseList *resourceUseList,
CommandBufferHelper *commandBufferHelper,
vk::CommandGraphResource *recorder);
angle::Result updateImagesDescriptorSet(ContextVk *contextVk,
vk::CommandGraphResource *recorder);

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

@ -1389,6 +1389,8 @@ angle::Result TextureVk::changeLevels(ContextVk *contextVk,
}
}
// This global barrier is no longer needed without the command graph as barriers are correctly
// inserted using the normal command APIs.
if (contextVk->commandGraphEnabled())
{
// Create a new node for the image and add a global memory barrier for the staging buffers.

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

@ -124,8 +124,9 @@ struct CombinedPrintToStringParamName
ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(), ES3_VULKAN(), ES3_VULKAN_SWIFTSHADER(), \
WithNoCommandGraph(ES3_VULKAN())
#define ANGLE_ALL_TEST_PLATFORMS_ES31 \
ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES(), ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER()
#define ANGLE_ALL_TEST_PLATFORMS_ES31 \
ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES(), ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER(), \
WithNoCommandGraph(ES31_VULKAN())
#define ANGLE_ALL_TEST_PLATFORMS_NULL ES2_NULL(), ES3_NULL(), ES31_NULL()