Commit 9601a548 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: implement external semaphore barriers

glWaitSemaphoreEXT and glSignalSemaphoreEXT functions optionally request buffer and image barriers to be performed by the implementation. If any barriers are present, a single global memory barrier is inserted to take care of memory accesses. In both functions, buffer and image memory barriers are used to perform queue ownership transfers to ANGLE's queue (glWaitSemaphoreEXT) or the EXTERNAL queue (glSignalSemaphoreEXT). In glWaitSemaphoreEXT, the given layouts are information regarding how the external entity (the caller) has modified the images' layouts, and is used to update ANGLE's internal state tracking. Bug: angleproject:3289 Bug: 1026673 Change-Id: Ic478a8813df727c89413c8ae2adf42b5c1d06069 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1933016 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarMichael Spang <spang@chromium.org>
parent 190d9a81
...@@ -1104,6 +1104,14 @@ void CommandGraph::makeHostVisibleBufferWriteAvailable() ...@@ -1104,6 +1104,14 @@ void CommandGraph::makeHostVisibleBufferWriteAvailable()
CommandGraphResourceType::HostAvailabilityOperation, 0); CommandGraphResourceType::HostAvailabilityOperation, 0);
} }
void CommandGraph::syncExternalMemory()
{
// Add an all-inclusive memory barrier.
memoryBarrier(VK_ACCESS_MEMORY_WRITE_BIT,
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
// Dumps the command graph into a dot file that works with graphviz. // Dumps the command graph into a dot file that works with graphviz.
void CommandGraph::dumpGraphDotFile(std::ostream &out) const void CommandGraph::dumpGraphDotFile(std::ostream &out) const
{ {
......
...@@ -382,6 +382,9 @@ class CommandGraphResource : angle::NonCopyable ...@@ -382,6 +382,9 @@ class CommandGraphResource : angle::NonCopyable
// Returns true if the resource is in use by the renderer. // Returns true if the resource is in use by the renderer.
bool isResourceInUse(ContextVk *contextVk) const; bool isResourceInUse(ContextVk *contextVk) const;
// Returns true if the resource has commands in the graph. This is used to know if a flush
// should be performed, e.g. if we need to wait for the GPU to finish with the resource.
bool isCurrentlyInGraph() const { return mUse.isCurrentlyInGraph(); }
// queries, to know if the queue they are submitted on has finished execution. // queries, to know if the queue they are submitted on has finished execution.
Serial getLatestSerial() const { return mUse.getSerial(); } Serial getLatestSerial() const { return mUse.getSerial(); }
...@@ -532,6 +535,8 @@ class CommandGraph final : angle::NonCopyable ...@@ -532,6 +535,8 @@ class CommandGraph final : angle::NonCopyable
void popDebugMarker(); void popDebugMarker();
// Host-visible buffer write availability operation: // Host-visible buffer write availability operation:
void makeHostVisibleBufferWriteAvailable(); void makeHostVisibleBufferWriteAvailable();
// External memory synchronization:
void syncExternalMemory();
void onResourceUse(const SharedResourceUse &resourceUse); void onResourceUse(const SharedResourceUse &resourceUse);
void releaseResourceUses(); void releaseResourceUses();
......
...@@ -95,6 +95,14 @@ void SecondaryCommandBuffer::executeCommands(VkCommandBuffer cmdBuffer) ...@@ -95,6 +95,14 @@ void SecondaryCommandBuffer::executeCommands(VkCommandBuffer cmdBuffer)
params->filter); params->filter);
break; break;
} }
case CommandID::BufferBarrier:
{
const BufferBarrierParams *params =
getParamPtr<BufferBarrierParams>(currentCommand);
vkCmdPipelineBarrier(cmdBuffer, params->srcStageMask, params->dstStageMask, 0,
0, nullptr, 1, &params->bufferMemoryBarrier, 0, nullptr);
break;
}
case CommandID::ClearAttachments: case CommandID::ClearAttachments:
{ {
const ClearAttachmentsParams *params = const ClearAttachmentsParams *params =
...@@ -426,6 +434,9 @@ std::string SecondaryCommandBuffer::dumpCommands(const char *separator) const ...@@ -426,6 +434,9 @@ std::string SecondaryCommandBuffer::dumpCommands(const char *separator) const
case CommandID::BlitImage: case CommandID::BlitImage:
result += "BlitImage"; result += "BlitImage";
break; break;
case CommandID::BufferBarrier:
result += "BufferBarrier";
break;
case CommandID::ClearAttachments: case CommandID::ClearAttachments:
result += "ClearAttachments"; result += "ClearAttachments";
break; break;
...@@ -501,6 +512,9 @@ std::string SecondaryCommandBuffer::dumpCommands(const char *separator) const ...@@ -501,6 +512,9 @@ std::string SecondaryCommandBuffer::dumpCommands(const char *separator) const
case CommandID::ResetQueryPool: case CommandID::ResetQueryPool:
result += "ResetQueryPool"; result += "ResetQueryPool";
break; break;
case CommandID::ResolveImage:
result += "ResolveImage";
break;
case CommandID::SetEvent: case CommandID::SetEvent:
result += "SetEvent"; result += "SetEvent";
break; break;
......
...@@ -36,6 +36,7 @@ enum class CommandID : uint16_t ...@@ -36,6 +36,7 @@ enum class CommandID : uint16_t
BindIndexBuffer, BindIndexBuffer,
BindVertexBuffers, BindVertexBuffers,
BlitImage, BlitImage,
BufferBarrier,
ClearAttachments, ClearAttachments,
ClearColorImage, ClearColorImage,
ClearDepthStencilImage, ClearDepthStencilImage,
...@@ -312,6 +313,14 @@ struct ExecutionBarrierParams ...@@ -312,6 +313,14 @@ struct ExecutionBarrierParams
}; };
VERIFY_4_BYTE_ALIGNMENT(ExecutionBarrierParams) VERIFY_4_BYTE_ALIGNMENT(ExecutionBarrierParams)
struct BufferBarrierParams
{
VkPipelineStageFlags srcStageMask;
VkPipelineStageFlags dstStageMask;
VkBufferMemoryBarrier bufferMemoryBarrier;
};
VERIFY_4_BYTE_ALIGNMENT(BufferBarrierParams)
struct ImageBarrierParams struct ImageBarrierParams
{ {
VkPipelineStageFlags srcStageMask; VkPipelineStageFlags srcStageMask;
...@@ -447,6 +456,10 @@ class SecondaryCommandBuffer final : angle::NonCopyable ...@@ -447,6 +456,10 @@ class SecondaryCommandBuffer final : angle::NonCopyable
const VkImageBlit *regions, const VkImageBlit *regions,
VkFilter filter); VkFilter filter);
void bufferBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkBufferMemoryBarrier *bufferMemoryBarrier);
void clearAttachments(uint32_t attachmentCount, void clearAttachments(uint32_t attachmentCount,
const VkClearAttachment *attachments, const VkClearAttachment *attachments,
uint32_t rectCount, uint32_t rectCount,
...@@ -800,6 +813,17 @@ ANGLE_INLINE void SecondaryCommandBuffer::blitImage(const Image &srcImage, ...@@ -800,6 +813,17 @@ ANGLE_INLINE void SecondaryCommandBuffer::blitImage(const Image &srcImage,
paramStruct->region = regions[0]; paramStruct->region = regions[0];
} }
ANGLE_INLINE void SecondaryCommandBuffer::bufferBarrier(
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkBufferMemoryBarrier *bufferMemoryBarrier)
{
BufferBarrierParams *paramStruct = initCommand<BufferBarrierParams>(CommandID::BufferBarrier);
paramStruct->srcStageMask = srcStageMask;
paramStruct->dstStageMask = dstStageMask;
paramStruct->bufferMemoryBarrier = *bufferMemoryBarrier;
}
ANGLE_INLINE void SecondaryCommandBuffer::clearAttachments(uint32_t attachmentCount, ANGLE_INLINE void SecondaryCommandBuffer::clearAttachments(uint32_t attachmentCount,
const VkClearAttachment *attachments, const VkClearAttachment *attachments,
uint32_t rectCount, uint32_t rectCount,
......
...@@ -9,12 +9,50 @@ ...@@ -9,12 +9,50 @@
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/ContextVk.h" #include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h" #include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/TextureVk.h"
namespace rx namespace rx
{ {
namespace
{
vk::ImageLayout GetVulkanImageLayout(GLenum layout)
{
switch (layout)
{
case GL_NONE:
return vk::ImageLayout::Undefined;
case GL_LAYOUT_GENERAL_EXT:
return vk::ImageLayout::ExternalShadersWrite;
case GL_LAYOUT_COLOR_ATTACHMENT_EXT:
return vk::ImageLayout::ColorAttachment;
case GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT:
case GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT:
case GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT:
case GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT:
// Note: once VK_KHR_separate_depth_stencil_layouts becomes core or ubiquitous, we
// should optimize depth/stencil image layout transitions to only be performed on the
// aspect that needs transition. In that case, these four layouts can be distinguished
// and optimized. Note that the exact equivalent of these layouts are specified in
// VK_KHR_maintenance2, which are also usable, granted we transition the pair of
// depth/stencil layouts accordingly elsewhere in ANGLE.
return vk::ImageLayout::DepthStencilAttachment;
case GL_LAYOUT_SHADER_READ_ONLY_EXT:
return vk::ImageLayout::ExternalShadersReadOnly;
case GL_LAYOUT_TRANSFER_SRC_EXT:
return vk::ImageLayout::TransferSrc;
case GL_LAYOUT_TRANSFER_DST_EXT:
return vk::ImageLayout::TransferDst;
default:
UNREACHABLE();
return vk::ImageLayout::Undefined;
}
}
} // anonymous namespace
SemaphoreVk::SemaphoreVk() = default; SemaphoreVk::SemaphoreVk() = default;
SemaphoreVk::~SemaphoreVk() = default; SemaphoreVk::~SemaphoreVk() = default;
...@@ -44,16 +82,59 @@ angle::Result SemaphoreVk::wait(gl::Context *context, ...@@ -44,16 +82,59 @@ angle::Result SemaphoreVk::wait(gl::Context *context,
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
if (!bufferBarriers.empty() || !textureBarriers.empty())
{
// Create one global memory barrier to cover all barriers.
contextVk->getCommandGraph()->syncExternalMemory();
}
uint32_t rendererQueueFamilyIndex = contextVk->getRenderer()->getQueueFamilyIndex();
if (!bufferBarriers.empty()) if (!bufferBarriers.empty())
{ {
// Buffers in external memory are not implemented yet. // Perform a queue ownership transfer for each buffer.
UNIMPLEMENTED(); for (gl::Buffer *buffer : bufferBarriers)
{
BufferVk *bufferVk = vk::GetImpl(buffer);
vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
// If there were GL commands using this buffer prior to this call, that's a
// synchronization error on behalf of the program.
ASSERT(!bufferHelper.isCurrentlyInGraph());
vk::CommandBuffer *queueChange;
ANGLE_TRY(bufferHelper.recordCommands(contextVk, &queueChange));
// Queue ownership transfer.
bufferHelper.changeQueue(rendererQueueFamilyIndex, queueChange);
}
} }
if (!textureBarriers.empty()) if (!textureBarriers.empty())
{ {
// Texture barriers are not implemented yet. // Perform a queue ownership transfer for each texture. Additionally, we are being
UNIMPLEMENTED(); // informed that the layout of the image has been externally transitioned, so we need to
// update our internal state tracking.
for (const gl::TextureAndLayout &textureAndLayout : textureBarriers)
{
TextureVk *textureVk = vk::GetImpl(textureAndLayout.texture);
vk::ImageHelper &image = textureVk->getImage();
vk::ImageLayout layout = GetVulkanImageLayout(textureAndLayout.layout);
// If there were GL commands using this image prior to this call, that's a
// synchronization error on behalf of the program.
ASSERT(!image.isCurrentlyInGraph());
// Inform the image that the layout has been externally changed.
image.onExternalLayoutChange(layout);
vk::CommandBuffer *queueChange;
ANGLE_TRY(image.recordCommands(contextVk, &queueChange));
// Queue ownership transfer.
image.changeLayoutAndQueue(image.getAspectFlags(), layout, rendererQueueFamilyIndex,
queueChange);
}
} }
contextVk->insertWaitSemaphore(&mSemaphore); contextVk->insertWaitSemaphore(&mSemaphore);
...@@ -68,14 +149,51 @@ angle::Result SemaphoreVk::signal(gl::Context *context, ...@@ -68,14 +149,51 @@ angle::Result SemaphoreVk::signal(gl::Context *context,
if (!bufferBarriers.empty()) if (!bufferBarriers.empty())
{ {
// Buffers in external memory are not implemented yet. // Perform a queue ownership transfer for each buffer.
UNIMPLEMENTED(); for (gl::Buffer *buffer : bufferBarriers)
{
BufferVk *bufferVk = vk::GetImpl(buffer);
vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
vk::CommandBuffer *queueChange;
ANGLE_TRY(bufferHelper.recordCommands(contextVk, &queueChange));
// Queue ownership transfer.
bufferHelper.changeQueue(VK_QUEUE_FAMILY_EXTERNAL, queueChange);
}
} }
if (!textureBarriers.empty()) if (!textureBarriers.empty())
{ {
// Texture barriers are not implemented yet. // Perform a queue ownership transfer for each texture. Additionally, transition the image
UNIMPLEMENTED(); // to the requested layout.
for (const gl::TextureAndLayout &textureAndLayout : textureBarriers)
{
TextureVk *textureVk = vk::GetImpl(textureAndLayout.texture);
vk::ImageHelper &image = textureVk->getImage();
vk::ImageLayout layout = GetVulkanImageLayout(textureAndLayout.layout);
// Don't transition to Undefined layout. If external wants to transition the image away
// from Undefined after this operation, it's perfectly fine to keep the layout as is in
// ANGLE. Note that vk::ImageHelper doesn't expect transitions to Undefined.
if (layout == vk::ImageLayout::Undefined)
{
layout = image.getCurrentImageLayout();
}
vk::CommandBuffer *layoutChange;
ANGLE_TRY(image.recordCommands(contextVk, &layoutChange));
// Queue ownership transfer and layout transition.
image.changeLayoutAndQueue(image.getAspectFlags(), layout, VK_QUEUE_FAMILY_EXTERNAL,
layoutChange);
}
}
if (!bufferBarriers.empty() || !textureBarriers.empty())
{
// Create one global memory barrier to cover all barriers.
contextVk->getCommandGraph()->syncExternalMemory();
} }
return contextVk->flushImpl(&mSemaphore); return contextVk->flushImpl(&mSemaphore);
......
...@@ -100,6 +100,32 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -100,6 +100,32 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
}, },
}, },
{ {
ImageLayout::ExternalShadersReadOnly,
{
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
// Transition to: all reads must happen after barrier.
VK_ACCESS_SHADER_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier.
0,
false,
},
},
{
ImageLayout::ExternalShadersWrite,
{
VK_IMAGE_LAYOUT_GENERAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
// Transition to: all reads and writes must happen after barrier.
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
// Transition from: all writes must finish before barrier.
VK_ACCESS_SHADER_WRITE_BIT,
true,
},
},
{
ImageLayout::TransferSrc, ImageLayout::TransferSrc,
{ {
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
...@@ -1401,6 +1427,7 @@ BufferHelper::BufferHelper() ...@@ -1401,6 +1427,7 @@ BufferHelper::BufferHelper()
mSize(0), mSize(0),
mMappedMemory(nullptr), mMappedMemory(nullptr),
mViewFormat(nullptr), mViewFormat(nullptr),
mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
mCurrentWriteAccess(0), mCurrentWriteAccess(0),
mCurrentReadAccess(0) mCurrentReadAccess(0)
{} {}
...@@ -1421,8 +1448,10 @@ angle::Result BufferHelper::init(ContextVk *contextVk, ...@@ -1421,8 +1448,10 @@ angle::Result BufferHelper::init(ContextVk *contextVk,
mSize = createInfo.size; mSize = createInfo.size;
ANGLE_VK_TRY(contextVk, mBuffer.init(contextVk->getDevice(), createInfo)); ANGLE_VK_TRY(contextVk, mBuffer.init(contextVk->getDevice(), createInfo));
return AllocateBufferMemory(contextVk, memoryPropertyFlags, &mMemoryPropertyFlags, nullptr, ANGLE_TRY(AllocateBufferMemory(contextVk, memoryPropertyFlags, &mMemoryPropertyFlags, nullptr,
&mBuffer, &mDeviceMemory); &mBuffer, &mDeviceMemory));
mCurrentQueueFamilyIndex = contextVk->getRenderer()->getQueueFamilyIndex();
return angle::Result::Continue;
} }
void BufferHelper::destroy(VkDevice device) void BufferHelper::destroy(VkDevice device)
...@@ -1581,6 +1610,24 @@ angle::Result BufferHelper::invalidate(ContextVk *contextVk, VkDeviceSize offset ...@@ -1581,6 +1610,24 @@ angle::Result BufferHelper::invalidate(ContextVk *contextVk, VkDeviceSize offset
return angle::Result::Continue; return angle::Result::Continue;
} }
void BufferHelper::changeQueue(uint32_t newQueueFamilyIndex, CommandBuffer *commandBuffer)
{
VkBufferMemoryBarrier bufferMemoryBarrier = {};
bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
bufferMemoryBarrier.srcAccessMask = 0;
bufferMemoryBarrier.dstAccessMask = 0;
bufferMemoryBarrier.srcQueueFamilyIndex = mCurrentQueueFamilyIndex;
bufferMemoryBarrier.dstQueueFamilyIndex = newQueueFamilyIndex;
bufferMemoryBarrier.buffer = mBuffer.getHandle();
bufferMemoryBarrier.offset = 0;
bufferMemoryBarrier.size = VK_WHOLE_SIZE;
commandBuffer->bufferBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &bufferMemoryBarrier);
mCurrentQueueFamilyIndex = newQueueFamilyIndex;
}
// ImageHelper implementation. // ImageHelper implementation.
ImageHelper::ImageHelper() ImageHelper::ImageHelper()
: CommandGraphResource(CommandGraphResourceType::Image), : CommandGraphResource(CommandGraphResourceType::Image),
...@@ -1928,6 +1975,15 @@ void ImageHelper::changeLayoutAndQueue(VkImageAspectFlags aspectMask, ...@@ -1928,6 +1975,15 @@ void ImageHelper::changeLayoutAndQueue(VkImageAspectFlags aspectMask,
forceChangeLayoutAndQueue(aspectMask, newLayout, newQueueFamilyIndex, commandBuffer); forceChangeLayoutAndQueue(aspectMask, newLayout, newQueueFamilyIndex, commandBuffer);
} }
void ImageHelper::onExternalLayoutChange(ImageLayout newLayout)
{
mCurrentLayout = newLayout;
// The image must have already been owned by EXTERNAL. If this is not the case, it's an
// application bug, so ASSERT might eventually need to change to a warning.
ASSERT(mCurrentQueueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL);
}
uint32_t ImageHelper::getBaseLevel() uint32_t ImageHelper::getBaseLevel()
{ {
return mBaseLevel; return mBaseLevel;
......
...@@ -560,6 +560,8 @@ class BufferHelper final : public CommandGraphResource ...@@ -560,6 +560,8 @@ class BufferHelper final : public CommandGraphResource
// After a sequence of writes, call invalidate to ensure the data is visible to the host. // After a sequence of writes, call invalidate to ensure the data is visible to the host.
angle::Result invalidate(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize size); angle::Result invalidate(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize size);
void changeQueue(uint32_t newQueueFamilyIndex, CommandBuffer *commandBuffer);
private: private:
angle::Result mapImpl(ContextVk *contextVk); angle::Result mapImpl(ContextVk *contextVk);
bool needsOnReadBarrier(VkAccessFlags readAccessType, bool needsOnReadBarrier(VkAccessFlags readAccessType,
...@@ -602,6 +604,7 @@ class BufferHelper final : public CommandGraphResource ...@@ -602,6 +604,7 @@ class BufferHelper final : public CommandGraphResource
VkDeviceSize mSize; VkDeviceSize mSize;
uint8_t *mMappedMemory; uint8_t *mMappedMemory;
const Format *mViewFormat; const Format *mViewFormat;
uint32_t mCurrentQueueFamilyIndex;
// For memory barriers. // For memory barriers.
VkFlags mCurrentWriteAccess; VkFlags mCurrentWriteAccess;
...@@ -642,18 +645,20 @@ enum class ImageLayout ...@@ -642,18 +645,20 @@ enum class ImageLayout
{ {
Undefined = 0, Undefined = 0,
ExternalPreInitialized = 1, ExternalPreInitialized = 1,
TransferSrc = 2, ExternalShadersReadOnly = 2,
TransferDst = 3, ExternalShadersWrite = 3,
ComputeShaderReadOnly = 4, TransferSrc = 4,
ComputeShaderWrite = 5, TransferDst = 5,
AllGraphicsShadersReadOnly = 6, ComputeShaderReadOnly = 6,
AllGraphicsShadersWrite = 7, ComputeShaderWrite = 7,
ColorAttachment = 8, AllGraphicsShadersReadOnly = 8,
DepthStencilAttachment = 9, AllGraphicsShadersWrite = 9,
Present = 10, ColorAttachment = 10,
DepthStencilAttachment = 11,
InvalidEnum = 11, Present = 12,
EnumCount = 11,
InvalidEnum = 13,
EnumCount = 13,
}; };
class ImageHelper final : public CommandGraphResource class ImageHelper final : public CommandGraphResource
...@@ -752,6 +757,7 @@ class ImageHelper final : public CommandGraphResource ...@@ -752,6 +757,7 @@ class ImageHelper final : public CommandGraphResource
const Format &getFormat() const { return *mFormat; } const Format &getFormat() const { return *mFormat; }
GLint getSamples() const { return mSamples; } GLint getSamples() const { return mSamples; }
ImageLayout getCurrentImageLayout() const { return mCurrentLayout; }
VkImageLayout getCurrentLayout() const; VkImageLayout getCurrentLayout() const;
// Helper function to calculate the extents of a render target created for a certain mip of the // Helper function to calculate the extents of a render target created for a certain mip of the
...@@ -896,6 +902,10 @@ class ImageHelper final : public CommandGraphResource ...@@ -896,6 +902,10 @@ class ImageHelper final : public CommandGraphResource
uint32_t newQueueFamilyIndex, uint32_t newQueueFamilyIndex,
CommandBuffer *commandBuffer); CommandBuffer *commandBuffer);
// If the image is used externally to GL, its layout could be different from ANGLE's internal
// state. This function is used to inform ImageHelper of an external layout change.
void onExternalLayoutChange(ImageLayout newLayout);
uint32_t getBaseLevel(); uint32_t getBaseLevel();
void setBaseAndMaxLevels(uint32_t baseLevel, uint32_t maxLevel); void setBaseAndMaxLevels(uint32_t baseLevel, uint32_t maxLevel);
......
...@@ -304,6 +304,10 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer> ...@@ -304,6 +304,10 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
VkDeviceSize size, VkDeviceSize size,
uint32_t data); uint32_t data);
void bufferBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkBufferMemoryBarrier *bufferMemoryBarrier);
void imageBarrier(VkPipelineStageFlags srcStageMask, void imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask, VkPipelineStageFlags dstStageMask,
const VkImageMemoryBarrier *imageMemoryBarrier); const VkImageMemoryBarrier *imageMemoryBarrier);
...@@ -672,6 +676,15 @@ ANGLE_INLINE void CommandBuffer::executionBarrier(VkPipelineStageFlags stageMask ...@@ -672,6 +676,15 @@ ANGLE_INLINE void CommandBuffer::executionBarrier(VkPipelineStageFlags stageMask
vkCmdPipelineBarrier(mHandle, stageMask, stageMask, 0, 0, nullptr, 0, nullptr, 0, nullptr); vkCmdPipelineBarrier(mHandle, stageMask, stageMask, 0, 0, nullptr, 0, nullptr, 0, nullptr);
} }
ANGLE_INLINE void CommandBuffer::bufferBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkBufferMemoryBarrier *bufferMemoryBarrier)
{
ASSERT(valid());
vkCmdPipelineBarrier(mHandle, srcStageMask, dstStageMask, 0, 0, nullptr, 1, bufferMemoryBarrier,
0, nullptr);
}
ANGLE_INLINE void CommandBuffer::imageBarrier(VkPipelineStageFlags srcStageMask, ANGLE_INLINE void CommandBuffer::imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask, VkPipelineStageFlags dstStageMask,
const VkImageMemoryBarrier *imageMemoryBarrier) const VkImageMemoryBarrier *imageMemoryBarrier)
......
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