Commit 2219b18c by Tobin Ehlis Committed by Commit Bot

Vulkan:Optimize SecondaryCommandBuffers

Optimize performance of SecondaryCommandBuffers and enable them as the default build option. To disable this set angle_enable_custom_vulkan_cmd_buffers=false in your build args. This CL enhances the PoolAllocator to have a "fast" mode that can be enabled at class creation. This mode uses an alignment of 1 byte and enables a fastAllocation() call that avoids some bookkeeping overhead. The SecondaryCommandBuffer uses this fastAllocation() function. Furthermore the fast path of fast allocate, using the current page, is inlined for maximum speed. Jamie Madill also updated the SecondaryCommandBuffers to pre-allocate blocks so that the commands occur linearly in memory. This speeds up processing with improved cache coherency and minimizes overhead when recording commands. Also the core Draw functions and their state updates are all inlined as well as the common functions to initialize commands and to copy command pointer data. This change also includes some new, custom commands. One is imageBarrier that is a specialized version of pipelineBarrier that only performs a single image layout transition. There are customized versions of various Draw commands to minimize copying of parameters. There are also specialized commands to bind[Graphics|Compute]Pipeline that have the pipeline type built in to the command. More custom commands and command data size optimizations will be made in follow-on commits. Bug: angleproject:3136 Change-Id: I35453cc2656bc8c51f0d84d1adef106900aca9a5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1497418 Commit-Queue: Tobin Ehlis <tobine@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 3e8a8d5b
......@@ -86,7 +86,7 @@ declare_args() {
angle_vulkan_conformant_configs_only = is_official_build
# Enable custom (cpu-side) secondary command buffers
angle_enable_custom_vulkan_cmd_buffers = false
angle_enable_custom_vulkan_cmd_buffers = true
}
}
......
......@@ -15,6 +15,7 @@
#include "common/angleutils.h"
#include "common/debug.h"
#include "common/mathutil.h"
#include "common/platform.h"
#include "common/tls.h"
......@@ -36,43 +37,48 @@ PoolAllocator::PoolAllocator(int growthIncrement, int allocationAlignment)
#endif
mLocked(false)
{
//
// Adjust mAlignment to be at least pointer aligned and
// power of 2.
//
size_t minAlign = sizeof(void *);
mAlignment &= ~(minAlign - 1);
if (mAlignment < minAlign)
mAlignment = minAlign;
size_t a = 1;
while (a < mAlignment)
a <<= 1;
mAlignment = a;
mAlignmentMask = a - 1;
if (mAlignment == 1)
{
// This is a special fast-path where fastAllocation() is enabled
mAlignmentMask = 0;
mHeaderSkip = sizeof(Header);
}
else
{
//
// Adjust mAlignment to be at least pointer aligned and
// power of 2.
//
size_t minAlign = sizeof(void *);
mAlignment &= ~(minAlign - 1);
if (mAlignment < minAlign)
mAlignment = minAlign;
mAlignment = gl::ceilPow2(mAlignment);
mAlignmentMask = mAlignment - 1;
#if !defined(ANGLE_DISABLE_POOL_ALLOC)
//
// Align header skip
//
mHeaderSkip = minAlign;
if (mHeaderSkip < sizeof(Header))
{
mHeaderSkip = rx::roundUp(sizeof(Header), mAlignment);
}
}
//
// Don't allow page sizes we know are smaller than all common
// OS page sizes.
//
if (mPageSize < 4 * 1024)
mPageSize = 4 * 1024;
//
// A large mCurrentPageOffset indicates a new page needs to
// be obtained to allocate memory.
//
mCurrentPageOffset = mPageSize;
//
// Align header skip
//
mHeaderSkip = minAlign;
if (mHeaderSkip < sizeof(Header))
{
mHeaderSkip = (sizeof(Header) + mAlignmentMask) & ~mAlignmentMask;
}
#else // !defined(ANGLE_DISABLE_POOL_ALLOC)
}
mStack.push_back({});
#endif
}
......@@ -262,7 +268,21 @@ void *PoolAllocator::allocate(size_t numBytes)
reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(memory) + mHeaderSkip);
return std::align(mAlignment, numBytes, unalignedPtr, allocationSize);
}
unsigned char *newPageAddr =
static_cast<unsigned char *>(allocateNewPage(numBytes, allocationSize));
return initializeAllocation(mInUseList, newPageAddr, numBytes);
#else // !defined(ANGLE_DISABLE_POOL_ALLOC)
void *alloc = malloc(numBytes + mAlignmentMask);
mStack.back().push_back(alloc);
intptr_t intAlloc = reinterpret_cast<intptr_t>(alloc);
intAlloc = rx::roundUp(intAlloc, mAlignment);
return reinterpret_cast<void *>(intAlloc);
#endif
}
void *PoolAllocator::allocateNewPage(size_t numBytes, size_t allocationSize)
{
//
// Need a simple page to allocate from.
//
......@@ -278,22 +298,13 @@ void *PoolAllocator::allocate(size_t numBytes)
if (memory == 0)
return 0;
}
// Use placement-new to initialize header
new (memory) Header(mInUseList, 1);
mInUseList = memory;
unsigned char *ret = reinterpret_cast<unsigned char *>(mInUseList) + mHeaderSkip;
mCurrentPageOffset = (mHeaderSkip + allocationSize + mAlignmentMask) & ~mAlignmentMask;
return initializeAllocation(mInUseList, ret, numBytes);
#else // !defined(ANGLE_DISABLE_POOL_ALLOC)
void *alloc = malloc(numBytes + mAlignmentMask);
mStack.back().push_back(alloc);
intptr_t intAlloc = reinterpret_cast<intptr_t>(alloc);
intAlloc = (intAlloc + mAlignmentMask) & ~mAlignmentMask;
return reinterpret_cast<void *>(intAlloc);
#endif
return ret;
}
void PoolAllocator::lock()
......
......@@ -38,6 +38,7 @@
#include <vector>
#include "angleutils.h"
#include "common/debug.h"
namespace angle
{
......@@ -123,6 +124,10 @@ class PoolAllocator : angle::NonCopyable
{
public:
static const int kDefaultAlignment = 16;
//
// Create PoolAllocator. If alignment is be set to 1 byte then fastAllocate()
// function can be used to make allocations with less overhead.
//
PoolAllocator(int growthIncrement = 8 * 1024, int allocationAlignment = kDefaultAlignment);
//
......@@ -154,6 +159,32 @@ class PoolAllocator : angle::NonCopyable
void *allocate(size_t numBytes);
//
// Call fastAllocate() for a faster allocate function that does minimal bookkeeping
// preCondition: Allocator must have been created w/ alignment of 1
ANGLE_INLINE uint8_t *fastAllocate(size_t numBytes)
{
#if defined(ANGLE_DISABLE_POOL_ALLOC)
return allocate(numBytes);
#endif
ASSERT(mAlignment == 1);
// No multi-page allocations
ASSERT(numBytes <= (mPageSize - mHeaderSkip));
//
// Do the allocation, most likely case inline first, for efficiency.
//
if (numBytes <= mPageSize - mCurrentPageOffset)
{
//
// Safe to allocate from mCurrentPageOffset.
//
uint8_t *memory = reinterpret_cast<uint8_t *>(mInUseList) + mCurrentPageOffset;
mCurrentPageOffset += numBytes;
return memory;
}
return reinterpret_cast<uint8_t *>(allocateNewPage(numBytes, numBytes));
}
//
// There is no deallocate. The point of this class is that
// deallocation can be skipped by the user of it, as the model
// of use is to simultaneously deallocate everything at once
......@@ -205,6 +236,8 @@ class PoolAllocator : angle::NonCopyable
};
using AllocStack = std::vector<AllocState>;
// Slow path of allocation when we have to get a new page.
void *allocateNewPage(size_t numBytes, size_t allocationSize);
// Track allocations if and only if we're using guard blocks
void *initializeAllocation(Header *block, unsigned char *memory, size_t numBytes)
{
......
......@@ -139,10 +139,9 @@ void MakeDebugUtilsLabel(GLenum source, const char *marker, VkDebugUtilsLabelEXT
}
#if ANGLE_USE_CUSTOM_VULKAN_CMD_BUFFERS
static constexpr VkSubpassContents kRenderPassContents = VK_SUBPASS_CONTENTS_INLINE;
constexpr VkSubpassContents kRenderPassContents = VK_SUBPASS_CONTENTS_INLINE;
#else
static constexpr VkSubpassContents kRenderPassContents =
VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
constexpr VkSubpassContents kRenderPassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
#endif
// Helpers to unify executeCommands call based on underlying cmd buffer type
......@@ -303,7 +302,6 @@ CommandGraphNode::CommandGraphNode(CommandGraphNodeFunction function,
CommandGraphNode::~CommandGraphNode()
{
mRenderPassFramebuffer.setHandle(VK_NULL_HANDLE);
// Command buffers are managed by the command pool, so don't need to be freed.
mOutsideRenderPassCommands.releaseHandle();
mInsideRenderPassCommands.releaseHandle();
......@@ -503,7 +501,6 @@ angle::Result CommandGraphNode::visitAndExecute(vk::Context *context,
RenderPass *renderPass = nullptr;
ANGLE_TRY(renderPassCache->getCompatibleRenderPass(context, serial, mRenderPassDesc,
&renderPass));
ANGLE_VK_TRY(context, mInsideRenderPassCommands.end());
VkRenderPassBeginInfo beginInfo = {};
......@@ -634,7 +631,10 @@ CommandGraph::CommandGraph(bool enableGraphDiagnostics, angle::PoolAllocator *po
: mEnableGraphDiagnostics(enableGraphDiagnostics),
mPoolAllocator(poolAllocator),
mLastBarrierIndex(kInvalidNodeIndex)
{}
{
// Push so that allocations made from here will be recycled in clear() below.
mPoolAllocator->push();
}
CommandGraph::~CommandGraph()
{
......@@ -776,6 +776,12 @@ bool CommandGraph::empty() const
void CommandGraph::clear()
{
mLastBarrierIndex = kInvalidNodeIndex;
// Release cmd graph pool memory now that cmds are submitted
// NOTE: This frees all memory since last push. Right now only the CommandGraph
// will push the allocator (at creation and below). If other people start
// pushing the allocator this (and/or the allocator) will need to be updated.
mPoolAllocator->pop();
mPoolAllocator->push();
// TODO(jmadill): Use pool allocator for performance. http://anglebug.com/2951
for (CommandGraphNode *node : mNodes)
......
......@@ -24,6 +24,7 @@ namespace rx
namespace vk
{
enum class VisitedState
{
Unvisited,
......@@ -119,9 +120,11 @@ class CommandGraphNode final : angle::NonCopyable
static void SetHappensBeforeDependencies(CommandGraphNode **beforeNodes,
size_t beforeNodesCount,
CommandGraphNode *afterNode);
static void SetHappensBeforeDependencies(CommandGraphNode *beforeNode,
CommandGraphNode **afterNodes,
size_t afterNodesCount);
bool hasParents() const;
bool hasChildren() const { return mHasChildren; }
......
......@@ -369,9 +369,7 @@ angle::Result ContextVk::handleDirtyPipeline(const gl::Context *context,
mGraphicsPipelineTransition.reset();
}
commandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline->getPipeline());
commandBuffer->bindGraphicsPipeline(mCurrentPipeline->getPipeline());
// Update the queue serial for the pipeline object.
ASSERT(mCurrentPipeline && mCurrentPipeline->valid());
mCurrentPipeline->updateSerial(mRenderer->getCurrentQueueSerial());
......@@ -449,8 +447,8 @@ angle::Result ContextVk::drawArrays(const gl::Context *context,
GLint first,
GLsizei count)
{
CommandBufferT *commandBuffer = nullptr;
uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
CommandBufferT *commandBuffer = nullptr;
uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
if (mode == gl::PrimitiveMode::LineLoop)
{
......@@ -462,7 +460,7 @@ angle::Result ContextVk::drawArrays(const gl::Context *context,
{
ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->draw(clampedVertexCount, 1, first, 0);
commandBuffer->draw(clampedVertexCount, first);
}
return angle::Result::Continue;
......@@ -484,7 +482,7 @@ angle::Result ContextVk::drawArraysInstanced(const gl::Context *context,
CommandBufferT *commandBuffer = nullptr;
ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->draw(gl::GetClampedVertexCount<uint32_t>(count), instances, first, 0);
commandBuffer->drawInstanced(gl::GetClampedVertexCount<uint32_t>(count), instances, first);
return angle::Result::Continue;
}
......@@ -503,7 +501,7 @@ angle::Result ContextVk::drawElements(const gl::Context *context,
else
{
ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer));
commandBuffer->drawIndexed(count, 1, 0, 0, 0);
commandBuffer->drawIndexed(count);
}
return angle::Result::Continue;
......@@ -525,7 +523,7 @@ angle::Result ContextVk::drawElementsInstanced(const gl::Context *context,
CommandBufferT *commandBuffer = nullptr;
ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer));
commandBuffer->drawIndexed(count, instances, 0, 0, 0);
commandBuffer->drawIndexedInstanced(count, instances);
return angle::Result::Continue;
}
......
......@@ -424,7 +424,7 @@ angle::Result FramebufferVk::blitWithCopy(ContextVk *contextVk,
VkImageAspectFlags aspectMask =
vk::GetDepthStencilAspectFlagsForCopy(blitDepthBuffer, blitStencilBuffer);
CommandBufferT *commandBuffer;
CommandBufferT *commandBuffer = nullptr;
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
vk::ImageHelper *writeImage = drawRenderTarget->getImageForWrite(&mFramebuffer);
......@@ -509,7 +509,7 @@ angle::Result FramebufferVk::blitWithReadback(ContextVk *contextVk,
// Reinitialize the commandBuffer after a read pixels because it calls
// renderer->finish which makes command buffers obsolete.
CommandBufferT *commandBuffer;
CommandBufferT *commandBuffer = nullptr;
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
// We read the bytes of the image in a buffer, now we have to copy them into the
......@@ -669,7 +669,7 @@ angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
vk::ImageHelper *dstImage = drawRenderTarget->getImageForWrite(&mFramebuffer);
CommandBufferT *commandBuffer;
CommandBufferT *commandBuffer = nullptr;
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
const vk::Format &readImageFormat = readRenderTarget->getImageFormat();
......@@ -903,8 +903,8 @@ angle::Result FramebufferVk::clearWithClearAttachments(
// This command can only happen inside a render pass, so obtain one if its already happening
// or create a new one if not.
CommandBufferT *commandBuffer = nullptr;
vk::RecordingMode mode = vk::RecordingMode::Start;
CommandBufferT *commandBuffer = nullptr;
vk::RecordingMode mode = vk::RecordingMode::Start;
ANGLE_TRY(getCommandBufferForDraw(contextVk, &commandBuffer, &mode));
// The array layer is offset by the ImageView. So we shouldn't need to set a base array layer.
......
......@@ -506,7 +506,7 @@ RendererVk::RendererVk()
mCurrentQueueSerial(mQueueSerialFactory.generate()),
mDeviceLost(false),
mPipelineCacheVkUpdateTimeout(kPipelineCacheVkUpdatePeriod),
mPoolAllocator(kDefaultPoolAllocatorPageSize),
mPoolAllocator(kDefaultPoolAllocatorPageSize, 1),
mCommandGraph(kEnableCommandGraphDiagnostics, &mPoolAllocator),
mGpuEventsEnabled(false),
mGpuClockSync{std::numeric_limits<double>::max(), std::numeric_limits<double>::max()},
......
......@@ -503,18 +503,18 @@ angle::Result WindowSurfaceVk::recreateSwapchain(DisplayVk *displayVk,
swapchainInfo.imageFormat = nativeFormat;
swapchainInfo.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
// Note: Vulkan doesn't allow 0-width/height swapchains.
swapchainInfo.imageExtent.width = std::max(extents.width, 1);
swapchainInfo.imageExtent.height = std::max(extents.height, 1);
swapchainInfo.imageArrayLayers = 1;
swapchainInfo.imageUsage = kImageUsageFlags;
swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchainInfo.queueFamilyIndexCount = 0;
swapchainInfo.pQueueFamilyIndices = nullptr;
swapchainInfo.preTransform = mPreTransform;
swapchainInfo.compositeAlpha = mCompositeAlpha;
swapchainInfo.presentMode = mDesiredSwapchainPresentMode;
swapchainInfo.clipped = VK_TRUE;
swapchainInfo.oldSwapchain = oldSwapchain;
swapchainInfo.imageExtent.width = std::max(extents.width, 1);
swapchainInfo.imageExtent.height = std::max(extents.height, 1);
swapchainInfo.imageArrayLayers = 1;
swapchainInfo.imageUsage = kImageUsageFlags;
swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchainInfo.queueFamilyIndexCount = 0;
swapchainInfo.pQueueFamilyIndices = nullptr;
swapchainInfo.preTransform = mPreTransform;
swapchainInfo.compositeAlpha = mCompositeAlpha;
swapchainInfo.presentMode = mDesiredSwapchainPresentMode;
swapchainInfo.clipped = VK_TRUE;
swapchainInfo.oldSwapchain = oldSwapchain;
// TODO(syoussefi): Once EGL_SWAP_BEHAVIOR_PRESERVED_BIT is supported, the contents of the old
// swapchain need to carry over to the new one. http://anglebug.com/2942
......@@ -738,7 +738,7 @@ angle::Result WindowSurfaceVk::present(DisplayVk *displayVk,
std::vector<VkRectLayerKHR> vk_rects;
if (renderer->getFeatures().supportsIncrementalPresent && (n_rects > 0))
{
EGLint *egl_rects = rects;
EGLint *egl_rects = rects;
presentRegion.rectangleCount = n_rects;
vk_rects.resize(n_rects);
for (EGLint rect = 0; rect < n_rects; rect++)
......
......@@ -1004,7 +1004,7 @@ angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context)
sourceRowPitch, imageData + bufferOffset));
}
CommandBufferT *commandBuffer;
CommandBufferT *commandBuffer = nullptr;
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
return mImage->flushStagedUpdates(contextVk, getNativeImageLevel(0), getLevelCount(),
commandBuffer);
......
......@@ -335,7 +335,7 @@ angle::Result UtilsVk::setupProgram(vk::Context *context,
program->setShader(gl::ShaderType::Compute, fsCsShader);
ANGLE_TRY(program->getComputePipeline(context, pipelineLayout.get(), &pipelineAndSerial));
pipelineAndSerial->updateSerial(serial);
commandBuffer->bindPipeline(bindPoint, pipelineAndSerial->get());
commandBuffer->bindComputePipeline(pipelineAndSerial->get());
}
else
{
......@@ -350,7 +350,7 @@ angle::Result UtilsVk::setupProgram(vk::Context *context,
context, &renderer->getRenderPassCache(), renderer->getPipelineCache(), serial,
pipelineLayout.get(), *pipelineDesc, gl::AttributesMask(), &descPtr, &helper));
helper->updateSerial(serial);
commandBuffer->bindPipeline(bindPoint, helper->getPipeline());
commandBuffer->bindGraphicsPipeline(helper->getPipeline());
}
if (descriptorSet != VK_NULL_HANDLE)
......@@ -657,9 +657,7 @@ angle::Result UtilsVk::clearImage(ContextVk *contextVk,
ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
&mImageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
sizeof(shaderParams), commandBuffer));
commandBuffer->draw(6, 1, 0, 0);
commandBuffer->draw(6, 0);
return angle::Result::Continue;
}
......@@ -783,9 +781,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk,
ANGLE_TRY(setupProgram(contextVk, Function::ImageCopy, fragmentShader, vertexShader,
&mImageCopyPrograms[flags], &pipelineDesc, descriptorSet, &shaderParams,
sizeof(shaderParams), commandBuffer));
commandBuffer->draw(6, 1, 0, 0);
commandBuffer->draw(6, 0);
descriptorPoolBinding.reset();
return angle::Result::Continue;
......
......@@ -1064,7 +1064,7 @@ void LineLoopHelper::Draw(uint32_t count, CommandBufferT *commandBuffer)
{
// Our first index is always 0 because that's how we set it up in createIndexBuffer*.
// Note: this could theoretically overflow and wrap to zero.
commandBuffer->drawIndexed(count + 1, 1, 0, 0, 0);
commandBuffer->drawIndexed(count + 1);
}
// BufferHelper implementation.
......@@ -1603,10 +1603,9 @@ void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
imageMemoryBarrier.subresourceRange.layerCount = mLayerCount;
commandBuffer->pipelineBarrier(transitionFrom.srcStageMask, transitionTo.dstStageMask, 0, 0,
nullptr, 0, nullptr, 1, &imageMemoryBarrier);
mCurrentLayout = newLayout;
commandBuffer->imageBarrier(transitionFrom.srcStageMask, transitionTo.dstStageMask,
&imageMemoryBarrier);
mCurrentLayout = newLayout;
mCurrentQueueFamilyIndex = newQueueFamilyIndex;
}
......@@ -1614,7 +1613,6 @@ void ImageHelper::clearColor(const VkClearColorValue &color,
uint32_t baseMipLevel,
uint32_t levelCount,
CommandBufferT *commandBuffer)
{
clearColorLayer(color, baseMipLevel, levelCount, 0, mLayerCount, commandBuffer);
}
......@@ -1738,10 +1736,8 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, GLuint
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
// We can do it for all layers at once.
commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1,
&barrier);
commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
&barrier);
VkImageBlit blit = {};
blit.srcOffsets[0] = {0, 0, 0};
blit.srcOffsets[1] = {mipWidth, mipHeight, 1};
......@@ -1770,9 +1766,8 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, GLuint
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
// We can do it for all layers at once.
commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
0, 0, nullptr, 0, nullptr, 1, &barrier);
commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
&barrier);
// This is just changing the internal state of the image helper so that the next call
// to changeLayout will use this layout as the "oldLayout" argument.
mCurrentLayout = ImageLayout::TransferSrc;
......
......@@ -626,6 +626,7 @@ class ImageHelper final : public CommandGraphResource
VkImageAspectFlags clearAspectFlags,
const VkClearDepthStencilValue &depthStencil,
CommandBufferT *commandBuffer);
gl::Extents getSize(const gl::ImageIndex &index) const;
static void Copy(ImageHelper *srcImage,
......
......@@ -180,7 +180,9 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
const VkBufferMemoryBarrier *bufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier *imageMemoryBarriers);
void imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkImageMemoryBarrier *imageMemoryBarrier);
void clearColorImage(const Image &image,
VkImageLayout imageLayout,
const VkClearColorValue &color,
......@@ -226,16 +228,21 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance);
void draw(uint32_t vertexCount, uint32_t firstVertex);
void drawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex);
void drawIndexed(uint32_t indexCount,
uint32_t instanceCount,
uint32_t firstIndex,
int32_t vertexOffset,
uint32_t firstInstance);
void drawIndexed(uint32_t indexCount);
void drawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount);
void dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const Pipeline &pipeline);
void bindGraphicsPipeline(const Pipeline &pipeline);
void bindComputePipeline(const Pipeline &pipeline);
void bindVertexBuffers(uint32_t firstBinding,
uint32_t bindingCount,
......@@ -573,6 +580,15 @@ ANGLE_INLINE void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMa
imageMemoryBarrierCount, imageMemoryBarriers);
}
ANGLE_INLINE void CommandBuffer::imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkImageMemoryBarrier *imageMemoryBarrier)
{
ASSERT(valid());
vkCmdPipelineBarrier(mHandle, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1,
imageMemoryBarrier);
}
ANGLE_INLINE void CommandBuffer::destroy(VkDevice device)
{
releaseHandle();
......@@ -808,6 +824,20 @@ ANGLE_INLINE void CommandBuffer::draw(uint32_t vertexCount,
vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, firstInstance);
}
ANGLE_INLINE void CommandBuffer::draw(uint32_t vertexCount, uint32_t firstVertex)
{
ASSERT(valid());
vkCmdDraw(mHandle, vertexCount, 1, firstVertex, 0);
}
ANGLE_INLINE void CommandBuffer::drawInstanced(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex)
{
ASSERT(valid());
vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, 0);
}
ANGLE_INLINE void CommandBuffer::drawIndexed(uint32_t indexCount,
uint32_t instanceCount,
uint32_t firstIndex,
......@@ -818,6 +848,18 @@ ANGLE_INLINE void CommandBuffer::drawIndexed(uint32_t indexCount,
vkCmdDrawIndexed(mHandle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
}
ANGLE_INLINE void CommandBuffer::drawIndexed(uint32_t indexCount)
{
ASSERT(valid());
vkCmdDrawIndexed(mHandle, indexCount, 1, 0, 0, 0);
}
ANGLE_INLINE void CommandBuffer::drawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount)
{
ASSERT(valid());
vkCmdDrawIndexed(mHandle, indexCount, instanceCount, 0, 0, 0);
}
ANGLE_INLINE void CommandBuffer::dispatch(uint32_t groupCountX,
uint32_t groupCountY,
uint32_t groupCountZ)
......@@ -833,6 +875,18 @@ ANGLE_INLINE void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPo
vkCmdBindPipeline(mHandle, pipelineBindPoint, pipeline.getHandle());
}
ANGLE_INLINE void CommandBuffer::bindGraphicsPipeline(const Pipeline &pipeline)
{
ASSERT(valid() && pipeline.valid());
vkCmdBindPipeline(mHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getHandle());
}
ANGLE_INLINE void CommandBuffer::bindComputePipeline(const Pipeline &pipeline)
{
ASSERT(valid() && pipeline.valid());
vkCmdBindPipeline(mHandle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.getHandle());
}
ANGLE_INLINE void CommandBuffer::bindVertexBuffers(uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer *buffers,
......
......@@ -1404,6 +1404,8 @@ TEST_P(SimpleStateChangeTest, RedefineBufferInUse)
// Tests updating a buffer's contents while in use, without redefining it.
TEST_P(SimpleStateChangeTest, UpdateBufferInUse)
{
// tobine: Started failing w/ custom cmd buffers. http://anglebug.com/3255
ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsVulkan());
std::vector<GLColor> redColorData(6, GLColor::red);
GLBuffer buffer;
......
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