Commit 6c7ab7fe by Jamie Madill Committed by Commit Bot

Vulkan: Reorganize helper classes.

This renames ResourceVk to vk::CommandGraphResource, which should help clarify its usage. This also moves LineLoopHandler, ImageHelper, and the DynamicBuffer and DynamicCommandPool classes into a new vk_helpers module. This file contains helper classes that manage other resources. Also this makes DynamicBuffer and DynamicDescriptorPool no longer inherit from CommandGraphResource. In the future, only Impl objects will be allowed to be graph resources. Bug: angleproject:2318 Change-Id: I0fa23da2ac853d90f3c822547a4a314f247cc757 Reviewed-on: https://chromium-review.googlesource.com/985200 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org>
parent 5ae64c94
...@@ -12,13 +12,13 @@ ...@@ -12,13 +12,13 @@
#include "libANGLE/Observer.h" #include "libANGLE/Observer.h"
#include "libANGLE/renderer/BufferImpl.h" #include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/vulkan/vk_utils.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
namespace rx namespace rx
{ {
class RendererVk; class RendererVk;
class BufferVk : public BufferImpl, public ResourceVk class BufferVk : public BufferImpl, public vk::CommandGraphResource
{ {
public: public:
BufferVk(const gl::BufferState &state); BufferVk(const gl::BufferState &state);
......
...@@ -51,6 +51,98 @@ Error InitAndBeginCommandBuffer(VkDevice device, ...@@ -51,6 +51,98 @@ Error InitAndBeginCommandBuffer(VkDevice device,
} // anonymous namespace } // anonymous namespace
// CommandGraphResource implementation.
CommandGraphResource::CommandGraphResource() : mCurrentWritingNode(nullptr)
{
}
CommandGraphResource::~CommandGraphResource()
{
}
void CommandGraphResource::updateQueueSerial(Serial queueSerial)
{
ASSERT(queueSerial >= mStoredQueueSerial);
if (queueSerial > mStoredQueueSerial)
{
mCurrentWritingNode = nullptr;
mCurrentReadingNodes.clear();
mStoredQueueSerial = queueSerial;
}
}
Serial CommandGraphResource::getQueueSerial() const
{
return mStoredQueueSerial;
}
bool CommandGraphResource::hasCurrentWritingNode(Serial currentSerial) const
{
return (mStoredQueueSerial == currentSerial && mCurrentWritingNode != nullptr &&
!mCurrentWritingNode->hasChildren());
}
CommandGraphNode *CommandGraphResource::getCurrentWritingNode(Serial currentSerial)
{
ASSERT(currentSerial == mStoredQueueSerial);
return mCurrentWritingNode;
}
CommandGraphNode *CommandGraphResource::getNewWritingNode(RendererVk *renderer)
{
CommandGraphNode *newCommands = renderer->allocateCommandNode();
onWriteResource(newCommands, renderer->getCurrentQueueSerial());
return newCommands;
}
Error CommandGraphResource::beginWriteResource(RendererVk *renderer,
CommandBuffer **commandBufferOut)
{
CommandGraphNode *commands = getNewWritingNode(renderer);
VkDevice device = renderer->getDevice();
ANGLE_TRY(commands->beginOutsideRenderPassRecording(device, renderer->getCommandPool(),
commandBufferOut));
return NoError();
}
void CommandGraphResource::onWriteResource(CommandGraphNode *writingNode, Serial serial)
{
updateQueueSerial(serial);
// Make sure any open reads and writes finish before we execute 'newCommands'.
if (!mCurrentReadingNodes.empty())
{
CommandGraphNode::SetHappensBeforeDependencies(mCurrentReadingNodes, writingNode);
mCurrentReadingNodes.clear();
}
if (mCurrentWritingNode && mCurrentWritingNode != writingNode)
{
CommandGraphNode::SetHappensBeforeDependency(mCurrentWritingNode, writingNode);
}
mCurrentWritingNode = writingNode;
}
void CommandGraphResource::onReadResource(CommandGraphNode *readingNode, Serial serial)
{
if (hasCurrentWritingNode(serial))
{
// Ensure 'readOperation' happens after the current write commands.
CommandGraphNode::SetHappensBeforeDependency(getCurrentWritingNode(serial), readingNode);
ASSERT(mStoredQueueSerial == serial);
}
else
{
updateQueueSerial(serial);
}
// Add the read operation to the list of nodes currently reading this resource.
mCurrentReadingNodes.push_back(readingNode);
}
// CommandGraphNode implementation. // CommandGraphNode implementation.
CommandGraphNode::CommandGraphNode() : mHasChildren(false), mVisitedState(VisitedState::Unvisited) CommandGraphNode::CommandGraphNode() : mHasChildren(false), mVisitedState(VisitedState::Unvisited)
...@@ -354,7 +446,7 @@ Error CommandGraph::submitCommands(VkDevice device, ...@@ -354,7 +446,7 @@ Error CommandGraph::submitCommands(VkDevice device,
ANGLE_TRY(primaryCommandBufferOut->end()); ANGLE_TRY(primaryCommandBufferOut->end());
// TODO(jmadill): Use pool allocation so we don't need to deallocate command graph. // TODO(jmadill): Use pool allocation so we don't need to deallocate command graph.
for (vk::CommandGraphNode *node : mNodes) for (CommandGraphNode *node : mNodes)
{ {
delete node; delete node;
} }
......
...@@ -18,6 +18,46 @@ namespace rx ...@@ -18,6 +18,46 @@ namespace rx
namespace vk namespace vk
{ {
// This is a helper class for back-end objects used in Vk command buffers. It records a serial
// at command recording times indicating an order in the queue. We use Fences to detect when
// commands finish, and then release any unreferenced and deleted resources based on the stored
// queue serial in a special 'garbage' queue. Resources also track current read and write
// dependencies. Only one command buffer node can be writing to the Resource at a time, but many
// can be reading from it. Together the dependencies will form a command graph at submission time.
class CommandGraphResource
{
public:
CommandGraphResource();
virtual ~CommandGraphResource();
void updateQueueSerial(Serial queueSerial);
Serial getQueueSerial() const;
// Returns true if any tracked read or write nodes match 'currentSerial'.
bool hasCurrentWritingNode(Serial currentSerial) const;
// Returns the active write node, and asserts 'currentSerial' matches the stored serial.
CommandGraphNode *getCurrentWritingNode(Serial currentSerial);
// Allocates a new write node and calls onWriteResource internally.
CommandGraphNode *getNewWritingNode(RendererVk *renderer);
// Allocates a write node via getNewWriteNode and returns a started command buffer.
// The started command buffer will render outside of a RenderPass.
Error beginWriteResource(RendererVk *renderer, CommandBuffer **commandBufferOut);
// Sets up dependency relations. 'writingNode' will modify 'this' ResourceVk.
void onWriteResource(CommandGraphNode *writingNode, Serial serial);
// Sets up dependency relations. 'readingNode' will read from 'this' ResourceVk.
void onReadResource(CommandGraphNode *readingNode, Serial serial);
private:
Serial mStoredQueueSerial;
std::vector<CommandGraphNode *> mCurrentReadingNodes;
CommandGraphNode *mCurrentWritingNode;
};
enum class VisitedState enum class VisitedState
{ {
Unvisited, Unvisited,
...@@ -39,7 +79,7 @@ enum class VisitedState ...@@ -39,7 +79,7 @@ enum class VisitedState
// for a directed acyclic CommandGraph. When we need to submit the CommandGraph, say during a // for a directed acyclic CommandGraph. When we need to submit the CommandGraph, say during a
// SwapBuffers or ReadPixels call, we begin a primary Vulkan CommandBuffer, and walk the // SwapBuffers or ReadPixels call, we begin a primary Vulkan CommandBuffer, and walk the
// CommandGraph, starting at the most senior nodes, recording secondary CommandBuffers inside // CommandGraph, starting at the most senior nodes, recording secondary CommandBuffers inside
// and outside vk::RenderPasses as necessary, filled with the right load/store operations. Once // and outside RenderPasses as necessary, filled with the right load/store operations. Once
// the primary CommandBuffer has recorded all of the secondary CommandBuffers from all the open // the primary CommandBuffer has recorded all of the secondary CommandBuffers from all the open
// CommandGraphNodes, we submit the primary CommandBuffer to the VkQueue on the device. // CommandGraphNodes, we submit the primary CommandBuffer to the VkQueue on the device.
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include "libANGLE/renderer/vulkan/CompilerVk.h" #include "libANGLE/renderer/vulkan/CompilerVk.h"
#include "libANGLE/renderer/vulkan/ContextVk.h" #include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/DeviceVk.h" #include "libANGLE/renderer/vulkan/DeviceVk.h"
#include "libANGLE/renderer/vulkan/DynamicDescriptorPool.h"
#include "libANGLE/renderer/vulkan/FenceNVVk.h" #include "libANGLE/renderer/vulkan/FenceNVVk.h"
#include "libANGLE/renderer/vulkan/FramebufferVk.h" #include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include "libANGLE/renderer/vulkan/ImageVk.h" #include "libANGLE/renderer/vulkan/ImageVk.h"
...@@ -732,7 +731,7 @@ gl::Error ContextVk::memoryBarrierByRegion(const gl::Context *context, GLbitfiel ...@@ -732,7 +731,7 @@ gl::Error ContextVk::memoryBarrierByRegion(const gl::Context *context, GLbitfiel
return gl::InternalError(); return gl::InternalError();
} }
DynamicDescriptorPool *ContextVk::getDynamicDescriptorPool() vk::DynamicDescriptorPool *ContextVk::getDynamicDescriptorPool()
{ {
return &mDynamicDescriptorPool; return &mDynamicDescriptorPool;
} }
......
...@@ -13,9 +13,7 @@ ...@@ -13,9 +13,7 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include "libANGLE/renderer/ContextImpl.h" #include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/vulkan/DynamicBuffer.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
#include "libANGLE/renderer/vulkan/DynamicDescriptorPool.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h"
namespace rx namespace rx
{ {
...@@ -156,7 +154,7 @@ class ContextVk : public ContextImpl ...@@ -156,7 +154,7 @@ class ContextVk : public ContextImpl
void invalidateCurrentPipeline(); void invalidateCurrentPipeline();
DynamicDescriptorPool *getDynamicDescriptorPool(); vk::DynamicDescriptorPool *getDynamicDescriptorPool();
const VkClearValue &getClearColorValue() const; const VkClearValue &getClearColorValue() const;
const VkClearValue &getClearDepthStencilValue() const; const VkClearValue &getClearDepthStencilValue() const;
...@@ -179,7 +177,7 @@ class ContextVk : public ContextImpl ...@@ -179,7 +177,7 @@ class ContextVk : public ContextImpl
// The dynamic descriptor pool is externally sychronized, so cannot be accessed from different // The dynamic descriptor pool is externally sychronized, so cannot be accessed from different
// threads simultaneously. Hence, we keep it in the ContextVk instead of the RendererVk. // threads simultaneously. Hence, we keep it in the ContextVk instead of the RendererVk.
DynamicDescriptorPool mDynamicDescriptorPool; vk::DynamicDescriptorPool mDynamicDescriptorPool;
// Triggers adding dependencies to the command graph. // Triggers adding dependencies to the command graph.
bool mTexturesDirty; bool mTexturesDirty;
...@@ -189,7 +187,6 @@ class ContextVk : public ContextImpl ...@@ -189,7 +187,6 @@ class ContextVk : public ContextImpl
VkClearValue mClearColorValue; VkClearValue mClearColorValue;
VkClearValue mClearDepthStencilValue; VkClearValue mClearDepthStencilValue;
}; };
} // namespace rx } // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_ #endif // LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
//
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// DynamicBuffer:
// Create, map and flush buffers as needed to hold data, returning a handle and offset for each
// chunk.
//
#include "libANGLE/renderer/vulkan/DynamicBuffer.h"
#include "anglebase/numerics/safe_math.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx
{
DynamicBuffer::DynamicBuffer(VkBufferUsageFlags usage, size_t minSize)
: mUsage(usage),
mMinSize(minSize),
mNextWriteOffset(0),
mLastFlushOffset(0),
mSize(0),
mAlignment(0),
mMappedMemory(nullptr)
{
}
void DynamicBuffer::init(size_t alignment)
{
ASSERT(alignment > 0);
mAlignment = alignment;
}
DynamicBuffer::~DynamicBuffer()
{
ASSERT(mAlignment == 0);
}
bool DynamicBuffer::valid()
{
return mAlignment > 0;
}
vk::Error DynamicBuffer::allocate(RendererVk *renderer,
size_t sizeInBytes,
uint8_t **ptrOut,
VkBuffer *handleOut,
uint32_t *offsetOut,
bool *outNewBufferAllocated)
{
ASSERT(valid());
VkDevice device = renderer->getDevice();
size_t sizeToAllocate = roundUp(sizeInBytes, mAlignment);
angle::base::CheckedNumeric<size_t> checkedNextWriteOffset = mNextWriteOffset;
checkedNextWriteOffset += sizeToAllocate;
if (!checkedNextWriteOffset.IsValid() || checkedNextWriteOffset.ValueOrDie() > mSize)
{
if (mMappedMemory)
{
ANGLE_TRY(flush(device));
mMemory.unmap(device);
mMappedMemory = nullptr;
}
Serial currentSerial = renderer->getCurrentQueueSerial();
renderer->releaseObject(currentSerial, &mBuffer);
renderer->releaseObject(currentSerial, &mMemory);
VkBufferCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.size = std::max(sizeToAllocate, mMinSize);
createInfo.usage = mUsage;
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.queueFamilyIndexCount = 0;
createInfo.pQueueFamilyIndices = nullptr;
ANGLE_TRY(mBuffer.init(device, createInfo));
ANGLE_TRY(vk::AllocateBufferMemory(renderer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &mBuffer,
&mMemory, &mSize));
ANGLE_TRY(mMemory.map(device, 0, mSize, 0, &mMappedMemory));
mNextWriteOffset = 0;
mLastFlushOffset = 0;
if (outNewBufferAllocated != nullptr)
{
*outNewBufferAllocated = true;
}
}
else
{
if (outNewBufferAllocated != nullptr)
{
*outNewBufferAllocated = false;
}
}
ASSERT(mBuffer.valid());
if (handleOut != nullptr)
{
*handleOut = mBuffer.getHandle();
}
ASSERT(mMappedMemory);
*ptrOut = mMappedMemory + mNextWriteOffset;
*offsetOut = mNextWriteOffset;
mNextWriteOffset += static_cast<uint32_t>(sizeToAllocate);
return vk::NoError();
}
vk::Error DynamicBuffer::flush(VkDevice device)
{
if (mNextWriteOffset > mLastFlushOffset)
{
VkMappedMemoryRange range;
range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
range.pNext = nullptr;
range.memory = mMemory.getHandle();
range.offset = mLastFlushOffset;
range.size = mNextWriteOffset - mLastFlushOffset;
ANGLE_VK_TRY(vkFlushMappedMemoryRanges(device, 1, &range));
mLastFlushOffset = mNextWriteOffset;
}
return vk::NoError();
}
void DynamicBuffer::destroy(VkDevice device)
{
mAlignment = 0;
mBuffer.destroy(device);
mMemory.destroy(device);
}
VkBuffer DynamicBuffer::getCurrentBufferHandle() const
{
return mBuffer.getHandle();
}
void DynamicBuffer::setMinimumSize(size_t minSize)
{
// This will really only have an effect next time we call allocate.
mMinSize = minSize;
// Forces a new allocation on the next allocate.
mSize = 0;
}
} // namespace rx
//
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// DynamicBuffer:
// Create, map and flush buffers as needed to hold data, returning a handle and offset for each
// chunk.
//
#ifndef LIBANGLE_RENDERER_VULKAN_STREAMING_BUFFER_H_
#define LIBANGLE_RENDERER_VULKAN_STREAMING_BUFFER_H_
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
{
class DynamicBuffer : public ResourceVk
{
public:
DynamicBuffer(VkBufferUsageFlags usage, size_t minSize);
~DynamicBuffer();
void init(size_t alignment);
bool valid();
vk::Error allocate(RendererVk *renderer,
size_t sizeInBytes,
uint8_t **ptrOut,
VkBuffer *handleOut,
uint32_t *offsetOut,
bool *outNewBufferAllocated);
vk::Error flush(VkDevice device);
void destroy(VkDevice device);
VkBuffer getCurrentBufferHandle() const;
// For testing only!
void setMinimumSize(size_t minSize);
private:
VkBufferUsageFlags mUsage;
size_t mMinSize;
vk::Buffer mBuffer;
vk::DeviceMemory mMemory;
uint32_t mNextWriteOffset;
uint32_t mLastFlushOffset;
size_t mSize;
size_t mAlignment;
uint8_t *mMappedMemory;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_STREAMING_BUFFER_H_
//
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// DynamicDescriptorPool:
// Uses DescriptorPool to allocate descriptor sets as needed. If the descriptor pool
// is full, we simply allocate a new pool to keep allocating descriptor sets as needed and
// leave the renderer take care of the life time of the pools that become unused.
//
#include "DynamicDescriptorPool.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx
{
namespace
{
// TODO(jmadill): Pick non-arbitrary max.
constexpr uint32_t kMaxSets = 2048;
} // anonymous namespace
DynamicDescriptorPool::DynamicDescriptorPool()
: mCurrentAllocatedDescriptorSetCount(0),
mUniformBufferDescriptorsPerSet(0),
mCombinedImageSamplerDescriptorsPerSet(0)
{
}
DynamicDescriptorPool::~DynamicDescriptorPool()
{
}
void DynamicDescriptorPool::destroy(RendererVk *rendererVk)
{
ASSERT(mCurrentDescriptorSetPool.valid());
rendererVk->releaseResource(*this, &mCurrentDescriptorSetPool);
}
vk::Error DynamicDescriptorPool::init(const VkDevice &device,
uint32_t uniformBufferDescriptorsPerSet,
uint32_t combinedImageSamplerDescriptorsPerSet)
{
ASSERT(!mCurrentDescriptorSetPool.valid() && mCurrentAllocatedDescriptorSetCount == 0);
mUniformBufferDescriptorsPerSet = uniformBufferDescriptorsPerSet;
mCombinedImageSamplerDescriptorsPerSet = combinedImageSamplerDescriptorsPerSet;
ANGLE_TRY(allocateNewPool(device));
return vk::NoError();
}
vk::Error DynamicDescriptorPool::allocateDescriptorSets(
ContextVk *contextVk,
const VkDescriptorSetLayout *descriptorSetLayout,
uint32_t descriptorSetCount,
VkDescriptorSet *descriptorSetsOut)
{
updateQueueSerial(contextVk->getRenderer()->getCurrentQueueSerial());
if (descriptorSetCount + mCurrentAllocatedDescriptorSetCount > kMaxSets)
{
// We will bust the limit of descriptor set with this allocation so we need to get a new
// pool for it.
contextVk->getRenderer()->releaseResource(*this, &mCurrentDescriptorSetPool);
ANGLE_TRY(allocateNewPool(contextVk->getDevice()));
}
VkDescriptorSetAllocateInfo allocInfo;
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.pNext = nullptr;
allocInfo.descriptorPool = mCurrentDescriptorSetPool.getHandle();
allocInfo.descriptorSetCount = descriptorSetCount;
allocInfo.pSetLayouts = descriptorSetLayout;
ANGLE_TRY(mCurrentDescriptorSetPool.allocateDescriptorSets(contextVk->getDevice(), allocInfo,
descriptorSetsOut));
mCurrentAllocatedDescriptorSetCount += allocInfo.descriptorSetCount;
return vk::NoError();
}
vk::Error DynamicDescriptorPool::allocateNewPool(const VkDevice &device)
{
VkDescriptorPoolSize poolSizes[DescriptorPoolIndexCount];
poolSizes[UniformBufferIndex].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
poolSizes[UniformBufferIndex].descriptorCount =
mUniformBufferDescriptorsPerSet * kMaxSets / DescriptorPoolIndexCount;
poolSizes[TextureIndex].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[TextureIndex].descriptorCount =
mCombinedImageSamplerDescriptorsPerSet * kMaxSets / DescriptorPoolIndexCount;
VkDescriptorPoolCreateInfo descriptorPoolInfo;
descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptorPoolInfo.pNext = nullptr;
descriptorPoolInfo.flags = 0;
descriptorPoolInfo.maxSets = kMaxSets;
// Reserve pools for uniform blocks and textures.
descriptorPoolInfo.poolSizeCount = DescriptorPoolIndexCount;
descriptorPoolInfo.pPoolSizes = poolSizes;
mCurrentAllocatedDescriptorSetCount = 0;
ANGLE_TRY(mCurrentDescriptorSetPool.init(device, descriptorPoolInfo));
return vk::NoError();
}
} // namespace rx
//
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// DynamicDescriptorPool:
// Uses DescriptorPool to allocate descriptor sets as needed. If the descriptor pool
// is full, we simply allocate a new pool to keep allocating descriptor sets as needed and
// leave the renderer take care of the life time of the pools that become unused.
//
#ifndef LIBANGLE_RENDERER_VULKAN_DYNAMIC_DESCRIPTOR_POOL_H_
#define LIBANGLE_RENDERER_VULKAN_DYNAMIC_DESCRIPTOR_POOL_H_
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
{
enum DescriptorPoolIndex : uint8_t
{
UniformBufferIndex = 0,
TextureIndex = 1,
DescriptorPoolIndexCount = 2
};
class DynamicDescriptorPool final : public ResourceVk
{
public:
DynamicDescriptorPool();
~DynamicDescriptorPool();
void destroy(RendererVk *rendererVk);
vk::Error init(const VkDevice &device,
uint32_t uniformBufferDescriptorsPerSet,
uint32_t combinedImageSamplerDescriptorsPerSet);
// It is an undefined behavior to pass a different descriptorSetLayout from call to call.
vk::Error allocateDescriptorSets(ContextVk *contextVk,
const VkDescriptorSetLayout *descriptorSetLayout,
uint32_t descriptorSetCount,
VkDescriptorSet *descriptorSetsOut);
private:
vk::Error allocateNewPool(const VkDevice &device);
vk::DescriptorPool mCurrentDescriptorSetPool;
size_t mCurrentAllocatedDescriptorSetCount;
uint32_t mUniformBufferDescriptorsPerSet;
uint32_t mCombinedImageSamplerDescriptorsPerSet;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_DYNAMIC_DESCRIPTOR_POOL_H_
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "libANGLE/renderer/FramebufferImpl.h" #include "libANGLE/renderer/FramebufferImpl.h"
#include "libANGLE/renderer/RenderTargetCache.h" #include "libANGLE/renderer/RenderTargetCache.h"
#include "libANGLE/renderer/vulkan/CommandGraph.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h" #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
namespace rx namespace rx
...@@ -20,7 +21,7 @@ class RendererVk; ...@@ -20,7 +21,7 @@ class RendererVk;
class RenderTargetVk; class RenderTargetVk;
class WindowSurfaceVk; class WindowSurfaceVk;
class FramebufferVk : public FramebufferImpl, public ResourceVk class FramebufferVk : public FramebufferImpl, public vk::CommandGraphResource
{ {
public: public:
// Factory methods so we don't have to use constructors with overloads. // Factory methods so we don't have to use constructors with overloads.
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include "common/utilities.h" #include "common/utilities.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/ContextVk.h" #include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/DynamicDescriptorPool.h"
#include "libANGLE/renderer/vulkan/GlslangWrapper.h" #include "libANGLE/renderer/vulkan/GlslangWrapper.h"
#include "libANGLE/renderer/vulkan/RendererVk.h" #include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/TextureVk.h" #include "libANGLE/renderer/vulkan/TextureVk.h"
...@@ -114,7 +113,7 @@ void ReadFromDefaultUniformBlock(int componentCount, ...@@ -114,7 +113,7 @@ void ReadFromDefaultUniformBlock(int componentCount,
} }
vk::Error SyncDefaultUniformBlock(RendererVk *renderer, vk::Error SyncDefaultUniformBlock(RendererVk *renderer,
DynamicBuffer *dynamicBuffer, vk::DynamicBuffer *dynamicBuffer,
const angle::MemoryBuffer &bufferData, const angle::MemoryBuffer &bufferData,
uint32_t *outOffset, uint32_t *outOffset,
bool *outBufferModified) bool *outBufferModified)
...@@ -702,7 +701,7 @@ vk::Error ProgramVk::allocateDescriptorSet(ContextVk *contextVk, uint32_t descri ...@@ -702,7 +701,7 @@ vk::Error ProgramVk::allocateDescriptorSet(ContextVk *contextVk, uint32_t descri
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
// Write out to a new a descriptor set. // Write out to a new a descriptor set.
DynamicDescriptorPool *dynamicDescriptorPool = contextVk->getDynamicDescriptorPool(); vk::DynamicDescriptorPool *dynamicDescriptorPool = contextVk->getDynamicDescriptorPool();
const auto &descriptorSetLayouts = renderer->getGraphicsDescriptorSetLayouts(); const auto &descriptorSetLayouts = renderer->getGraphicsDescriptorSetLayouts();
uint32_t potentialNewCount = descriptorSetIndex + 1; uint32_t potentialNewCount = descriptorSetIndex + 1;
...@@ -770,7 +769,7 @@ vk::Error ProgramVk::updateUniforms(ContextVk *contextVk) ...@@ -770,7 +769,7 @@ vk::Error ProgramVk::updateUniforms(ContextVk *contextVk)
{ {
// We need to reinitialize the descriptor sets if we newly allocated buffers since we can't // We need to reinitialize the descriptor sets if we newly allocated buffers since we can't
// modify the descriptor sets once initialized. // modify the descriptor sets once initialized.
ANGLE_TRY(allocateDescriptorSet(contextVk, UniformBufferIndex)); ANGLE_TRY(allocateDescriptorSet(contextVk, vk::UniformBufferIndex));
ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk)); ANGLE_TRY(updateDefaultUniformsDescriptorSet(contextVk));
} }
...@@ -856,7 +855,7 @@ vk::Error ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk) ...@@ -856,7 +855,7 @@ vk::Error ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
return vk::NoError(); return vk::NoError();
} }
ANGLE_TRY(allocateDescriptorSet(contextVk, TextureIndex)); ANGLE_TRY(allocateDescriptorSet(contextVk, vk::TextureIndex));
ASSERT(mUsedDescriptorSetRange.contains(1)); ASSERT(mUsedDescriptorSetRange.contains(1));
VkDescriptorSet descriptorSet = mDescriptorSets[1]; VkDescriptorSet descriptorSet = mDescriptorSets[1];
...@@ -925,7 +924,7 @@ void ProgramVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize) ...@@ -925,7 +924,7 @@ void ProgramVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
{ {
for (DefaultUniformBlock &block : mDefaultUniformBlocks) for (DefaultUniformBlock &block : mDefaultUniformBlocks)
{ {
block.storage.setMinimumSize(minSize); block.storage.setMinimumSizeForTesting(minSize);
} }
} }
} // namespace rx } // namespace rx
...@@ -14,9 +14,8 @@ ...@@ -14,9 +14,8 @@
#include "libANGLE/Constants.h" #include "libANGLE/Constants.h"
#include "libANGLE/renderer/ProgramImpl.h" #include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/vulkan/DynamicBuffer.h"
#include "libANGLE/renderer/vulkan/RendererVk.h" #include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_utils.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
namespace rx namespace rx
{ {
...@@ -153,7 +152,7 @@ class ProgramVk : public ProgramImpl ...@@ -153,7 +152,7 @@ class ProgramVk : public ProgramImpl
DefaultUniformBlock(); DefaultUniformBlock();
~DefaultUniformBlock(); ~DefaultUniformBlock();
DynamicBuffer storage; vk::DynamicBuffer storage;
// Shadow copies of the shader uniform data. // Shadow copies of the shader uniform data.
angle::MemoryBuffer uniformData; angle::MemoryBuffer uniformData;
......
...@@ -16,10 +16,9 @@ ...@@ -16,10 +16,9 @@
namespace rx namespace rx
{ {
class ResourceVk;
namespace vk namespace vk
{ {
class CommandGraphResource;
class ImageHelper; class ImageHelper;
class ImageView; class ImageView;
} // namespace vk } // namespace vk
...@@ -34,7 +33,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget ...@@ -34,7 +33,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
vk::ImageHelper *image; vk::ImageHelper *image;
vk::ImageView *imageView; vk::ImageView *imageView;
ResourceVk *resource; vk::CommandGraphResource *resource;
}; };
} // namespace rx } // namespace rx
......
...@@ -12,12 +12,12 @@ ...@@ -12,12 +12,12 @@
#include "libANGLE/renderer/RenderbufferImpl.h" #include "libANGLE/renderer/RenderbufferImpl.h"
#include "libANGLE/renderer/vulkan/RenderTargetVk.h" #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
#include "libANGLE/renderer/vulkan/vk_utils.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
namespace rx namespace rx
{ {
class RenderbufferVk : public RenderbufferImpl, public ResourceVk class RenderbufferVk : public RenderbufferImpl, public vk::CommandGraphResource
{ {
public: public:
RenderbufferVk(const gl::RenderbufferState &state); RenderbufferVk(const gl::RenderbufferState &state);
......
...@@ -797,7 +797,7 @@ Serial RendererVk::getCurrentQueueSerial() const ...@@ -797,7 +797,7 @@ Serial RendererVk::getCurrentQueueSerial() const
return mCurrentQueueSerial; return mCurrentQueueSerial;
} }
bool RendererVk::isResourceInUse(const ResourceVk &resource) bool RendererVk::isResourceInUse(const vk::CommandGraphResource &resource)
{ {
return isSerialInUse(resource.getQueueSerial()); return isSerialInUse(resource.getQueueSerial());
} }
......
...@@ -73,11 +73,11 @@ class RendererVk : angle::NonCopyable ...@@ -73,11 +73,11 @@ class RendererVk : angle::NonCopyable
Serial getCurrentQueueSerial() const; Serial getCurrentQueueSerial() const;
bool isResourceInUse(const ResourceVk &resource); bool isResourceInUse(const vk::CommandGraphResource &resource);
bool isSerialInUse(Serial serial); bool isSerialInUse(Serial serial);
template <typename T> template <typename T>
void releaseResource(const ResourceVk &resource, T *object) void releaseResource(const vk::CommandGraphResource &resource, T *object)
{ {
Serial resourceSerial = resource.getQueueSerial(); Serial resourceSerial = resource.getQueueSerial();
releaseObject(resourceSerial, object); releaseObject(resourceSerial, object);
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include "libANGLE/renderer/SurfaceImpl.h" #include "libANGLE/renderer/SurfaceImpl.h"
#include "libANGLE/renderer/vulkan/RenderTargetVk.h" #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
#include "libANGLE/renderer/vulkan/vk_utils.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
namespace rx namespace rx
{ {
...@@ -60,7 +60,7 @@ class OffscreenSurfaceVk : public SurfaceImpl ...@@ -60,7 +60,7 @@ class OffscreenSurfaceVk : public SurfaceImpl
EGLint mHeight; EGLint mHeight;
}; };
class WindowSurfaceVk : public SurfaceImpl, public ResourceVk class WindowSurfaceVk : public SurfaceImpl, public vk::CommandGraphResource
{ {
public: public:
WindowSurfaceVk(const egl::SurfaceState &surfaceState, WindowSurfaceVk(const egl::SurfaceState &surfaceState,
......
...@@ -11,13 +11,14 @@ ...@@ -11,13 +11,14 @@
#define LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_ #define LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
#include "libANGLE/renderer/TextureImpl.h" #include "libANGLE/renderer/TextureImpl.h"
#include "libANGLE/renderer/vulkan/CommandGraph.h"
#include "libANGLE/renderer/vulkan/RenderTargetVk.h" #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
#include "libANGLE/renderer/vulkan/vk_utils.h" #include "libANGLE/renderer/vulkan/vk_helpers.h"
namespace rx namespace rx
{ {
class TextureVk : public TextureImpl, public ResourceVk class TextureVk : public TextureImpl, public vk::CommandGraphResource
{ {
public: public:
TextureVk(const gl::TextureState &state); TextureVk(const gl::TextureState &state);
......
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
#define LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_ #define LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_
#include "libANGLE/renderer/VertexArrayImpl.h" #include "libANGLE/renderer/VertexArrayImpl.h"
#include "libANGLE/renderer/vulkan/DynamicBuffer.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h" #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
namespace gl namespace gl
{ {
...@@ -22,7 +22,12 @@ class DrawCallParams; ...@@ -22,7 +22,12 @@ class DrawCallParams;
namespace rx namespace rx
{ {
class BufferVk; class BufferVk;
namespace vk
{
class CommandGraphResource;
class DynamicBuffer; class DynamicBuffer;
} // namespace vk
class VertexArrayVk : public VertexArrayImpl class VertexArrayVk : public VertexArrayImpl
{ {
...@@ -40,6 +45,12 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -40,6 +45,12 @@ class VertexArrayVk : public VertexArrayImpl
const gl::AttribArray<VkBuffer> &getCurrentArrayBufferHandles() const; const gl::AttribArray<VkBuffer> &getCurrentArrayBufferHandles() const;
const gl::AttribArray<VkDeviceSize> &getCurrentArrayBufferOffsets() const; const gl::AttribArray<VkDeviceSize> &getCurrentArrayBufferOffsets() const;
void updateDrawDependencies(vk::CommandGraphNode *readNode,
const gl::AttributesMask &activeAttribsMask,
vk::CommandGraphResource *elementArrayBufferOverride,
Serial serial,
bool isDrawElements);
void getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc); void getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc);
// Draw call handling. // Draw call handling.
...@@ -90,10 +101,10 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -90,10 +101,10 @@ class VertexArrayVk : public VertexArrayImpl
gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles; gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles;
gl::AttribArray<VkDeviceSize> mCurrentArrayBufferOffsets; gl::AttribArray<VkDeviceSize> mCurrentArrayBufferOffsets;
gl::AttribArray<ResourceVk *> mCurrentArrayBufferResources; gl::AttribArray<vk::CommandGraphResource *> mCurrentArrayBufferResources;
VkBuffer mCurrentElementArrayBufferHandle; VkBuffer mCurrentElementArrayBufferHandle;
VkDeviceSize mCurrentElementArrayBufferOffset; VkDeviceSize mCurrentElementArrayBufferOffset;
ResourceVk *mCurrentElementArrayBufferResource; vk::CommandGraphResource *mCurrentElementArrayBufferResource;
// Keep a cache of binding and attribute descriptions for easy pipeline updates. // Keep a cache of binding and attribute descriptions for easy pipeline updates.
// This is copied out of here into the pipeline description on a Context state change. // This is copied out of here into the pipeline description on a Context state change.
...@@ -105,8 +116,8 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -105,8 +116,8 @@ class VertexArrayVk : public VertexArrayImpl
// TODO(jmadill): Move this to VertexArrayState. http://anglebug.com/2389 // TODO(jmadill): Move this to VertexArrayState. http://anglebug.com/2389
gl::AttributesMask mClientMemoryAttribs; gl::AttributesMask mClientMemoryAttribs;
DynamicBuffer mDynamicVertexData; vk::DynamicBuffer mDynamicVertexData;
DynamicBuffer mDynamicIndexData; vk::DynamicBuffer mDynamicIndexData;
vk::LineLoopHandler mLineLoopHandler; vk::LineLoopHandler mLineLoopHandler;
Optional<int> mLineLoopBufferFirstIndex; Optional<int> mLineLoopBufferFirstIndex;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "libANGLE/renderer/vulkan/ProgramVk.h" #include "libANGLE/renderer/vulkan/ProgramVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h" #include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.h" #include "libANGLE/renderer/vulkan/vk_format_utils.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
namespace rx namespace rx
{ {
......
...@@ -19,6 +19,8 @@ namespace rx ...@@ -19,6 +19,8 @@ namespace rx
namespace vk namespace vk
{ {
class ImageHelper;
// Packed Vk resource descriptions. // Packed Vk resource descriptions.
// Most Vk types use many more bits than required to represent the underlying data. // Most Vk types use many more bits than required to represent the underlying data.
// Since ANGLE wants cache things like RenderPasses and Pipeline State Objects using // Since ANGLE wants cache things like RenderPasses and Pipeline State Objects using
......
//
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// vk_helpers:
// Helper utilitiy classes that manage Vulkan resources.
#ifndef LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_
#define LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_
#include "libANGLE/renderer/vulkan/CommandGraph.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
{
namespace vk
{
// A dynamic buffer is conceptually an infinitely long buffer. Each time you write to the buffer,
// you will always write to a previously unused portion. After a series of writes, you must flush
// the buffer data to the device. Buffer lifetime currently assumes that each new allocation will
// last as long or longer than each prior allocation.
//
// Dynamic buffers are used to implement a variety of data streaming operations in Vulkan, such
// as for immediate vertex array and element array data, uniform updates, and other dynamic data.
class DynamicBuffer : angle::NonCopyable
{
public:
DynamicBuffer(VkBufferUsageFlags usage, size_t minSize);
~DynamicBuffer();
// Init is called after the buffer creation so that the alignment can be specified later.
void init(size_t alignment);
bool valid();
// This call will allocate a new region at the end of the buffer. It internally may trigger
// a new buffer to be created (which is returned in 'newBufferAllocatedOut'. This param may
// be nullptr.
Error allocate(RendererVk *renderer,
size_t sizeInBytes,
uint8_t **ptrOut,
VkBuffer *handleOut,
uint32_t *offsetOut,
bool *newBufferAllocatedOut);
// After a sequence of writes, call flush to ensure the data is visible to the device.
Error flush(VkDevice device);
// This releases resources when they might currently be in use.
void release(RendererVk *renderer);
// This frees resources immediately.
void destroy(VkDevice device);
VkBuffer getCurrentBufferHandle() const;
// For testing only!
void setMinimumSizeForTesting(size_t minSize);
private:
VkBufferUsageFlags mUsage;
size_t mMinSize;
Buffer mBuffer;
DeviceMemory mMemory;
uint32_t mNextWriteOffset;
uint32_t mLastFlushOffset;
size_t mSize;
size_t mAlignment;
uint8_t *mMappedMemory;
};
// Uses DescriptorPool to allocate descriptor sets as needed. If the descriptor pool
// is full, we simply allocate a new pool to keep allocating descriptor sets as needed and
// leave the renderer take care of the life time of the pools that become unused.
enum DescriptorPoolIndex : uint8_t
{
UniformBufferIndex = 0,
TextureIndex = 1,
DescriptorPoolIndexCount = 2
};
class DynamicDescriptorPool final : angle::NonCopyable
{
public:
DynamicDescriptorPool();
~DynamicDescriptorPool();
void destroy(RendererVk *rendererVk);
Error init(const VkDevice &device,
uint32_t uniformBufferDescriptorsPerSet,
uint32_t combinedImageSamplerDescriptorsPerSet);
// It is an undefined behavior to pass a different descriptorSetLayout from call to call.
Error allocateDescriptorSets(ContextVk *contextVk,
const VkDescriptorSetLayout *descriptorSetLayout,
uint32_t descriptorSetCount,
VkDescriptorSet *descriptorSetsOut);
private:
Error allocateNewPool(const VkDevice &device);
DescriptorPool mCurrentDescriptorSetPool;
size_t mCurrentAllocatedDescriptorSetCount;
uint32_t mUniformBufferDescriptorsPerSet;
uint32_t mCombinedImageSamplerDescriptorsPerSet;
};
// This class' responsibility is to create index buffers needed to support line loops in Vulkan.
// In the setup phase of drawing, the createIndexBuffer method should be called with the
// current draw call parameters. If an element array buffer is bound for an indexed draw, use
// createIndexBufferFromElementArrayBuffer.
//
// If the user wants to draw a loop between [v1, v2, v3], we will create an indexed buffer with
// these indexes: [0, 1, 2, 3, 0] to emulate the loop.
class LineLoopHandler final : public vk::CommandGraphResource
{
public:
LineLoopHandler();
~LineLoopHandler();
gl::Error createIndexBuffer(RendererVk *renderer,
const gl::DrawCallParams &drawCallParams,
VkBuffer *bufferHandleOut,
VkDeviceSize *offsetOut);
gl::Error createIndexBufferFromElementArrayBuffer(RendererVk *renderer,
BufferVk *elementArrayBufferVk,
VkIndexType indexType,
int indexCount,
VkBuffer *bufferHandleOut,
VkDeviceSize *bufferOffsetOut);
void destroy(VkDevice device);
static void Draw(int count, CommandBuffer *commandBuffer);
private:
std::unique_ptr<DynamicBuffer> mDynamicLineLoopIndicesData;
};
class ImageHelper final : angle::NonCopyable
{
public:
ImageHelper();
ImageHelper(ImageHelper &&other);
~ImageHelper();
bool valid() const;
Error init2D(VkDevice device,
const gl::Extents &extents,
const Format &format,
GLint samples,
VkImageUsageFlags usage);
Error initMemory(VkDevice device,
const MemoryProperties &memoryProperties,
VkMemoryPropertyFlags flags);
Error initImageView(VkDevice device,
VkImageAspectFlags aspectMask,
const gl::SwizzleState &swizzleMap,
ImageView *imageViewOut);
Error init2DStaging(VkDevice device,
const MemoryProperties &memoryProperties,
const Format &format,
const gl::Extents &extent,
StagingUsage usage);
void release(Serial serial, RendererVk *renderer);
void destroy(VkDevice device);
void dumpResources(Serial serial, std::vector<GarbageObject> *garbageQueue);
void init2DWeakReference(VkImage handle,
const gl::Extents &extents,
const Format &format,
GLint samples);
void resetImageWeakReference();
const Image &getImage() const;
const DeviceMemory &getDeviceMemory() const;
const gl::Extents &getExtents() const;
const Format &getFormat() const;
GLint getSamples() const;
size_t getAllocatedMemorySize() const;
VkImageLayout getCurrentLayout() const { return mCurrentLayout; }
void updateLayout(VkImageLayout layout) { mCurrentLayout = layout; }
void changeLayoutWithStages(VkImageAspectFlags aspectMask,
VkImageLayout newLayout,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
CommandBuffer *commandBuffer);
void clearColor(const VkClearColorValue &color, CommandBuffer *commandBuffer);
void clearDepthStencil(VkImageAspectFlags aspectFlags,
const VkClearDepthStencilValue &depthStencil,
CommandBuffer *commandBuffer);
static void Copy(ImageHelper *srcImage,
ImageHelper *dstImage,
const gl::Offset &srcOffset,
const gl::Offset &dstOffset,
const gl::Extents &copySize,
VkImageAspectFlags aspectMask,
CommandBuffer *commandBuffer);
private:
// Vulkan objects.
Image mImage;
DeviceMemory mDeviceMemory;
// Image properties.
gl::Extents mExtents;
const Format *mFormat;
GLint mSamples;
size_t mAllocatedMemorySize;
// Current state.
VkImageLayout mCurrentLayout;
};
} // namespace vk
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_
...@@ -53,11 +53,10 @@ ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_OBJECT); ...@@ -53,11 +53,10 @@ ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_OBJECT);
namespace rx namespace rx
{ {
class CommandGraphResource;
class DisplayVk; class DisplayVk;
class DynamicBuffer;
class RenderTargetVk; class RenderTargetVk;
class RendererVk; class RendererVk;
class ResourceVk;
class RenderPassCache; class RenderPassCache;
ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_VK_OBJECT); ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_VK_OBJECT);
...@@ -636,127 +635,12 @@ struct BufferAndMemory final : private angle::NonCopyable ...@@ -636,127 +635,12 @@ struct BufferAndMemory final : private angle::NonCopyable
DeviceMemory memory; DeviceMemory memory;
}; };
Error AllocateImageMemory(RendererVk *renderer, Error AllocateImageMemory(VkDevice device,
const MemoryProperties &memoryProperties,
VkMemoryPropertyFlags memoryPropertyFlags, VkMemoryPropertyFlags memoryPropertyFlags,
Image *image, Image *image,
DeviceMemory *deviceMemoryOut, DeviceMemory *deviceMemoryOut,
size_t *requiredSizeOut); size_t *requiredSizeOut);
// This class' responsibility is to create index buffers needed to support line loops in Vulkan.
// In the setup phase of drawing, the createIndexBuffer method should be called with the
// current draw call parameters. If an element array buffer is bound for an indexed draw, use
// createIndexBufferFromElementArrayBuffer.
//
// If the user wants to draw a loop between [v1, v2, v3], we will create an indexed buffer with
// these indexes: [0, 1, 2, 3, 0] to emulate the loop.
class LineLoopHandler final : angle::NonCopyable
{
public:
LineLoopHandler();
~LineLoopHandler();
gl::Error createIndexBuffer(RendererVk *renderer,
const gl::DrawCallParams &drawCallParams,
VkBuffer *bufferHandleOut,
VkDeviceSize *offsetOut);
gl::Error createIndexBufferFromElementArrayBuffer(RendererVk *renderer,
BufferVk *elementArrayBufferVk,
VkIndexType indexType,
int indexCount,
VkBuffer *bufferHandleOut,
VkDeviceSize *bufferOffsetOut);
void destroy(VkDevice device);
static void Draw(int count, CommandBuffer *commandBuffer);
ResourceVk *getLineLoopBufferResource();
private:
std::unique_ptr<DynamicBuffer> mDynamicLineLoopIndicesData;
};
class ImageHelper final : angle::NonCopyable
{
public:
ImageHelper();
ImageHelper(ImageHelper &&other);
~ImageHelper();
bool valid() const;
Error init2D(VkDevice device,
const gl::Extents &extents,
const Format &format,
GLint samples,
VkImageUsageFlags usage);
Error initMemory(VkDevice device,
const MemoryProperties &memoryProperties,
VkMemoryPropertyFlags flags);
Error initImageView(VkDevice device,
VkImageAspectFlags aspectMask,
const gl::SwizzleState &swizzleMap,
ImageView *imageViewOut);
Error init2DStaging(VkDevice device,
const MemoryProperties &memoryProperties,
const Format &format,
const gl::Extents &extent,
StagingUsage usage);
void release(Serial serial, RendererVk *renderer);
void destroy(VkDevice device);
void dumpResources(Serial serial, std::vector<GarbageObject> *garbageQueue);
void init2DWeakReference(VkImage handle,
const gl::Extents &extents,
const Format &format,
GLint samples);
void resetImageWeakReference();
const Image &getImage() const;
const DeviceMemory &getDeviceMemory() const;
const gl::Extents &getExtents() const;
const Format &getFormat() const;
GLint getSamples() const;
size_t getAllocatedMemorySize() const;
VkImageLayout getCurrentLayout() const { return mCurrentLayout; }
void updateLayout(VkImageLayout layout) { mCurrentLayout = layout; }
void changeLayoutWithStages(VkImageAspectFlags aspectMask,
VkImageLayout newLayout,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
CommandBuffer *commandBuffer);
void clearColor(const VkClearColorValue &color, CommandBuffer *commandBuffer);
void clearDepthStencil(VkImageAspectFlags aspectFlags,
const VkClearDepthStencilValue &depthStencil,
CommandBuffer *commandBuffer);
static void Copy(ImageHelper *srcImage,
ImageHelper *dstImage,
const gl::Offset &srcOffset,
const gl::Offset &dstOffset,
const gl::Extents &copySize,
VkImageAspectFlags aspectMask,
CommandBuffer *commandBuffer);
private:
// Vulkan objects.
Image mImage;
DeviceMemory mDeviceMemory;
// Image properties.
gl::Extents mExtents;
const Format *mFormat;
GLint mSamples;
size_t mAllocatedMemorySize;
// Current state.
VkImageLayout mCurrentLayout;
};
} // namespace vk } // namespace vk
namespace gl_vk namespace gl_vk
...@@ -769,46 +653,6 @@ VkComponentSwizzle GetSwizzle(const GLenum swizzle); ...@@ -769,46 +653,6 @@ VkComponentSwizzle GetSwizzle(const GLenum swizzle);
VkIndexType GetIndexType(GLenum elementType); VkIndexType GetIndexType(GLenum elementType);
} // namespace gl_vk } // namespace gl_vk
// This is a helper class for back-end objects used in Vk command buffers. It records a serial
// at command recording times indicating an order in the queue. We use Fences to detect when
// commands finish, and then release any unreferenced and deleted resources based on the stored
// queue serial in a special 'garbage' queue. Resources also track current read and write
// dependencies. Only one command buffer node can be writing to the Resource at a time, but many
// can be reading from it. Together the dependencies will form a command graph at submission time.
class ResourceVk
{
public:
ResourceVk();
virtual ~ResourceVk();
void updateQueueSerial(Serial queueSerial);
Serial getQueueSerial() const;
// Returns true if any tracked read or write nodes match 'currentSerial'.
bool hasCurrentWritingNode(Serial currentSerial) const;
// Returns the active write node, and asserts 'currentSerial' matches the stored serial.
vk::CommandGraphNode *getCurrentWritingNode(Serial currentSerial);
// Allocates a new write node and calls onWriteResource internally.
vk::CommandGraphNode *getNewWritingNode(RendererVk *renderer);
// Allocates a write node via getNewWriteNode and returns a started command buffer.
// The started command buffer will render outside of a RenderPass.
vk::Error beginWriteResource(RendererVk *renderer, vk::CommandBuffer **commandBufferOut);
// Sets up dependency relations. 'writingNode' will modify 'this' ResourceVk.
void onWriteResource(vk::CommandGraphNode *writingNode, Serial serial);
// Sets up dependency relations. 'readingNode' will read from 'this' ResourceVk.
void onReadResource(vk::CommandGraphNode *readingNode, Serial serial);
private:
Serial mStoredQueueSerial;
std::vector<vk::CommandGraphNode *> mCurrentReadingNodes;
vk::CommandGraphNode *mCurrentWritingNode;
};
} // namespace rx } // namespace rx
#define ANGLE_VK_TRY(command) \ #define ANGLE_VK_TRY(command) \
......
...@@ -758,10 +758,6 @@ ...@@ -758,10 +758,6 @@
'libANGLE/renderer/vulkan/DeviceVk.h', 'libANGLE/renderer/vulkan/DeviceVk.h',
'libANGLE/renderer/vulkan/DisplayVk.cpp', 'libANGLE/renderer/vulkan/DisplayVk.cpp',
'libANGLE/renderer/vulkan/DisplayVk.h', 'libANGLE/renderer/vulkan/DisplayVk.h',
'libANGLE/renderer/vulkan/DynamicBuffer.h',
'libANGLE/renderer/vulkan/DynamicBuffer.cpp',
'libANGLE/renderer/vulkan/DynamicDescriptorPool.cpp',
'libANGLE/renderer/vulkan/DynamicDescriptorPool.h',
'libANGLE/renderer/vulkan/FenceNVVk.cpp', 'libANGLE/renderer/vulkan/FenceNVVk.cpp',
'libANGLE/renderer/vulkan/FenceNVVk.h', 'libANGLE/renderer/vulkan/FenceNVVk.h',
'libANGLE/renderer/vulkan/FramebufferVk.cpp', 'libANGLE/renderer/vulkan/FramebufferVk.cpp',
...@@ -803,6 +799,8 @@ ...@@ -803,6 +799,8 @@
'libANGLE/renderer/vulkan/vk_format_table_autogen.cpp', 'libANGLE/renderer/vulkan/vk_format_table_autogen.cpp',
'libANGLE/renderer/vulkan/vk_format_utils.h', 'libANGLE/renderer/vulkan/vk_format_utils.h',
'libANGLE/renderer/vulkan/vk_format_utils.cpp', 'libANGLE/renderer/vulkan/vk_format_utils.cpp',
'libANGLE/renderer/vulkan/vk_helpers.cpp',
'libANGLE/renderer/vulkan/vk_helpers.h',
'libANGLE/renderer/vulkan/vk_mandatory_format_support_table_autogen.cpp', 'libANGLE/renderer/vulkan/vk_mandatory_format_support_table_autogen.cpp',
'libANGLE/renderer/vulkan/vk_utils.cpp', 'libANGLE/renderer/vulkan/vk_utils.cpp',
'libANGLE/renderer/vulkan/vk_utils.h', 'libANGLE/renderer/vulkan/vk_utils.h',
......
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