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() { ...@@ -86,7 +86,7 @@ declare_args() {
angle_vulkan_conformant_configs_only = is_official_build angle_vulkan_conformant_configs_only = is_official_build
# Enable custom (cpu-side) secondary command buffers # 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 @@ ...@@ -15,6 +15,7 @@
#include "common/angleutils.h" #include "common/angleutils.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/mathutil.h"
#include "common/platform.h" #include "common/platform.h"
#include "common/tls.h" #include "common/tls.h"
...@@ -36,43 +37,48 @@ PoolAllocator::PoolAllocator(int growthIncrement, int allocationAlignment) ...@@ -36,43 +37,48 @@ PoolAllocator::PoolAllocator(int growthIncrement, int allocationAlignment)
#endif #endif
mLocked(false) mLocked(false)
{ {
// if (mAlignment == 1)
// Adjust mAlignment to be at least pointer aligned and {
// power of 2. // This is a special fast-path where fastAllocation() is enabled
// mAlignmentMask = 0;
size_t minAlign = sizeof(void *); mHeaderSkip = sizeof(Header);
mAlignment &= ~(minAlign - 1); }
if (mAlignment < minAlign) else
mAlignment = minAlign; {
size_t a = 1; //
while (a < mAlignment) // Adjust mAlignment to be at least pointer aligned and
a <<= 1; // power of 2.
mAlignment = a; //
mAlignmentMask = a - 1; 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) #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 // Don't allow page sizes we know are smaller than all common
// OS page sizes. // OS page sizes.
// //
if (mPageSize < 4 * 1024) if (mPageSize < 4 * 1024)
mPageSize = 4 * 1024; mPageSize = 4 * 1024;
// //
// A large mCurrentPageOffset indicates a new page needs to // A large mCurrentPageOffset indicates a new page needs to
// be obtained to allocate memory. // be obtained to allocate memory.
// //
mCurrentPageOffset = mPageSize; mCurrentPageOffset = mPageSize;
//
// Align header skip
//
mHeaderSkip = minAlign;
if (mHeaderSkip < sizeof(Header))
{
mHeaderSkip = (sizeof(Header) + mAlignmentMask) & ~mAlignmentMask;
}
#else // !defined(ANGLE_DISABLE_POOL_ALLOC) #else // !defined(ANGLE_DISABLE_POOL_ALLOC)
}
mStack.push_back({}); mStack.push_back({});
#endif #endif
} }
...@@ -262,7 +268,21 @@ void *PoolAllocator::allocate(size_t numBytes) ...@@ -262,7 +268,21 @@ void *PoolAllocator::allocate(size_t numBytes)
reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(memory) + mHeaderSkip); reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(memory) + mHeaderSkip);
return std::align(mAlignment, numBytes, unalignedPtr, allocationSize); 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. // Need a simple page to allocate from.
// //
...@@ -278,22 +298,13 @@ void *PoolAllocator::allocate(size_t numBytes) ...@@ -278,22 +298,13 @@ void *PoolAllocator::allocate(size_t numBytes)
if (memory == 0) if (memory == 0)
return 0; return 0;
} }
// Use placement-new to initialize header // Use placement-new to initialize header
new (memory) Header(mInUseList, 1); new (memory) Header(mInUseList, 1);
mInUseList = memory; mInUseList = memory;
unsigned char *ret = reinterpret_cast<unsigned char *>(mInUseList) + mHeaderSkip; unsigned char *ret = reinterpret_cast<unsigned char *>(mInUseList) + mHeaderSkip;
mCurrentPageOffset = (mHeaderSkip + allocationSize + mAlignmentMask) & ~mAlignmentMask; mCurrentPageOffset = (mHeaderSkip + allocationSize + mAlignmentMask) & ~mAlignmentMask;
return initializeAllocation(mInUseList, ret, numBytes); return ret;
#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
} }
void PoolAllocator::lock() void PoolAllocator::lock()
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <vector> #include <vector>
#include "angleutils.h" #include "angleutils.h"
#include "common/debug.h"
namespace angle namespace angle
{ {
...@@ -123,6 +124,10 @@ class PoolAllocator : angle::NonCopyable ...@@ -123,6 +124,10 @@ class PoolAllocator : angle::NonCopyable
{ {
public: public:
static const int kDefaultAlignment = 16; 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); PoolAllocator(int growthIncrement = 8 * 1024, int allocationAlignment = kDefaultAlignment);
// //
...@@ -154,6 +159,32 @@ class PoolAllocator : angle::NonCopyable ...@@ -154,6 +159,32 @@ class PoolAllocator : angle::NonCopyable
void *allocate(size_t numBytes); 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 // There is no deallocate. The point of this class is that
// deallocation can be skipped by the user of it, as the model // deallocation can be skipped by the user of it, as the model
// of use is to simultaneously deallocate everything at once // of use is to simultaneously deallocate everything at once
...@@ -205,6 +236,8 @@ class PoolAllocator : angle::NonCopyable ...@@ -205,6 +236,8 @@ class PoolAllocator : angle::NonCopyable
}; };
using AllocStack = std::vector<AllocState>; 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 // Track allocations if and only if we're using guard blocks
void *initializeAllocation(Header *block, unsigned char *memory, size_t numBytes) void *initializeAllocation(Header *block, unsigned char *memory, size_t numBytes)
{ {
......
...@@ -139,10 +139,9 @@ void MakeDebugUtilsLabel(GLenum source, const char *marker, VkDebugUtilsLabelEXT ...@@ -139,10 +139,9 @@ void MakeDebugUtilsLabel(GLenum source, const char *marker, VkDebugUtilsLabelEXT
} }
#if ANGLE_USE_CUSTOM_VULKAN_CMD_BUFFERS #if ANGLE_USE_CUSTOM_VULKAN_CMD_BUFFERS
static constexpr VkSubpassContents kRenderPassContents = VK_SUBPASS_CONTENTS_INLINE; constexpr VkSubpassContents kRenderPassContents = VK_SUBPASS_CONTENTS_INLINE;
#else #else
static constexpr VkSubpassContents kRenderPassContents = constexpr VkSubpassContents kRenderPassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
#endif #endif
// Helpers to unify executeCommands call based on underlying cmd buffer type // Helpers to unify executeCommands call based on underlying cmd buffer type
...@@ -303,7 +302,6 @@ CommandGraphNode::CommandGraphNode(CommandGraphNodeFunction function, ...@@ -303,7 +302,6 @@ CommandGraphNode::CommandGraphNode(CommandGraphNodeFunction function,
CommandGraphNode::~CommandGraphNode() CommandGraphNode::~CommandGraphNode()
{ {
mRenderPassFramebuffer.setHandle(VK_NULL_HANDLE); mRenderPassFramebuffer.setHandle(VK_NULL_HANDLE);
// Command buffers are managed by the command pool, so don't need to be freed. // Command buffers are managed by the command pool, so don't need to be freed.
mOutsideRenderPassCommands.releaseHandle(); mOutsideRenderPassCommands.releaseHandle();
mInsideRenderPassCommands.releaseHandle(); mInsideRenderPassCommands.releaseHandle();
...@@ -503,7 +501,6 @@ angle::Result CommandGraphNode::visitAndExecute(vk::Context *context, ...@@ -503,7 +501,6 @@ angle::Result CommandGraphNode::visitAndExecute(vk::Context *context,
RenderPass *renderPass = nullptr; RenderPass *renderPass = nullptr;
ANGLE_TRY(renderPassCache->getCompatibleRenderPass(context, serial, mRenderPassDesc, ANGLE_TRY(renderPassCache->getCompatibleRenderPass(context, serial, mRenderPassDesc,
&renderPass)); &renderPass));
ANGLE_VK_TRY(context, mInsideRenderPassCommands.end()); ANGLE_VK_TRY(context, mInsideRenderPassCommands.end());
VkRenderPassBeginInfo beginInfo = {}; VkRenderPassBeginInfo beginInfo = {};
...@@ -634,7 +631,10 @@ CommandGraph::CommandGraph(bool enableGraphDiagnostics, angle::PoolAllocator *po ...@@ -634,7 +631,10 @@ CommandGraph::CommandGraph(bool enableGraphDiagnostics, angle::PoolAllocator *po
: mEnableGraphDiagnostics(enableGraphDiagnostics), : mEnableGraphDiagnostics(enableGraphDiagnostics),
mPoolAllocator(poolAllocator), mPoolAllocator(poolAllocator),
mLastBarrierIndex(kInvalidNodeIndex) mLastBarrierIndex(kInvalidNodeIndex)
{} {
// Push so that allocations made from here will be recycled in clear() below.
mPoolAllocator->push();
}
CommandGraph::~CommandGraph() CommandGraph::~CommandGraph()
{ {
...@@ -776,6 +776,12 @@ bool CommandGraph::empty() const ...@@ -776,6 +776,12 @@ bool CommandGraph::empty() const
void CommandGraph::clear() void CommandGraph::clear()
{ {
mLastBarrierIndex = kInvalidNodeIndex; 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 // TODO(jmadill): Use pool allocator for performance. http://anglebug.com/2951
for (CommandGraphNode *node : mNodes) for (CommandGraphNode *node : mNodes)
......
...@@ -24,6 +24,7 @@ namespace rx ...@@ -24,6 +24,7 @@ namespace rx
namespace vk namespace vk
{ {
enum class VisitedState enum class VisitedState
{ {
Unvisited, Unvisited,
...@@ -119,9 +120,11 @@ class CommandGraphNode final : angle::NonCopyable ...@@ -119,9 +120,11 @@ class CommandGraphNode final : angle::NonCopyable
static void SetHappensBeforeDependencies(CommandGraphNode **beforeNodes, static void SetHappensBeforeDependencies(CommandGraphNode **beforeNodes,
size_t beforeNodesCount, size_t beforeNodesCount,
CommandGraphNode *afterNode); CommandGraphNode *afterNode);
static void SetHappensBeforeDependencies(CommandGraphNode *beforeNode, static void SetHappensBeforeDependencies(CommandGraphNode *beforeNode,
CommandGraphNode **afterNodes, CommandGraphNode **afterNodes,
size_t afterNodesCount); size_t afterNodesCount);
bool hasParents() const; bool hasParents() const;
bool hasChildren() const { return mHasChildren; } bool hasChildren() const { return mHasChildren; }
......
...@@ -369,9 +369,7 @@ angle::Result ContextVk::handleDirtyPipeline(const gl::Context *context, ...@@ -369,9 +369,7 @@ angle::Result ContextVk::handleDirtyPipeline(const gl::Context *context,
mGraphicsPipelineTransition.reset(); mGraphicsPipelineTransition.reset();
} }
commandBuffer->bindGraphicsPipeline(mCurrentPipeline->getPipeline());
commandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline->getPipeline());
// Update the queue serial for the pipeline object. // Update the queue serial for the pipeline object.
ASSERT(mCurrentPipeline && mCurrentPipeline->valid()); ASSERT(mCurrentPipeline && mCurrentPipeline->valid());
mCurrentPipeline->updateSerial(mRenderer->getCurrentQueueSerial()); mCurrentPipeline->updateSerial(mRenderer->getCurrentQueueSerial());
...@@ -449,8 +447,8 @@ angle::Result ContextVk::drawArrays(const gl::Context *context, ...@@ -449,8 +447,8 @@ angle::Result ContextVk::drawArrays(const gl::Context *context,
GLint first, GLint first,
GLsizei count) GLsizei count)
{ {
CommandBufferT *commandBuffer = nullptr; CommandBufferT *commandBuffer = nullptr;
uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count); uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
if (mode == gl::PrimitiveMode::LineLoop) if (mode == gl::PrimitiveMode::LineLoop)
{ {
...@@ -462,7 +460,7 @@ angle::Result ContextVk::drawArrays(const gl::Context *context, ...@@ -462,7 +460,7 @@ angle::Result ContextVk::drawArrays(const gl::Context *context,
{ {
ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum, ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer)); nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->draw(clampedVertexCount, 1, first, 0); commandBuffer->draw(clampedVertexCount, first);
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -484,7 +482,7 @@ angle::Result ContextVk::drawArraysInstanced(const gl::Context *context, ...@@ -484,7 +482,7 @@ angle::Result ContextVk::drawArraysInstanced(const gl::Context *context,
CommandBufferT *commandBuffer = nullptr; CommandBufferT *commandBuffer = nullptr;
ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum, ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer)); 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; return angle::Result::Continue;
} }
...@@ -503,7 +501,7 @@ angle::Result ContextVk::drawElements(const gl::Context *context, ...@@ -503,7 +501,7 @@ angle::Result ContextVk::drawElements(const gl::Context *context,
else else
{ {
ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer)); ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer));
commandBuffer->drawIndexed(count, 1, 0, 0, 0); commandBuffer->drawIndexed(count);
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -525,7 +523,7 @@ angle::Result ContextVk::drawElementsInstanced(const gl::Context *context, ...@@ -525,7 +523,7 @@ angle::Result ContextVk::drawElementsInstanced(const gl::Context *context,
CommandBufferT *commandBuffer = nullptr; CommandBufferT *commandBuffer = nullptr;
ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer)); 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; return angle::Result::Continue;
} }
......
...@@ -424,7 +424,7 @@ angle::Result FramebufferVk::blitWithCopy(ContextVk *contextVk, ...@@ -424,7 +424,7 @@ angle::Result FramebufferVk::blitWithCopy(ContextVk *contextVk,
VkImageAspectFlags aspectMask = VkImageAspectFlags aspectMask =
vk::GetDepthStencilAspectFlagsForCopy(blitDepthBuffer, blitStencilBuffer); vk::GetDepthStencilAspectFlagsForCopy(blitDepthBuffer, blitStencilBuffer);
CommandBufferT *commandBuffer; CommandBufferT *commandBuffer = nullptr;
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
vk::ImageHelper *writeImage = drawRenderTarget->getImageForWrite(&mFramebuffer); vk::ImageHelper *writeImage = drawRenderTarget->getImageForWrite(&mFramebuffer);
...@@ -509,7 +509,7 @@ angle::Result FramebufferVk::blitWithReadback(ContextVk *contextVk, ...@@ -509,7 +509,7 @@ angle::Result FramebufferVk::blitWithReadback(ContextVk *contextVk,
// Reinitialize the commandBuffer after a read pixels because it calls // Reinitialize the commandBuffer after a read pixels because it calls
// renderer->finish which makes command buffers obsolete. // renderer->finish which makes command buffers obsolete.
CommandBufferT *commandBuffer; CommandBufferT *commandBuffer = nullptr;
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
// We read the bytes of the image in a buffer, now we have to copy them into the // 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, ...@@ -669,7 +669,7 @@ angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
vk::ImageHelper *dstImage = drawRenderTarget->getImageForWrite(&mFramebuffer); vk::ImageHelper *dstImage = drawRenderTarget->getImageForWrite(&mFramebuffer);
CommandBufferT *commandBuffer; CommandBufferT *commandBuffer = nullptr;
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
const vk::Format &readImageFormat = readRenderTarget->getImageFormat(); const vk::Format &readImageFormat = readRenderTarget->getImageFormat();
...@@ -903,8 +903,8 @@ angle::Result FramebufferVk::clearWithClearAttachments( ...@@ -903,8 +903,8 @@ angle::Result FramebufferVk::clearWithClearAttachments(
// This command can only happen inside a render pass, so obtain one if its already happening // This command can only happen inside a render pass, so obtain one if its already happening
// or create a new one if not. // or create a new one if not.
CommandBufferT *commandBuffer = nullptr; CommandBufferT *commandBuffer = nullptr;
vk::RecordingMode mode = vk::RecordingMode::Start; vk::RecordingMode mode = vk::RecordingMode::Start;
ANGLE_TRY(getCommandBufferForDraw(contextVk, &commandBuffer, &mode)); 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. // 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() ...@@ -506,7 +506,7 @@ RendererVk::RendererVk()
mCurrentQueueSerial(mQueueSerialFactory.generate()), mCurrentQueueSerial(mQueueSerialFactory.generate()),
mDeviceLost(false), mDeviceLost(false),
mPipelineCacheVkUpdateTimeout(kPipelineCacheVkUpdatePeriod), mPipelineCacheVkUpdateTimeout(kPipelineCacheVkUpdatePeriod),
mPoolAllocator(kDefaultPoolAllocatorPageSize), mPoolAllocator(kDefaultPoolAllocatorPageSize, 1),
mCommandGraph(kEnableCommandGraphDiagnostics, &mPoolAllocator), mCommandGraph(kEnableCommandGraphDiagnostics, &mPoolAllocator),
mGpuEventsEnabled(false), mGpuEventsEnabled(false),
mGpuClockSync{std::numeric_limits<double>::max(), std::numeric_limits<double>::max()}, mGpuClockSync{std::numeric_limits<double>::max(), std::numeric_limits<double>::max()},
......
...@@ -14,102 +14,6 @@ namespace rx ...@@ -14,102 +14,6 @@ namespace rx
{ {
namespace vk namespace vk
{ {
// Allocate/initialize memory for the command and return pointer to Cmd Header
template <class StructType>
StructType *SecondaryCommandBuffer::initCommand(CommandID cmdID, size_t variableSize)
{
size_t paramSize = sizeof(StructType);
size_t completeSize = sizeof(CommandHeader) + paramSize + variableSize;
CommandHeader *header = static_cast<CommandHeader *>(mAllocator->allocate(completeSize));
// Update cmd ID in header
header->id = cmdID;
header->next = nullptr;
// Update mHead ptr
mHead = (mHead == nullptr) ? header : mHead;
// Update prev cmd's "next" ptr and mLast ptr
if (mLast)
{
mLast->next = header;
}
// Update mLast ptr
mLast = header;
uint8_t *fixedParamPtr = reinterpret_cast<uint8_t *>(header) + sizeof(CommandHeader);
mPtrCmdData = fixedParamPtr + sizeof(StructType);
return reinterpret_cast<StructType *>(fixedParamPtr);
}
template <class PtrType>
void SecondaryCommandBuffer::storePointerParameter(const PtrType *paramData,
const PtrType **writePtr,
size_t sizeInBytes)
{
*writePtr = reinterpret_cast<const PtrType *>(mPtrCmdData);
memcpy(mPtrCmdData, paramData, sizeInBytes);
mPtrCmdData += sizeInBytes;
}
void SecondaryCommandBuffer::bindDescriptorSets(VkPipelineBindPoint bindPoint,
const PipelineLayout &layout,
uint32_t firstSet,
uint32_t descriptorSetCount,
const VkDescriptorSet *descriptorSets,
uint32_t dynamicOffsetCount,
const uint32_t *dynamicOffsets)
{
size_t descSize = descriptorSetCount * sizeof(VkDescriptorSet);
size_t offsetSize = dynamicOffsetCount * sizeof(uint32_t);
size_t varSize = descSize + offsetSize;
BindDescriptorSetParams *paramStruct =
initCommand<BindDescriptorSetParams>(CommandID::BindDescriptorSets, varSize);
// Copy params into memory
paramStruct->bindPoint = bindPoint;
paramStruct->layout = layout.getHandle();
paramStruct->firstSet = firstSet;
paramStruct->descriptorSetCount = descriptorSetCount;
paramStruct->dynamicOffsetCount = dynamicOffsetCount;
// Copy variable sized data
storePointerParameter(descriptorSets, &paramStruct->descriptorSets, descSize);
storePointerParameter(dynamicOffsets, &paramStruct->dynamicOffsets, offsetSize);
}
void SecondaryCommandBuffer::bindIndexBuffer(const Buffer &buffer,
VkDeviceSize offset,
VkIndexType indexType)
{
BindIndexBufferParams *paramStruct =
initCommand<BindIndexBufferParams>(CommandID::BindIndexBuffer, 0);
paramStruct->buffer = buffer.getHandle();
paramStruct->offset = offset;
paramStruct->indexType = indexType;
}
void SecondaryCommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint,
const Pipeline &pipeline)
{
BindPipelineParams *paramStruct = initCommand<BindPipelineParams>(CommandID::BindPipeline, 0);
paramStruct->pipelineBindPoint = pipelineBindPoint;
paramStruct->pipeline = pipeline.getHandle();
}
void SecondaryCommandBuffer::bindVertexBuffers(uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer *buffers,
const VkDeviceSize *offsets)
{
size_t buffSize = bindingCount * sizeof(VkBuffer);
size_t offsetSize = bindingCount * sizeof(VkDeviceSize);
BindVertexBuffersParams *paramStruct =
initCommand<BindVertexBuffersParams>(CommandID::BindVertexBuffers, buffSize + offsetSize);
// Copy params
paramStruct->firstBinding = firstBinding;
paramStruct->bindingCount = bindingCount;
// Copy variable sized data
storePointerParameter(buffers, &paramStruct->buffers, buffSize);
storePointerParameter(offsets, &paramStruct->offsets, offsetSize);
}
void SecondaryCommandBuffer::blitImage(const Image &srcImage, void SecondaryCommandBuffer::blitImage(const Image &srcImage,
VkImageLayout srcImageLayout, VkImageLayout srcImageLayout,
const Image &dstImage, const Image &dstImage,
...@@ -305,37 +209,11 @@ void SecondaryCommandBuffer::setScissor(uint32_t firstScissor, ...@@ -305,37 +209,11 @@ void SecondaryCommandBuffer::setScissor(uint32_t firstScissor,
storePointerParameter(scissors, &paramStruct->scissors, scissorSize); storePointerParameter(scissors, &paramStruct->scissors, scissorSize);
} }
void SecondaryCommandBuffer::draw(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance)
{
DrawParams *paramStruct = initCommand<DrawParams>(CommandID::Draw, 0);
paramStruct->vertexCount = vertexCount;
paramStruct->instanceCount = instanceCount;
paramStruct->firstVertex = firstVertex;
paramStruct->firstInstance = firstInstance;
}
void SecondaryCommandBuffer::drawIndexed(uint32_t indexCount,
uint32_t instanceCount,
uint32_t firstIndex,
int32_t vertexOffset,
uint32_t firstInstance)
{
DrawIndexedParams *paramStruct = initCommand<DrawIndexedParams>(CommandID::DrawIndexed, 0);
paramStruct->indexCount = indexCount;
paramStruct->instanceCount = instanceCount;
paramStruct->firstIndex = firstIndex;
paramStruct->vertexOffset = vertexOffset;
paramStruct->firstInstance = firstInstance;
}
void SecondaryCommandBuffer::dispatch(uint32_t groupCountX, void SecondaryCommandBuffer::dispatch(uint32_t groupCountX,
uint32_t groupCountY, uint32_t groupCountY,
uint32_t groupCountZ) uint32_t groupCountZ)
{ {
DispatchParams *paramStruct = initCommand<DispatchParams>(CommandID::Dispatch, 0); DispatchParams *paramStruct = initCommand<DispatchParams>(CommandID::Dispatch);
paramStruct->groupCountX = groupCountX; paramStruct->groupCountX = groupCountX;
paramStruct->groupCountY = groupCountY; paramStruct->groupCountY = groupCountY;
paramStruct->groupCountZ = groupCountZ; paramStruct->groupCountZ = groupCountZ;
...@@ -355,9 +233,10 @@ void SecondaryCommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask, ...@@ -355,9 +233,10 @@ void SecondaryCommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask,
size_t buffBarrierSize = bufferMemoryBarrierCount * sizeof(VkBufferMemoryBarrier); size_t buffBarrierSize = bufferMemoryBarrierCount * sizeof(VkBufferMemoryBarrier);
size_t imgBarrierSize = imageMemoryBarrierCount * sizeof(VkImageMemoryBarrier); size_t imgBarrierSize = imageMemoryBarrierCount * sizeof(VkImageMemoryBarrier);
PipelineBarrierParams *paramStruct = initCommand<PipelineBarrierParams>( PipelineBarrierParams *paramStruct = initCommand<PipelineBarrierParams>(
CommandID::PipelinBarrier, memBarrierSize + buffBarrierSize + imgBarrierSize); CommandID::PipelineBarrier, memBarrierSize + buffBarrierSize + imgBarrierSize);
paramStruct->srcStageMask = srcStageMask; paramStruct->srcStageMask = srcStageMask;
paramStruct->dstStageMask = dstStageMask; paramStruct->dstStageMask = dstStageMask;
paramStruct->dependencyFlags = dependencyFlags;
paramStruct->memoryBarrierCount = memoryBarrierCount; paramStruct->memoryBarrierCount = memoryBarrierCount;
paramStruct->bufferMemoryBarrierCount = bufferMemoryBarrierCount; paramStruct->bufferMemoryBarrierCount = bufferMemoryBarrierCount;
paramStruct->imageMemoryBarrierCount = imageMemoryBarrierCount; paramStruct->imageMemoryBarrierCount = imageMemoryBarrierCount;
...@@ -368,16 +247,26 @@ void SecondaryCommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask, ...@@ -368,16 +247,26 @@ void SecondaryCommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask,
storePointerParameter(imageMemoryBarriers, &paramStruct->imageMemoryBarriers, imgBarrierSize); storePointerParameter(imageMemoryBarriers, &paramStruct->imageMemoryBarriers, imgBarrierSize);
} }
void SecondaryCommandBuffer::imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkImageMemoryBarrier *imageMemoryBarrier)
{
ImageBarrierParams *paramStruct = initCommand<ImageBarrierParams>(CommandID::ImageBarrier);
paramStruct->srcStageMask = srcStageMask;
paramStruct->dstStageMask = dstStageMask;
paramStruct->imageMemoryBarrier = *imageMemoryBarrier;
}
void SecondaryCommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask) void SecondaryCommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask)
{ {
SetEventParams *paramStruct = initCommand<SetEventParams>(CommandID::SetEvent, 0); SetEventParams *paramStruct = initCommand<SetEventParams>(CommandID::SetEvent);
paramStruct->event = event; paramStruct->event = event;
paramStruct->stageMask = stageMask; paramStruct->stageMask = stageMask;
} }
void SecondaryCommandBuffer::resetEvent(VkEvent event, VkPipelineStageFlags stageMask) void SecondaryCommandBuffer::resetEvent(VkEvent event, VkPipelineStageFlags stageMask)
{ {
ResetEventParams *paramStruct = initCommand<ResetEventParams>(CommandID::ResetEvent, 0); ResetEventParams *paramStruct = initCommand<ResetEventParams>(CommandID::ResetEvent);
paramStruct->event = event; paramStruct->event = event;
paramStruct->stageMask = stageMask; paramStruct->stageMask = stageMask;
} }
...@@ -418,7 +307,7 @@ void SecondaryCommandBuffer::resetQueryPool(VkQueryPool queryPool, ...@@ -418,7 +307,7 @@ void SecondaryCommandBuffer::resetQueryPool(VkQueryPool queryPool,
uint32_t queryCount) uint32_t queryCount)
{ {
ResetQueryPoolParams *paramStruct = ResetQueryPoolParams *paramStruct =
initCommand<ResetQueryPoolParams>(CommandID::ResetQueryPool, 0); initCommand<ResetQueryPoolParams>(CommandID::ResetQueryPool);
paramStruct->queryPool = queryPool; paramStruct->queryPool = queryPool;
paramStruct->firstQuery = firstQuery; paramStruct->firstQuery = firstQuery;
paramStruct->queryCount = queryCount; paramStruct->queryCount = queryCount;
...@@ -428,7 +317,7 @@ void SecondaryCommandBuffer::beginQuery(VkQueryPool queryPool, ...@@ -428,7 +317,7 @@ void SecondaryCommandBuffer::beginQuery(VkQueryPool queryPool,
uint32_t query, uint32_t query,
VkQueryControlFlags flags) VkQueryControlFlags flags)
{ {
BeginQueryParams *paramStruct = initCommand<BeginQueryParams>(CommandID::BeginQuery, 0); BeginQueryParams *paramStruct = initCommand<BeginQueryParams>(CommandID::BeginQuery);
paramStruct->queryPool = queryPool; paramStruct->queryPool = queryPool;
paramStruct->query = query; paramStruct->query = query;
paramStruct->flags = flags; paramStruct->flags = flags;
...@@ -436,7 +325,7 @@ void SecondaryCommandBuffer::beginQuery(VkQueryPool queryPool, ...@@ -436,7 +325,7 @@ void SecondaryCommandBuffer::beginQuery(VkQueryPool queryPool,
void SecondaryCommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query) void SecondaryCommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query)
{ {
EndQueryParams *paramStruct = initCommand<EndQueryParams>(CommandID::EndQuery, 0); EndQueryParams *paramStruct = initCommand<EndQueryParams>(CommandID::EndQuery);
paramStruct->queryPool = queryPool; paramStruct->queryPool = queryPool;
paramStruct->query = query; paramStruct->query = query;
} }
...@@ -446,225 +335,276 @@ void SecondaryCommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStag ...@@ -446,225 +335,276 @@ void SecondaryCommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStag
uint32_t query) uint32_t query)
{ {
WriteTimestampParams *paramStruct = WriteTimestampParams *paramStruct =
initCommand<WriteTimestampParams>(CommandID::WriteTimestamp, 0); initCommand<WriteTimestampParams>(CommandID::WriteTimestamp);
paramStruct->pipelineStage = pipelineStage; paramStruct->pipelineStage = pipelineStage;
paramStruct->queryPool = queryPool; paramStruct->queryPool = queryPool;
paramStruct->query = query; paramStruct->query = query;
} }
ANGLE_INLINE const CommandHeader *NextCommand(const CommandHeader *command)
{
return reinterpret_cast<const CommandHeader *>(reinterpret_cast<const uint8_t *>(command) +
command->size);
}
// Parse the cmds in this cmd buffer into given primary cmd buffer // Parse the cmds in this cmd buffer into given primary cmd buffer
void SecondaryCommandBuffer::executeCommands(VkCommandBuffer cmdBuffer) void SecondaryCommandBuffer::executeCommands(VkCommandBuffer cmdBuffer)
{ {
for (CommandHeader *currentCommand = mHead; currentCommand; for (const CommandHeader *command : mCommands)
currentCommand = currentCommand->next)
{ {
switch (currentCommand->id) for (const CommandHeader *currentCommand = command;
currentCommand->id != CommandID::Invalid; currentCommand = NextCommand(currentCommand))
{ {
case CommandID::BindDescriptorSets: switch (currentCommand->id)
{
BindDescriptorSetParams *params =
getParamPtr<BindDescriptorSetParams>(currentCommand);
vkCmdBindDescriptorSets(cmdBuffer, params->bindPoint, params->layout,
params->firstSet, params->descriptorSetCount,
params->descriptorSets, params->dynamicOffsetCount,
params->dynamicOffsets);
break;
}
case CommandID::BindIndexBuffer:
{
BindIndexBufferParams *params = getParamPtr<BindIndexBufferParams>(currentCommand);
vkCmdBindIndexBuffer(cmdBuffer, params->buffer, params->offset, params->indexType);
break;
}
case CommandID::BindPipeline:
{
BindPipelineParams *params = getParamPtr<BindPipelineParams>(currentCommand);
vkCmdBindPipeline(cmdBuffer, params->pipelineBindPoint, params->pipeline);
break;
}
case CommandID::BindVertexBuffers:
{
BindVertexBuffersParams *params =
getParamPtr<BindVertexBuffersParams>(currentCommand);
vkCmdBindVertexBuffers(cmdBuffer, params->firstBinding, params->bindingCount,
params->buffers, params->offsets);
break;
}
case CommandID::BlitImage:
{
BlitImageParams *params = getParamPtr<BlitImageParams>(currentCommand);
vkCmdBlitImage(cmdBuffer, params->srcImage, params->srcImageLayout,
params->dstImage, params->dstImageLayout, params->regionCount,
params->pRegions, params->filter);
break;
}
case CommandID::CopyBuffer:
{
CopyBufferParams *params = getParamPtr<CopyBufferParams>(currentCommand);
vkCmdCopyBuffer(cmdBuffer, params->srcBuffer, params->destBuffer,
params->regionCount, params->regions);
break;
}
case CommandID::CopyBufferToImage:
{
CopyBufferToImageParams *params =
getParamPtr<CopyBufferToImageParams>(currentCommand);
vkCmdCopyBufferToImage(cmdBuffer, params->srcBuffer, params->dstImage,
params->dstImageLayout, params->regionCount,
params->regions);
break;
}
case CommandID::CopyImage:
{
CopyImageParams *params = getParamPtr<CopyImageParams>(currentCommand);
vkCmdCopyImage(cmdBuffer, params->srcImage, params->srcImageLayout,
params->dstImage, params->dstImageLayout, params->regionCount,
params->regions);
break;
}
case CommandID::CopyImageToBuffer:
{
CopyImageToBufferParams *params =
getParamPtr<CopyImageToBufferParams>(currentCommand);
vkCmdCopyImageToBuffer(cmdBuffer, params->srcImage, params->srcImageLayout,
params->dstBuffer, params->regionCount, params->regions);
break;
}
case CommandID::ClearAttachments:
{
ClearAttachmentsParams *params =
getParamPtr<ClearAttachmentsParams>(currentCommand);
vkCmdClearAttachments(cmdBuffer, params->attachmentCount, params->attachments,
params->rectCount, params->rects);
break;
}
case CommandID::ClearColorImage:
{
ClearColorImageParams *params = getParamPtr<ClearColorImageParams>(currentCommand);
vkCmdClearColorImage(cmdBuffer, params->image, params->imageLayout, &params->color,
params->rangeCount, params->ranges);
break;
}
case CommandID::ClearDepthStencilImage:
{
ClearDepthStencilImageParams *params =
getParamPtr<ClearDepthStencilImageParams>(currentCommand);
vkCmdClearDepthStencilImage(cmdBuffer, params->image, params->imageLayout,
&params->depthStencil, params->rangeCount,
params->ranges);
break;
}
case CommandID::UpdateBuffer:
{
UpdateBufferParams *params = getParamPtr<UpdateBufferParams>(currentCommand);
vkCmdUpdateBuffer(cmdBuffer, params->buffer, params->dstOffset, params->dataSize,
params->data);
break;
}
case CommandID::PushConstants:
{
PushConstantsParams *params = getParamPtr<PushConstantsParams>(currentCommand);
vkCmdPushConstants(cmdBuffer, params->layout, params->flag, params->offset,
params->size, params->data);
break;
}
case CommandID::SetViewport:
{
SetViewportParams *params = getParamPtr<SetViewportParams>(currentCommand);
vkCmdSetViewport(cmdBuffer, params->firstViewport, params->viewportCount,
params->viewports);
break;
}
case CommandID::SetScissor:
{
SetScissorParams *params = getParamPtr<SetScissorParams>(currentCommand);
vkCmdSetScissor(cmdBuffer, params->firstScissor, params->scissorCount,
params->scissors);
break;
}
case CommandID::Draw:
{
DrawParams *params = getParamPtr<DrawParams>(currentCommand);
vkCmdDraw(cmdBuffer, params->vertexCount, params->instanceCount,
params->firstVertex, params->firstInstance);
break;
}
case CommandID::DrawIndexed:
{
DrawIndexedParams *params = getParamPtr<DrawIndexedParams>(currentCommand);
vkCmdDrawIndexed(cmdBuffer, params->indexCount, params->instanceCount,
params->firstIndex, params->vertexOffset, params->firstInstance);
break;
}
case CommandID::Dispatch:
{
DispatchParams *params = getParamPtr<DispatchParams>(currentCommand);
vkCmdDispatch(cmdBuffer, params->groupCountX, params->groupCountY,
params->groupCountZ);
break;
}
case CommandID::PipelinBarrier:
{
PipelineBarrierParams *params = getParamPtr<PipelineBarrierParams>(currentCommand);
vkCmdPipelineBarrier(cmdBuffer, params->srcStageMask, params->dstStageMask,
params->dependencyFlags, params->memoryBarrierCount,
params->memoryBarriers, params->bufferMemoryBarrierCount,
params->bufferMemoryBarriers, params->imageMemoryBarrierCount,
params->imageMemoryBarriers);
break;
}
case CommandID::SetEvent:
{
SetEventParams *params = getParamPtr<SetEventParams>(currentCommand);
vkCmdSetEvent(cmdBuffer, params->event, params->stageMask);
break;
}
case CommandID::ResetEvent:
{
ResetEventParams *params = getParamPtr<ResetEventParams>(currentCommand);
vkCmdResetEvent(cmdBuffer, params->event, params->stageMask);
break;
}
case CommandID::WaitEvents:
{
WaitEventsParams *params = getParamPtr<WaitEventsParams>(currentCommand);
vkCmdWaitEvents(cmdBuffer, params->eventCount, params->events, params->srcStageMask,
params->dstStageMask, params->memoryBarrierCount,
params->memoryBarriers, params->bufferMemoryBarrierCount,
params->bufferMemoryBarriers, params->imageMemoryBarrierCount,
params->imageMemoryBarriers);
break;
}
case CommandID::ResetQueryPool:
{
ResetQueryPoolParams *params = getParamPtr<ResetQueryPoolParams>(currentCommand);
vkCmdResetQueryPool(cmdBuffer, params->queryPool, params->firstQuery,
params->queryCount);
break;
}
case CommandID::BeginQuery:
{
BeginQueryParams *params = getParamPtr<BeginQueryParams>(currentCommand);
vkCmdBeginQuery(cmdBuffer, params->queryPool, params->query, params->flags);
break;
}
case CommandID::EndQuery:
{
EndQueryParams *params = getParamPtr<EndQueryParams>(currentCommand);
vkCmdEndQuery(cmdBuffer, params->queryPool, params->query);
break;
}
case CommandID::WriteTimestamp:
{
WriteTimestampParams *params = getParamPtr<WriteTimestampParams>(currentCommand);
vkCmdWriteTimestamp(cmdBuffer, params->pipelineStage, params->queryPool,
params->query);
break;
}
default:
{ {
UNREACHABLE(); case CommandID::BeginQuery:
break; {
const BeginQueryParams *params = getParamPtr<BeginQueryParams>(currentCommand);
vkCmdBeginQuery(cmdBuffer, params->queryPool, params->query, params->flags);
break;
}
case CommandID::BindComputePipeline:
{
const BindPipelineParams *params =
getParamPtr<BindPipelineParams>(currentCommand);
vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, params->pipeline);
break;
}
case CommandID::BindDescriptorSets:
{
const BindDescriptorSetParams *params =
getParamPtr<BindDescriptorSetParams>(currentCommand);
vkCmdBindDescriptorSets(cmdBuffer, params->bindPoint, params->layout,
params->firstSet, params->descriptorSetCount,
params->descriptorSets, params->dynamicOffsetCount,
params->dynamicOffsets);
break;
}
case CommandID::BindGraphicsPipeline:
{
const BindPipelineParams *params =
getParamPtr<BindPipelineParams>(currentCommand);
vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, params->pipeline);
break;
}
case CommandID::BindIndexBuffer:
{
const BindIndexBufferParams *params =
getParamPtr<BindIndexBufferParams>(currentCommand);
vkCmdBindIndexBuffer(cmdBuffer, params->buffer, params->offset,
params->indexType);
break;
}
case CommandID::BindVertexBuffers:
{
const BindVertexBuffersParams *params =
getParamPtr<BindVertexBuffersParams>(currentCommand);
const VkBuffer *buffers =
Offset<VkBuffer>(params, sizeof(BindVertexBuffersParams));
const VkDeviceSize *offsets =
Offset<VkDeviceSize>(buffers, sizeof(VkBuffer) * params->bindingCount);
vkCmdBindVertexBuffers(cmdBuffer, 0, params->bindingCount, buffers, offsets);
break;
}
case CommandID::BlitImage:
{
const BlitImageParams *params = getParamPtr<BlitImageParams>(currentCommand);
vkCmdBlitImage(cmdBuffer, params->srcImage, params->srcImageLayout,
params->dstImage, params->dstImageLayout, params->regionCount,
params->pRegions, params->filter);
break;
}
case CommandID::ClearAttachments:
{
const ClearAttachmentsParams *params =
getParamPtr<ClearAttachmentsParams>(currentCommand);
vkCmdClearAttachments(cmdBuffer, params->attachmentCount, params->attachments,
params->rectCount, params->rects);
break;
}
case CommandID::ClearColorImage:
{
const ClearColorImageParams *params =
getParamPtr<ClearColorImageParams>(currentCommand);
vkCmdClearColorImage(cmdBuffer, params->image, params->imageLayout,
&params->color, params->rangeCount, params->ranges);
break;
}
case CommandID::ClearDepthStencilImage:
{
const ClearDepthStencilImageParams *params =
getParamPtr<ClearDepthStencilImageParams>(currentCommand);
vkCmdClearDepthStencilImage(cmdBuffer, params->image, params->imageLayout,
&params->depthStencil, params->rangeCount,
params->ranges);
break;
}
case CommandID::CopyBuffer:
{
const CopyBufferParams *params = getParamPtr<CopyBufferParams>(currentCommand);
vkCmdCopyBuffer(cmdBuffer, params->srcBuffer, params->destBuffer,
params->regionCount, params->regions);
break;
}
case CommandID::CopyBufferToImage:
{
const CopyBufferToImageParams *params =
getParamPtr<CopyBufferToImageParams>(currentCommand);
vkCmdCopyBufferToImage(cmdBuffer, params->srcBuffer, params->dstImage,
params->dstImageLayout, params->regionCount,
params->regions);
break;
}
case CommandID::CopyImage:
{
const CopyImageParams *params = getParamPtr<CopyImageParams>(currentCommand);
vkCmdCopyImage(cmdBuffer, params->srcImage, params->srcImageLayout,
params->dstImage, params->dstImageLayout, params->regionCount,
params->regions);
break;
}
case CommandID::CopyImageToBuffer:
{
const CopyImageToBufferParams *params =
getParamPtr<CopyImageToBufferParams>(currentCommand);
vkCmdCopyImageToBuffer(cmdBuffer, params->srcImage, params->srcImageLayout,
params->dstBuffer, params->regionCount, params->regions);
break;
}
case CommandID::Dispatch:
{
const DispatchParams *params = getParamPtr<DispatchParams>(currentCommand);
vkCmdDispatch(cmdBuffer, params->groupCountX, params->groupCountY,
params->groupCountZ);
break;
}
case CommandID::Draw:
{
const DrawParams *params = getParamPtr<DrawParams>(currentCommand);
vkCmdDraw(cmdBuffer, params->vertexCount, 1, params->firstVertex, 0);
break;
}
case CommandID::DrawIndexed:
{
const DrawIndexedParams *params =
getParamPtr<DrawIndexedParams>(currentCommand);
vkCmdDrawIndexed(cmdBuffer, params->indexCount, 1, 0, 0, 0);
break;
}
case CommandID::DrawIndexedInstanced:
{
const DrawIndexedInstancedParams *params =
getParamPtr<DrawIndexedInstancedParams>(currentCommand);
vkCmdDrawIndexed(cmdBuffer, params->indexCount, params->instanceCount, 0, 0, 0);
break;
}
case CommandID::DrawInstanced:
{
const DrawInstancedParams *params =
getParamPtr<DrawInstancedParams>(currentCommand);
vkCmdDraw(cmdBuffer, params->vertexCount, params->instanceCount,
params->firstVertex, 0);
break;
}
case CommandID::EndQuery:
{
const EndQueryParams *params = getParamPtr<EndQueryParams>(currentCommand);
vkCmdEndQuery(cmdBuffer, params->queryPool, params->query);
break;
}
case CommandID::ImageBarrier:
{
const ImageBarrierParams *params =
getParamPtr<ImageBarrierParams>(currentCommand);
vkCmdPipelineBarrier(cmdBuffer, params->srcStageMask, params->dstStageMask, 0,
0, nullptr, 0, nullptr, 1, &params->imageMemoryBarrier);
break;
}
case CommandID::PipelineBarrier:
{
const PipelineBarrierParams *params =
getParamPtr<PipelineBarrierParams>(currentCommand);
vkCmdPipelineBarrier(
cmdBuffer, params->srcStageMask, params->dstStageMask,
params->dependencyFlags, params->memoryBarrierCount, params->memoryBarriers,
params->bufferMemoryBarrierCount, params->bufferMemoryBarriers,
params->imageMemoryBarrierCount, params->imageMemoryBarriers);
break;
}
case CommandID::PushConstants:
{
const PushConstantsParams *params =
getParamPtr<PushConstantsParams>(currentCommand);
vkCmdPushConstants(cmdBuffer, params->layout, params->flag, params->offset,
params->size, params->data);
break;
}
case CommandID::ResetEvent:
{
const ResetEventParams *params = getParamPtr<ResetEventParams>(currentCommand);
vkCmdResetEvent(cmdBuffer, params->event, params->stageMask);
break;
}
case CommandID::ResetQueryPool:
{
const ResetQueryPoolParams *params =
getParamPtr<ResetQueryPoolParams>(currentCommand);
vkCmdResetQueryPool(cmdBuffer, params->queryPool, params->firstQuery,
params->queryCount);
break;
}
case CommandID::SetEvent:
{
const SetEventParams *params = getParamPtr<SetEventParams>(currentCommand);
vkCmdSetEvent(cmdBuffer, params->event, params->stageMask);
break;
}
case CommandID::SetScissor:
{
const SetScissorParams *params = getParamPtr<SetScissorParams>(currentCommand);
vkCmdSetScissor(cmdBuffer, params->firstScissor, params->scissorCount,
params->scissors);
break;
}
case CommandID::SetViewport:
{
const SetViewportParams *params =
getParamPtr<SetViewportParams>(currentCommand);
vkCmdSetViewport(cmdBuffer, params->firstViewport, params->viewportCount,
params->viewports);
break;
}
case CommandID::UpdateBuffer:
{
const UpdateBufferParams *params =
getParamPtr<UpdateBufferParams>(currentCommand);
vkCmdUpdateBuffer(cmdBuffer, params->buffer, params->dstOffset,
params->dataSize, params->data);
break;
}
case CommandID::WaitEvents:
{
const WaitEventsParams *params = getParamPtr<WaitEventsParams>(currentCommand);
vkCmdWaitEvents(cmdBuffer, params->eventCount, params->events,
params->srcStageMask, params->dstStageMask,
params->memoryBarrierCount, params->memoryBarriers,
params->bufferMemoryBarrierCount, params->bufferMemoryBarriers,
params->imageMemoryBarrierCount, params->imageMemoryBarriers);
break;
}
case CommandID::WriteTimestamp:
{
const WriteTimestampParams *params =
getParamPtr<WriteTimestampParams>(currentCommand);
vkCmdWriteTimestamp(cmdBuffer, params->pipelineStage, params->queryPool,
params->query);
break;
}
default:
{
UNREACHABLE();
break;
}
} }
} }
} }
......
...@@ -22,40 +22,46 @@ namespace rx ...@@ -22,40 +22,46 @@ namespace rx
namespace vk namespace vk
{ {
enum class CommandID enum class CommandID : uint16_t
{ {
// State update cmds // Invalid cmd used to mark end of sequence of commands
BindDescriptorSets = 0, Invalid = 0,
BindIndexBuffer = 1, BeginQuery,
BindPipeline = 2, BindComputePipeline,
BindVertexBuffers = 3, BindDescriptorSets,
BlitImage = 4, BindGraphicsPipeline,
CopyBuffer = 5, BindIndexBuffer,
CopyBufferToImage = 6, BindVertexBuffers,
CopyImage = 7, BlitImage,
CopyImageToBuffer = 8, ClearAttachments,
ClearAttachments = 9, ClearColorImage,
ClearColorImage = 10, ClearDepthStencilImage,
ClearDepthStencilImage = 11, CopyBuffer,
UpdateBuffer = 12, CopyBufferToImage,
PushConstants = 13, CopyImage,
SetViewport = 14, CopyImageToBuffer,
SetScissor = 15, Dispatch,
// Draw/dispatch cmds Draw,
Draw = 16, DrawIndexed,
DrawIndexed = 17, DrawIndexedInstanced,
Dispatch = 18, DrawInstanced,
// Sync & Query cmds EndQuery,
PipelinBarrier = 19, ImageBarrier,
ResetEvent = 20, PipelineBarrier,
SetEvent = 21, PushConstants,
WaitEvents = 22, ResetEvent,
ResetQueryPool = 23, ResetQueryPool,
BeginQuery = 24, SetEvent,
EndQuery = 25, SetScissor,
WriteTimestamp = 26, SetViewport,
UpdateBuffer,
WaitEvents,
WriteTimestamp,
}; };
#define VERIFY_4_BYTE_ALIGNMENT(StructName) \
static_assert((sizeof(StructName) % 4) == 0, "Check StructName alignment");
// Structs to encapsulate parameters for different commands // Structs to encapsulate parameters for different commands
// This makes it easy to know the size of params & to copy params // This makes it easy to know the size of params & to copy params
// TODO: Could optimize the size of some of these structs through bit-packing // TODO: Could optimize the size of some of these structs through bit-packing
...@@ -70,6 +76,7 @@ struct BindDescriptorSetParams ...@@ -70,6 +76,7 @@ struct BindDescriptorSetParams
uint32_t dynamicOffsetCount; uint32_t dynamicOffsetCount;
const uint32_t *dynamicOffsets; const uint32_t *dynamicOffsets;
}; };
VERIFY_4_BYTE_ALIGNMENT(BindDescriptorSetParams)
struct BindIndexBufferParams struct BindIndexBufferParams
{ {
...@@ -77,20 +84,20 @@ struct BindIndexBufferParams ...@@ -77,20 +84,20 @@ struct BindIndexBufferParams
VkDeviceSize offset; VkDeviceSize offset;
VkIndexType indexType; VkIndexType indexType;
}; };
VERIFY_4_BYTE_ALIGNMENT(BindIndexBufferParams)
struct BindPipelineParams struct BindPipelineParams
{ {
VkPipelineBindPoint pipelineBindPoint;
VkPipeline pipeline; VkPipeline pipeline;
}; };
VERIFY_4_BYTE_ALIGNMENT(BindPipelineParams)
struct BindVertexBuffersParams struct BindVertexBuffersParams
{ {
uint32_t firstBinding; // ANGLE always has firstBinding of 0 so not storing that currently
uint32_t bindingCount; uint32_t bindingCount;
const VkBuffer *buffers;
const VkDeviceSize *offsets;
}; };
VERIFY_4_BYTE_ALIGNMENT(BindVertexBuffersParams)
struct BlitImageParams struct BlitImageParams
{ {
...@@ -102,6 +109,7 @@ struct BlitImageParams ...@@ -102,6 +109,7 @@ struct BlitImageParams
const VkImageBlit *pRegions; const VkImageBlit *pRegions;
VkFilter filter; VkFilter filter;
}; };
VERIFY_4_BYTE_ALIGNMENT(BlitImageParams)
struct CopyBufferParams struct CopyBufferParams
{ {
...@@ -110,6 +118,7 @@ struct CopyBufferParams ...@@ -110,6 +118,7 @@ struct CopyBufferParams
uint32_t regionCount; uint32_t regionCount;
const VkBufferCopy *regions; const VkBufferCopy *regions;
}; };
VERIFY_4_BYTE_ALIGNMENT(CopyBufferParams)
struct CopyBufferToImageParams struct CopyBufferToImageParams
{ {
...@@ -119,6 +128,7 @@ struct CopyBufferToImageParams ...@@ -119,6 +128,7 @@ struct CopyBufferToImageParams
uint32_t regionCount; uint32_t regionCount;
const VkBufferImageCopy *regions; const VkBufferImageCopy *regions;
}; };
VERIFY_4_BYTE_ALIGNMENT(CopyBufferToImageParams)
struct CopyImageParams struct CopyImageParams
{ {
...@@ -129,6 +139,7 @@ struct CopyImageParams ...@@ -129,6 +139,7 @@ struct CopyImageParams
uint32_t regionCount; uint32_t regionCount;
const VkImageCopy *regions; const VkImageCopy *regions;
}; };
VERIFY_4_BYTE_ALIGNMENT(CopyImageParams)
struct CopyImageToBufferParams struct CopyImageToBufferParams
{ {
...@@ -138,6 +149,7 @@ struct CopyImageToBufferParams ...@@ -138,6 +149,7 @@ struct CopyImageToBufferParams
uint32_t regionCount; uint32_t regionCount;
const VkBufferImageCopy *regions; const VkBufferImageCopy *regions;
}; };
VERIFY_4_BYTE_ALIGNMENT(CopyImageToBufferParams)
struct ClearAttachmentsParams struct ClearAttachmentsParams
{ {
...@@ -146,6 +158,7 @@ struct ClearAttachmentsParams ...@@ -146,6 +158,7 @@ struct ClearAttachmentsParams
uint32_t rectCount; uint32_t rectCount;
const VkClearRect *rects; const VkClearRect *rects;
}; };
VERIFY_4_BYTE_ALIGNMENT(ClearAttachmentsParams)
struct ClearColorImageParams struct ClearColorImageParams
{ {
...@@ -155,6 +168,7 @@ struct ClearColorImageParams ...@@ -155,6 +168,7 @@ struct ClearColorImageParams
uint32_t rangeCount; uint32_t rangeCount;
const VkImageSubresourceRange *ranges; const VkImageSubresourceRange *ranges;
}; };
VERIFY_4_BYTE_ALIGNMENT(ClearColorImageParams)
struct ClearDepthStencilImageParams struct ClearDepthStencilImageParams
{ {
...@@ -164,6 +178,7 @@ struct ClearDepthStencilImageParams ...@@ -164,6 +178,7 @@ struct ClearDepthStencilImageParams
uint32_t rangeCount; uint32_t rangeCount;
const VkImageSubresourceRange *ranges; const VkImageSubresourceRange *ranges;
}; };
VERIFY_4_BYTE_ALIGNMENT(ClearDepthStencilImageParams)
struct UpdateBufferParams struct UpdateBufferParams
{ {
...@@ -172,6 +187,7 @@ struct UpdateBufferParams ...@@ -172,6 +187,7 @@ struct UpdateBufferParams
VkDeviceSize dataSize; VkDeviceSize dataSize;
const void *data; const void *data;
}; };
VERIFY_4_BYTE_ALIGNMENT(UpdateBufferParams)
struct PushConstantsParams struct PushConstantsParams
{ {
...@@ -181,6 +197,7 @@ struct PushConstantsParams ...@@ -181,6 +197,7 @@ struct PushConstantsParams
uint32_t size; uint32_t size;
const void *data; const void *data;
}; };
VERIFY_4_BYTE_ALIGNMENT(PushConstantsParams)
struct SetViewportParams struct SetViewportParams
{ {
...@@ -188,6 +205,7 @@ struct SetViewportParams ...@@ -188,6 +205,7 @@ struct SetViewportParams
uint32_t viewportCount; uint32_t viewportCount;
const VkViewport *viewports; const VkViewport *viewports;
}; };
VERIFY_4_BYTE_ALIGNMENT(SetViewportParams)
struct SetScissorParams struct SetScissorParams
{ {
...@@ -195,23 +213,35 @@ struct SetScissorParams ...@@ -195,23 +213,35 @@ struct SetScissorParams
uint32_t scissorCount; uint32_t scissorCount;
const VkRect2D *scissors; const VkRect2D *scissors;
}; };
VERIFY_4_BYTE_ALIGNMENT(SetScissorParams)
struct DrawParams struct DrawParams
{ {
uint32_t vertexCount; uint32_t vertexCount;
uint32_t firstVertex;
};
VERIFY_4_BYTE_ALIGNMENT(DrawParams)
struct DrawInstancedParams
{
uint32_t vertexCount;
uint32_t instanceCount; uint32_t instanceCount;
uint32_t firstVertex; uint32_t firstVertex;
uint32_t firstInstance;
}; };
VERIFY_4_BYTE_ALIGNMENT(DrawInstancedParams)
struct DrawIndexedParams struct DrawIndexedParams
{ {
uint32_t indexCount; uint32_t indexCount;
};
VERIFY_4_BYTE_ALIGNMENT(DrawIndexedParams)
struct DrawIndexedInstancedParams
{
uint32_t indexCount;
uint32_t instanceCount; uint32_t instanceCount;
uint32_t firstIndex;
int32_t vertexOffset;
uint32_t firstInstance;
}; };
VERIFY_4_BYTE_ALIGNMENT(DrawIndexedInstancedParams)
struct DispatchParams struct DispatchParams
{ {
...@@ -219,6 +249,7 @@ struct DispatchParams ...@@ -219,6 +249,7 @@ struct DispatchParams
uint32_t groupCountY; uint32_t groupCountY;
uint32_t groupCountZ; uint32_t groupCountZ;
}; };
VERIFY_4_BYTE_ALIGNMENT(DispatchParams)
struct PipelineBarrierParams struct PipelineBarrierParams
{ {
...@@ -232,18 +263,29 @@ struct PipelineBarrierParams ...@@ -232,18 +263,29 @@ struct PipelineBarrierParams
uint32_t imageMemoryBarrierCount; uint32_t imageMemoryBarrierCount;
const VkImageMemoryBarrier *imageMemoryBarriers; const VkImageMemoryBarrier *imageMemoryBarriers;
}; };
VERIFY_4_BYTE_ALIGNMENT(PipelineBarrierParams)
struct ImageBarrierParams
{
VkPipelineStageFlags srcStageMask;
VkPipelineStageFlags dstStageMask;
VkImageMemoryBarrier imageMemoryBarrier;
};
VERIFY_4_BYTE_ALIGNMENT(ImageBarrierParams)
struct SetEventParams struct SetEventParams
{ {
VkEvent event; VkEvent event;
VkPipelineStageFlags stageMask; VkPipelineStageFlags stageMask;
}; };
VERIFY_4_BYTE_ALIGNMENT(SetEventParams)
struct ResetEventParams struct ResetEventParams
{ {
VkEvent event; VkEvent event;
VkPipelineStageFlags stageMask; VkPipelineStageFlags stageMask;
}; };
VERIFY_4_BYTE_ALIGNMENT(ResetEventParams)
struct WaitEventsParams struct WaitEventsParams
{ {
...@@ -258,6 +300,7 @@ struct WaitEventsParams ...@@ -258,6 +300,7 @@ struct WaitEventsParams
uint32_t imageMemoryBarrierCount; uint32_t imageMemoryBarrierCount;
const VkImageMemoryBarrier *imageMemoryBarriers; const VkImageMemoryBarrier *imageMemoryBarriers;
}; };
VERIFY_4_BYTE_ALIGNMENT(WaitEventsParams)
struct ResetQueryPoolParams struct ResetQueryPoolParams
{ {
...@@ -265,6 +308,7 @@ struct ResetQueryPoolParams ...@@ -265,6 +308,7 @@ struct ResetQueryPoolParams
uint32_t firstQuery; uint32_t firstQuery;
uint32_t queryCount; uint32_t queryCount;
}; };
VERIFY_4_BYTE_ALIGNMENT(ResetQueryPoolParams)
struct BeginQueryParams struct BeginQueryParams
{ {
...@@ -272,12 +316,14 @@ struct BeginQueryParams ...@@ -272,12 +316,14 @@ struct BeginQueryParams
uint32_t query; uint32_t query;
VkQueryControlFlags flags; VkQueryControlFlags flags;
}; };
VERIFY_4_BYTE_ALIGNMENT(BeginQueryParams)
struct EndQueryParams struct EndQueryParams
{ {
VkQueryPool queryPool; VkQueryPool queryPool;
uint32_t query; uint32_t query;
}; };
VERIFY_4_BYTE_ALIGNMENT(EndQueryParams)
struct WriteTimestampParams struct WriteTimestampParams
{ {
...@@ -285,19 +331,34 @@ struct WriteTimestampParams ...@@ -285,19 +331,34 @@ struct WriteTimestampParams
VkQueryPool queryPool; VkQueryPool queryPool;
uint32_t query; uint32_t query;
}; };
VERIFY_4_BYTE_ALIGNMENT(WriteTimestampParams)
// Header for every cmd in custom cmd buffer // Header for every cmd in custom cmd buffer
struct CommandHeader struct CommandHeader
{ {
CommandID id; CommandID id;
CommandHeader *next; uint16_t size;
}; };
static_assert(sizeof(CommandHeader) == 4, "Check CommandHeader size");
template <typename DestT, typename T>
ANGLE_INLINE DestT *Offset(T *ptr, size_t bytes)
{
return reinterpret_cast<DestT *>((reinterpret_cast<uint8_t *>(ptr) + bytes));
}
template <typename DestT, typename T>
ANGLE_INLINE const DestT *Offset(const T *ptr, size_t bytes)
{
return reinterpret_cast<const DestT *>((reinterpret_cast<const uint8_t *>(ptr) + bytes));
}
class SecondaryCommandBuffer final : angle::NonCopyable class SecondaryCommandBuffer final : angle::NonCopyable
{ {
public: public:
SecondaryCommandBuffer() : mHead(nullptr), mLast(nullptr), mAllocator(nullptr) {} SecondaryCommandBuffer();
~SecondaryCommandBuffer() {} ~SecondaryCommandBuffer();
// Add commands // Add commands
void bindDescriptorSets(VkPipelineBindPoint bindPoint, void bindDescriptorSets(VkPipelineBindPoint bindPoint,
...@@ -310,7 +371,9 @@ class SecondaryCommandBuffer final : angle::NonCopyable ...@@ -310,7 +371,9 @@ class SecondaryCommandBuffer final : angle::NonCopyable
void bindIndexBuffer(const Buffer &buffer, VkDeviceSize offset, VkIndexType indexType); void bindIndexBuffer(const Buffer &buffer, VkDeviceSize offset, VkIndexType indexType);
void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const Pipeline &pipeline); void bindGraphicsPipeline(const Pipeline &pipeline);
void bindComputePipeline(const Pipeline &pipeline);
void bindVertexBuffers(uint32_t firstBinding, void bindVertexBuffers(uint32_t firstBinding,
uint32_t bindingCount, uint32_t bindingCount,
...@@ -380,16 +443,13 @@ class SecondaryCommandBuffer final : angle::NonCopyable ...@@ -380,16 +443,13 @@ class SecondaryCommandBuffer final : angle::NonCopyable
void setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *viewports); void setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *viewports);
void setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *scissors); void setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *scissors);
void draw(uint32_t vertexCount, void draw(uint32_t vertexCount, uint32_t firstVertex);
uint32_t instanceCount,
uint32_t firstVertex, void drawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex);
uint32_t firstInstance);
void drawIndexed(uint32_t indexCount, void drawIndexed(uint32_t indexCount);
uint32_t instanceCount,
uint32_t firstIndex, void drawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount);
int32_t vertexOffset,
uint32_t firstInstance);
void dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ); void dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
...@@ -403,6 +463,10 @@ class SecondaryCommandBuffer final : angle::NonCopyable ...@@ -403,6 +463,10 @@ class SecondaryCommandBuffer final : angle::NonCopyable
uint32_t imageMemoryBarrierCount, uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier *imageMemoryBarriers); const VkImageMemoryBarrier *imageMemoryBarriers);
void imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkImageMemoryBarrier *imageMemoryBarrier);
void setEvent(VkEvent event, VkPipelineStageFlags stageMask); void setEvent(VkEvent event, VkPipelineStageFlags stageMask);
void resetEvent(VkEvent event, VkPipelineStageFlags stageMask); void resetEvent(VkEvent event, VkPipelineStageFlags stageMask);
void waitEvents(uint32_t eventCount, void waitEvents(uint32_t eventCount,
...@@ -427,25 +491,87 @@ class SecondaryCommandBuffer final : angle::NonCopyable ...@@ -427,25 +491,87 @@ class SecondaryCommandBuffer final : angle::NonCopyable
// Parse the cmds in this cmd buffer into given primary cmd buffer for execution // Parse the cmds in this cmd buffer into given primary cmd buffer for execution
void executeCommands(VkCommandBuffer cmdBuffer); void executeCommands(VkCommandBuffer cmdBuffer);
// Pool Alloc uses 16kB pages w/ 16byte header = 16368bytes. To minimize waste
// using a 16368/12 = 1364. Also better perf than 1024 due to fewer block allocations
static constexpr size_t kBlockSize = 1364;
// Make sure block size is 4-byte aligned to avoid Android errors
static_assert((kBlockSize % 4) == 0, "Check kBlockSize alignment");
// Initialize the SecondaryCommandBuffer by setting the allocator it will use // Initialize the SecondaryCommandBuffer by setting the allocator it will use
void initialize(angle::PoolAllocator *allocator) { mAllocator = allocator; } void initialize(angle::PoolAllocator *allocator)
{
ASSERT(allocator);
mAllocator = allocator;
allocateNewBlock();
// Set first command to Invalid to start
reinterpret_cast<CommandHeader *>(mCurrentWritePointer)->id = CommandID::Invalid;
}
// This will cause the SecondaryCommandBuffer to become invalid by clearing its allocator // This will cause the SecondaryCommandBuffer to become invalid by clearing its allocator
void releaseHandle() { mAllocator = nullptr; } void releaseHandle() { mAllocator = nullptr; }
// The SecondaryCommandBuffer is valid if it's been initialized // The SecondaryCommandBuffer is valid if it's been initialized
bool valid() { return mAllocator != nullptr; } bool valid() { return mAllocator != nullptr; }
private: private:
template <class StructType>
ANGLE_INLINE StructType *commonInit(CommandID cmdID, size_t allocationSize)
{
mCurrentBytesRemaining -= allocationSize;
CommandHeader *header = reinterpret_cast<CommandHeader *>(mCurrentWritePointer);
header->id = cmdID;
header->size = static_cast<uint16_t>(allocationSize);
ASSERT(allocationSize <= std::numeric_limits<uint16_t>::max());
mCurrentWritePointer += allocationSize;
// Set next cmd header to Invalid (0) so cmd sequence will be terminated
reinterpret_cast<CommandHeader *>(mCurrentWritePointer)->id = CommandID::Invalid;
return Offset<StructType>(header, sizeof(CommandHeader));
}
ANGLE_INLINE void allocateNewBlock()
{
ASSERT(mAllocator);
mCurrentWritePointer = mAllocator->fastAllocate(kBlockSize);
mCurrentBytesRemaining = kBlockSize;
mCommands.push_back(reinterpret_cast<CommandHeader *>(mCurrentWritePointer));
}
// Allocate and initialize memory for given commandID & variable param size // Allocate and initialize memory for given commandID & variable param size
// returning a pointer to the start of the commands parameter data and updating // returning a pointer to the start of the commands parameter data and updating
// mPtrCmdData to just past the fixed parameter data. // mPtrCmdData to just past the fixed parameter data.
template <class StructType> template <class StructType>
StructType *initCommand(CommandID cmdID, size_t variableSize); ANGLE_INLINE StructType *initCommand(CommandID cmdID, size_t variableSize)
{
constexpr size_t fixedAllocationSize = sizeof(StructType) + sizeof(CommandHeader);
const size_t allocationSize = fixedAllocationSize + variableSize;
// Make sure we have enough room to mark follow-on header "Invalid"
if (mCurrentBytesRemaining <= (allocationSize + sizeof(CommandHeader)))
{
allocateNewBlock();
}
mPtrCmdData = mCurrentWritePointer + fixedAllocationSize;
return commonInit<StructType>(cmdID, allocationSize);
}
// Initialize a command that doesn't have variable-sized ptr data
template <class StructType>
ANGLE_INLINE StructType *initCommand(CommandID cmdID)
{
constexpr size_t allocationSize = sizeof(StructType) + sizeof(CommandHeader);
// Make sure we have enough room to mark follow-on header "Invalid"
if (mCurrentBytesRemaining <= (allocationSize + sizeof(CommandHeader)))
{
allocateNewBlock();
}
return commonInit<StructType>(cmdID, allocationSize);
}
// Return a ptr to the parameter type // Return a ptr to the parameter type
template <class StructType> template <class StructType>
StructType *getParamPtr(CommandHeader *header) const StructType *getParamPtr(const CommandHeader *header) const
{ {
return reinterpret_cast<StructType *>(reinterpret_cast<char *>(header) + return reinterpret_cast<const StructType *>(reinterpret_cast<const uint8_t *>(header) +
sizeof(CommandHeader)); sizeof(CommandHeader));
} }
// Copy sizeInBytes data from paramData to mPtrCmdData and assign *writePtr // Copy sizeInBytes data from paramData to mPtrCmdData and assign *writePtr
// to mPtrCmdData. Then increment mPtrCmdData by sizeInBytes. // to mPtrCmdData. Then increment mPtrCmdData by sizeInBytes.
...@@ -453,18 +579,132 @@ class SecondaryCommandBuffer final : angle::NonCopyable ...@@ -453,18 +579,132 @@ class SecondaryCommandBuffer final : angle::NonCopyable
template <class PtrType> template <class PtrType>
void storePointerParameter(const PtrType *paramData, void storePointerParameter(const PtrType *paramData,
const PtrType **writePtr, const PtrType **writePtr,
size_t sizeInBytes); size_t sizeInBytes)
{
if (sizeInBytes == 0)
return;
*writePtr = reinterpret_cast<const PtrType *>(mPtrCmdData);
memcpy(mPtrCmdData, paramData, sizeInBytes);
mPtrCmdData += sizeInBytes;
}
std::vector<CommandHeader *> mCommands;
// Pointer to start of cmd buffer // Allocator used by this class. If non-null then the class is valid.
CommandHeader *mHead;
// Last command inserted in cmd buffer
CommandHeader *mLast;
angle::PoolAllocator *mAllocator; angle::PoolAllocator *mAllocator;
uint8_t *mCurrentWritePointer;
size_t mCurrentBytesRemaining;
// Ptr to write variable ptr data section of cmd into. // Ptr to write variable ptr data section of cmd into.
// This is set to just past fixed parameter data when initCommand() is called // This is set to just past fixed parameter data when initCommand() is called
uint8_t *mPtrCmdData; uint8_t *mPtrCmdData;
}; };
ANGLE_INLINE SecondaryCommandBuffer::SecondaryCommandBuffer()
: mAllocator(nullptr), mCurrentWritePointer(nullptr), mCurrentBytesRemaining(0)
{}
ANGLE_INLINE SecondaryCommandBuffer::~SecondaryCommandBuffer() {}
ANGLE_INLINE void SecondaryCommandBuffer::bindDescriptorSets(VkPipelineBindPoint bindPoint,
const PipelineLayout &layout,
uint32_t firstSet,
uint32_t descriptorSetCount,
const VkDescriptorSet *descriptorSets,
uint32_t dynamicOffsetCount,
const uint32_t *dynamicOffsets)
{
size_t descSize = descriptorSetCount * sizeof(VkDescriptorSet);
size_t offsetSize = dynamicOffsetCount * sizeof(uint32_t);
size_t varSize = descSize + offsetSize;
BindDescriptorSetParams *paramStruct =
initCommand<BindDescriptorSetParams>(CommandID::BindDescriptorSets, varSize);
// Copy params into memory
paramStruct->bindPoint = bindPoint;
paramStruct->layout = layout.getHandle();
paramStruct->firstSet = firstSet;
paramStruct->descriptorSetCount = descriptorSetCount;
paramStruct->dynamicOffsetCount = dynamicOffsetCount;
// Copy variable sized data
storePointerParameter(descriptorSets, &paramStruct->descriptorSets, descSize);
storePointerParameter(dynamicOffsets, &paramStruct->dynamicOffsets, offsetSize);
}
ANGLE_INLINE void SecondaryCommandBuffer::bindIndexBuffer(const Buffer &buffer,
VkDeviceSize offset,
VkIndexType indexType)
{
BindIndexBufferParams *paramStruct =
initCommand<BindIndexBufferParams>(CommandID::BindIndexBuffer);
paramStruct->buffer = buffer.getHandle();
paramStruct->offset = offset;
paramStruct->indexType = indexType;
}
ANGLE_INLINE void SecondaryCommandBuffer::bindGraphicsPipeline(const Pipeline &pipeline)
{
BindPipelineParams *paramStruct =
initCommand<BindPipelineParams>(CommandID::BindGraphicsPipeline);
paramStruct->pipeline = pipeline.getHandle();
}
ANGLE_INLINE void SecondaryCommandBuffer::bindComputePipeline(const Pipeline &pipeline)
{
BindPipelineParams *paramStruct =
initCommand<BindPipelineParams>(CommandID::BindComputePipeline);
paramStruct->pipeline = pipeline.getHandle();
}
ANGLE_INLINE void SecondaryCommandBuffer::bindVertexBuffers(uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer *buffers,
const VkDeviceSize *offsets)
{
ASSERT(firstBinding == 0);
size_t buffersSize = bindingCount * sizeof(VkBuffer);
size_t offsetsSize = bindingCount * sizeof(VkDeviceSize);
BindVertexBuffersParams *paramStruct = initCommand<BindVertexBuffersParams>(
CommandID::BindVertexBuffers, buffersSize + offsetsSize);
// Copy params
paramStruct->bindingCount = bindingCount;
uint8_t *writePointer = Offset<uint8_t>(paramStruct, sizeof(BindVertexBuffersParams));
memcpy(writePointer, buffers, buffersSize);
writePointer += buffersSize;
memcpy(writePointer, offsets, offsetsSize);
}
ANGLE_INLINE void SecondaryCommandBuffer::draw(uint32_t vertexCount, uint32_t firstVertex)
{
DrawParams *paramStruct = initCommand<DrawParams>(CommandID::Draw);
paramStruct->vertexCount = vertexCount;
paramStruct->firstVertex = firstVertex;
}
ANGLE_INLINE void SecondaryCommandBuffer::drawInstanced(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex)
{
DrawInstancedParams *paramStruct = initCommand<DrawInstancedParams>(CommandID::DrawInstanced);
paramStruct->vertexCount = vertexCount;
paramStruct->instanceCount = instanceCount;
paramStruct->firstVertex = firstVertex;
}
ANGLE_INLINE void SecondaryCommandBuffer::drawIndexed(uint32_t indexCount)
{
DrawIndexedParams *paramStruct = initCommand<DrawIndexedParams>(CommandID::DrawIndexed);
paramStruct->indexCount = indexCount;
}
ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedInstanced(uint32_t indexCount,
uint32_t instanceCount)
{
DrawIndexedInstancedParams *paramStruct =
initCommand<DrawIndexedInstancedParams>(CommandID::DrawIndexedInstanced);
paramStruct->indexCount = indexCount;
paramStruct->instanceCount = instanceCount;
}
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
......
...@@ -503,18 +503,18 @@ angle::Result WindowSurfaceVk::recreateSwapchain(DisplayVk *displayVk, ...@@ -503,18 +503,18 @@ angle::Result WindowSurfaceVk::recreateSwapchain(DisplayVk *displayVk,
swapchainInfo.imageFormat = nativeFormat; swapchainInfo.imageFormat = nativeFormat;
swapchainInfo.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; swapchainInfo.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
// Note: Vulkan doesn't allow 0-width/height swapchains. // Note: Vulkan doesn't allow 0-width/height swapchains.
swapchainInfo.imageExtent.width = std::max(extents.width, 1); swapchainInfo.imageExtent.width = std::max(extents.width, 1);
swapchainInfo.imageExtent.height = std::max(extents.height, 1); swapchainInfo.imageExtent.height = std::max(extents.height, 1);
swapchainInfo.imageArrayLayers = 1; swapchainInfo.imageArrayLayers = 1;
swapchainInfo.imageUsage = kImageUsageFlags; swapchainInfo.imageUsage = kImageUsageFlags;
swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchainInfo.queueFamilyIndexCount = 0; swapchainInfo.queueFamilyIndexCount = 0;
swapchainInfo.pQueueFamilyIndices = nullptr; swapchainInfo.pQueueFamilyIndices = nullptr;
swapchainInfo.preTransform = mPreTransform; swapchainInfo.preTransform = mPreTransform;
swapchainInfo.compositeAlpha = mCompositeAlpha; swapchainInfo.compositeAlpha = mCompositeAlpha;
swapchainInfo.presentMode = mDesiredSwapchainPresentMode; swapchainInfo.presentMode = mDesiredSwapchainPresentMode;
swapchainInfo.clipped = VK_TRUE; swapchainInfo.clipped = VK_TRUE;
swapchainInfo.oldSwapchain = oldSwapchain; swapchainInfo.oldSwapchain = oldSwapchain;
// TODO(syoussefi): Once EGL_SWAP_BEHAVIOR_PRESERVED_BIT is supported, the contents of the old // 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 // swapchain need to carry over to the new one. http://anglebug.com/2942
...@@ -738,7 +738,7 @@ angle::Result WindowSurfaceVk::present(DisplayVk *displayVk, ...@@ -738,7 +738,7 @@ angle::Result WindowSurfaceVk::present(DisplayVk *displayVk,
std::vector<VkRectLayerKHR> vk_rects; std::vector<VkRectLayerKHR> vk_rects;
if (renderer->getFeatures().supportsIncrementalPresent && (n_rects > 0)) if (renderer->getFeatures().supportsIncrementalPresent && (n_rects > 0))
{ {
EGLint *egl_rects = rects; EGLint *egl_rects = rects;
presentRegion.rectangleCount = n_rects; presentRegion.rectangleCount = n_rects;
vk_rects.resize(n_rects); vk_rects.resize(n_rects);
for (EGLint rect = 0; rect < n_rects; rect++) for (EGLint rect = 0; rect < n_rects; rect++)
......
...@@ -1004,7 +1004,7 @@ angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context) ...@@ -1004,7 +1004,7 @@ angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context)
sourceRowPitch, imageData + bufferOffset)); sourceRowPitch, imageData + bufferOffset));
} }
CommandBufferT *commandBuffer; CommandBufferT *commandBuffer = nullptr;
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer)); ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
return mImage->flushStagedUpdates(contextVk, getNativeImageLevel(0), getLevelCount(), return mImage->flushStagedUpdates(contextVk, getNativeImageLevel(0), getLevelCount(),
commandBuffer); commandBuffer);
......
...@@ -335,7 +335,7 @@ angle::Result UtilsVk::setupProgram(vk::Context *context, ...@@ -335,7 +335,7 @@ angle::Result UtilsVk::setupProgram(vk::Context *context,
program->setShader(gl::ShaderType::Compute, fsCsShader); program->setShader(gl::ShaderType::Compute, fsCsShader);
ANGLE_TRY(program->getComputePipeline(context, pipelineLayout.get(), &pipelineAndSerial)); ANGLE_TRY(program->getComputePipeline(context, pipelineLayout.get(), &pipelineAndSerial));
pipelineAndSerial->updateSerial(serial); pipelineAndSerial->updateSerial(serial);
commandBuffer->bindPipeline(bindPoint, pipelineAndSerial->get()); commandBuffer->bindComputePipeline(pipelineAndSerial->get());
} }
else else
{ {
...@@ -350,7 +350,7 @@ angle::Result UtilsVk::setupProgram(vk::Context *context, ...@@ -350,7 +350,7 @@ angle::Result UtilsVk::setupProgram(vk::Context *context,
context, &renderer->getRenderPassCache(), renderer->getPipelineCache(), serial, context, &renderer->getRenderPassCache(), renderer->getPipelineCache(), serial,
pipelineLayout.get(), *pipelineDesc, gl::AttributesMask(), &descPtr, &helper)); pipelineLayout.get(), *pipelineDesc, gl::AttributesMask(), &descPtr, &helper));
helper->updateSerial(serial); helper->updateSerial(serial);
commandBuffer->bindPipeline(bindPoint, helper->getPipeline()); commandBuffer->bindGraphicsPipeline(helper->getPipeline());
} }
if (descriptorSet != VK_NULL_HANDLE) if (descriptorSet != VK_NULL_HANDLE)
...@@ -657,9 +657,7 @@ angle::Result UtilsVk::clearImage(ContextVk *contextVk, ...@@ -657,9 +657,7 @@ angle::Result UtilsVk::clearImage(ContextVk *contextVk,
ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader, ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
&mImageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams, &mImageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
sizeof(shaderParams), commandBuffer)); sizeof(shaderParams), commandBuffer));
commandBuffer->draw(6, 0);
commandBuffer->draw(6, 1, 0, 0);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -783,9 +781,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk, ...@@ -783,9 +781,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk,
ANGLE_TRY(setupProgram(contextVk, Function::ImageCopy, fragmentShader, vertexShader, ANGLE_TRY(setupProgram(contextVk, Function::ImageCopy, fragmentShader, vertexShader,
&mImageCopyPrograms[flags], &pipelineDesc, descriptorSet, &shaderParams, &mImageCopyPrograms[flags], &pipelineDesc, descriptorSet, &shaderParams,
sizeof(shaderParams), commandBuffer)); sizeof(shaderParams), commandBuffer));
commandBuffer->draw(6, 0);
commandBuffer->draw(6, 1, 0, 0);
descriptorPoolBinding.reset(); descriptorPoolBinding.reset();
return angle::Result::Continue; return angle::Result::Continue;
......
...@@ -1064,7 +1064,7 @@ void LineLoopHelper::Draw(uint32_t count, CommandBufferT *commandBuffer) ...@@ -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*. // 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. // Note: this could theoretically overflow and wrap to zero.
commandBuffer->drawIndexed(count + 1, 1, 0, 0, 0); commandBuffer->drawIndexed(count + 1);
} }
// BufferHelper implementation. // BufferHelper implementation.
...@@ -1603,10 +1603,9 @@ void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask, ...@@ -1603,10 +1603,9 @@ void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
imageMemoryBarrier.subresourceRange.layerCount = mLayerCount; imageMemoryBarrier.subresourceRange.layerCount = mLayerCount;
commandBuffer->pipelineBarrier(transitionFrom.srcStageMask, transitionTo.dstStageMask, 0, 0, commandBuffer->imageBarrier(transitionFrom.srcStageMask, transitionTo.dstStageMask,
nullptr, 0, nullptr, 1, &imageMemoryBarrier); &imageMemoryBarrier);
mCurrentLayout = newLayout;
mCurrentLayout = newLayout;
mCurrentQueueFamilyIndex = newQueueFamilyIndex; mCurrentQueueFamilyIndex = newQueueFamilyIndex;
} }
...@@ -1614,7 +1613,6 @@ void ImageHelper::clearColor(const VkClearColorValue &color, ...@@ -1614,7 +1613,6 @@ void ImageHelper::clearColor(const VkClearColorValue &color,
uint32_t baseMipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
CommandBufferT *commandBuffer) CommandBufferT *commandBuffer)
{ {
clearColorLayer(color, baseMipLevel, levelCount, 0, mLayerCount, commandBuffer); clearColorLayer(color, baseMipLevel, levelCount, 0, mLayerCount, commandBuffer);
} }
...@@ -1738,10 +1736,8 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, GLuint ...@@ -1738,10 +1736,8 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, GLuint
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
// We can do it for all layers at once. // We can do it for all layers at once.
commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
&barrier);
VkImageBlit blit = {}; VkImageBlit blit = {};
blit.srcOffsets[0] = {0, 0, 0}; blit.srcOffsets[0] = {0, 0, 0};
blit.srcOffsets[1] = {mipWidth, mipHeight, 1}; blit.srcOffsets[1] = {mipWidth, mipHeight, 1};
...@@ -1770,9 +1766,8 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, GLuint ...@@ -1770,9 +1766,8 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, GLuint
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
// We can do it for all layers at once. // We can do it for all layers at once.
commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
0, 0, nullptr, 0, nullptr, 1, &barrier); &barrier);
// This is just changing the internal state of the image helper so that the next call // 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. // to changeLayout will use this layout as the "oldLayout" argument.
mCurrentLayout = ImageLayout::TransferSrc; mCurrentLayout = ImageLayout::TransferSrc;
......
...@@ -626,6 +626,7 @@ class ImageHelper final : public CommandGraphResource ...@@ -626,6 +626,7 @@ class ImageHelper final : public CommandGraphResource
VkImageAspectFlags clearAspectFlags, VkImageAspectFlags clearAspectFlags,
const VkClearDepthStencilValue &depthStencil, const VkClearDepthStencilValue &depthStencil,
CommandBufferT *commandBuffer); CommandBufferT *commandBuffer);
gl::Extents getSize(const gl::ImageIndex &index) const; gl::Extents getSize(const gl::ImageIndex &index) const;
static void Copy(ImageHelper *srcImage, static void Copy(ImageHelper *srcImage,
......
...@@ -180,7 +180,9 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer> ...@@ -180,7 +180,9 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
const VkBufferMemoryBarrier *bufferMemoryBarriers, const VkBufferMemoryBarrier *bufferMemoryBarriers,
uint32_t imageMemoryBarrierCount, uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier *imageMemoryBarriers); const VkImageMemoryBarrier *imageMemoryBarriers);
void imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkImageMemoryBarrier *imageMemoryBarrier);
void clearColorImage(const Image &image, void clearColorImage(const Image &image,
VkImageLayout imageLayout, VkImageLayout imageLayout,
const VkClearColorValue &color, const VkClearColorValue &color,
...@@ -226,16 +228,21 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer> ...@@ -226,16 +228,21 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
uint32_t instanceCount, uint32_t instanceCount,
uint32_t firstVertex, uint32_t firstVertex,
uint32_t firstInstance); 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, void drawIndexed(uint32_t indexCount,
uint32_t instanceCount, uint32_t instanceCount,
uint32_t firstIndex, uint32_t firstIndex,
int32_t vertexOffset, int32_t vertexOffset,
uint32_t firstInstance); 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 dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const Pipeline &pipeline); void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const Pipeline &pipeline);
void bindGraphicsPipeline(const Pipeline &pipeline);
void bindComputePipeline(const Pipeline &pipeline);
void bindVertexBuffers(uint32_t firstBinding, void bindVertexBuffers(uint32_t firstBinding,
uint32_t bindingCount, uint32_t bindingCount,
...@@ -573,6 +580,15 @@ ANGLE_INLINE void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMa ...@@ -573,6 +580,15 @@ ANGLE_INLINE void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMa
imageMemoryBarrierCount, imageMemoryBarriers); 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) ANGLE_INLINE void CommandBuffer::destroy(VkDevice device)
{ {
releaseHandle(); releaseHandle();
...@@ -808,6 +824,20 @@ ANGLE_INLINE void CommandBuffer::draw(uint32_t vertexCount, ...@@ -808,6 +824,20 @@ ANGLE_INLINE void CommandBuffer::draw(uint32_t vertexCount,
vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, firstInstance); 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, ANGLE_INLINE void CommandBuffer::drawIndexed(uint32_t indexCount,
uint32_t instanceCount, uint32_t instanceCount,
uint32_t firstIndex, uint32_t firstIndex,
...@@ -818,6 +848,18 @@ ANGLE_INLINE void CommandBuffer::drawIndexed(uint32_t indexCount, ...@@ -818,6 +848,18 @@ ANGLE_INLINE void CommandBuffer::drawIndexed(uint32_t indexCount,
vkCmdDrawIndexed(mHandle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); 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, ANGLE_INLINE void CommandBuffer::dispatch(uint32_t groupCountX,
uint32_t groupCountY, uint32_t groupCountY,
uint32_t groupCountZ) uint32_t groupCountZ)
...@@ -833,6 +875,18 @@ ANGLE_INLINE void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPo ...@@ -833,6 +875,18 @@ ANGLE_INLINE void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPo
vkCmdBindPipeline(mHandle, pipelineBindPoint, pipeline.getHandle()); 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, ANGLE_INLINE void CommandBuffer::bindVertexBuffers(uint32_t firstBinding,
uint32_t bindingCount, uint32_t bindingCount,
const VkBuffer *buffers, const VkBuffer *buffers,
......
...@@ -1404,6 +1404,8 @@ TEST_P(SimpleStateChangeTest, RedefineBufferInUse) ...@@ -1404,6 +1404,8 @@ TEST_P(SimpleStateChangeTest, RedefineBufferInUse)
// Tests updating a buffer's contents while in use, without redefining it. // Tests updating a buffer's contents while in use, without redefining it.
TEST_P(SimpleStateChangeTest, UpdateBufferInUse) 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); std::vector<GLColor> redColorData(6, GLColor::red);
GLBuffer buffer; 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