Hash :
701d51b1
Author :
Date :
2022-01-25T15:44:39
Vulkan: Add SmallBufferPool for small allocations The small pool uses buddy algorithm that is much faster. The only downside is that it rounds size to power of two. For small allocations that rounding does not generate much waste and avoid fragmentation as well. This CL adds a small pool for host visible non-coherent pool. My testing with gardenscape shows that on top of other CLs, this reduces CPU overhead from 1.77ms to 1.55ms as measured with --minimize-gpu-work with offscreen. Bug: b/215768827 Change-Id: I68434931f238c4e980b77d3df46d762260ef1db5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3415211 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Ian Elliott <ianelliott@google.com> Commit-Queue: Charlie Lao <cclao@google.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
//
// Copyright 2016 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.
//
// DisplayVk.h:
// Defines the class interface for DisplayVk, implementing DisplayImpl.
//
#ifndef LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_
#define LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_
#include "common/MemoryBuffer.h"
#include "libANGLE/renderer/DisplayImpl.h"
#include "libANGLE/renderer/vulkan/ResourceVk.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
{
class RendererVk;
using ContextVkSet = std::set<ContextVk *>;
class ShareGroupVk : public ShareGroupImpl
{
public:
ShareGroupVk();
void onDestroy(const egl::Display *display) override;
// PipelineLayoutCache and DescriptorSetLayoutCache can be shared between multiple threads
// accessing them via shared contexts. The ShareGroup locks around gl entrypoints ensuring
// synchronous update to the caches.
PipelineLayoutCache &getPipelineLayoutCache() { return mPipelineLayoutCache; }
DescriptorSetLayoutCache &getDescriptorSetLayoutCache() { return mDescriptorSetLayoutCache; }
ContextVkSet *getContexts() { return &mContexts; }
std::vector<vk::ResourceUseList> &&releaseResourceUseLists()
{
return std::move(mResourceUseLists);
}
void acquireResourceUseList(vk::ResourceUseList &&resourceUseList)
{
mResourceUseLists.emplace_back(std::move(resourceUseList));
}
vk::BufferPool *getDefaultBufferPool(RendererVk *renderer,
VkDeviceSize size,
uint32_t memoryTypeIndex);
void pruneDefaultBufferPools(RendererVk *renderer);
bool isDueForBufferPoolPrune();
private:
// ANGLE uses a PipelineLayout cache to store compatible pipeline layouts.
PipelineLayoutCache mPipelineLayoutCache;
// DescriptorSetLayouts are also managed in a cache.
DescriptorSetLayoutCache mDescriptorSetLayoutCache;
// The list of contexts within the share group
ContextVkSet mContexts;
// List of resources currently used that need to be freed when any ContextVk in this
// ShareGroupVk submits the next command.
std::vector<vk::ResourceUseList> mResourceUseLists;
// The per shared group buffer pools that all buffers should sub-allocate from.
vk::BufferPoolPointerArray mDefaultBufferPools;
// The pool dedicated for small allocations that uses faster buddy algorithm
std::unique_ptr<vk::BufferPool> mSmallBufferPool;
static constexpr VkDeviceSize kMaxSizeToUseSmallBufferPool = 256;
// The system time when last pruneEmptyBuffer gets called.
double mLastPruneTime;
};
class DisplayVk : public DisplayImpl, public vk::Context
{
public:
DisplayVk(const egl::DisplayState &state);
~DisplayVk() override;
egl::Error initialize(egl::Display *display) override;
void terminate() override;
egl::Error makeCurrent(egl::Display *display,
egl::Surface *drawSurface,
egl::Surface *readSurface,
gl::Context *context) override;
bool testDeviceLost() override;
egl::Error restoreLostDevice(const egl::Display *display) override;
std::string getRendererDescription() override;
std::string getVendorString() override;
std::string getVersionString() override;
DeviceImpl *createDevice() override;
egl::Error waitClient(const gl::Context *context) override;
egl::Error waitNative(const gl::Context *context, EGLint engine) override;
SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
EGLNativeWindowType window,
const egl::AttributeMap &attribs) override;
SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
const egl::AttributeMap &attribs) override;
SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) override;
SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
NativePixmapType nativePixmap,
const egl::AttributeMap &attribs) override;
ImageImpl *createImage(const egl::ImageState &state,
const gl::Context *context,
EGLenum target,
const egl::AttributeMap &attribs) override;
ContextImpl *createContext(const gl::State &state,
gl::ErrorSet *errorSet,
const egl::Config *configuration,
const gl::Context *shareContext,
const egl::AttributeMap &attribs) override;
StreamProducerImpl *createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,
const egl::AttributeMap &attribs) override;
EGLSyncImpl *createSync(const egl::AttributeMap &attribs) override;
gl::Version getMaxSupportedESVersion() const override;
gl::Version getMaxConformantESVersion() const override;
egl::Error validateImageClientBuffer(const gl::Context *context,
EGLenum target,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const override;
ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs) override;
virtual const char *getWSIExtension() const = 0;
virtual const char *getWSILayer() const;
virtual bool isUsingSwapchain() const;
// Determine if a config with given formats and sample counts is supported. This callback may
// modify the config to add or remove platform specific attributes such as nativeVisualID. If
// the config is not supported by the window system, it removes the EGL_WINDOW_BIT from
// surfaceType, which would still allow the config to be used for pbuffers.
virtual void checkConfigSupport(egl::Config *config) = 0;
ANGLE_NO_DISCARD bool getScratchBuffer(size_t requestedSizeBytes,
angle::MemoryBuffer **scratchBufferOut) const;
angle::ScratchBuffer *getScratchBuffer() const { return &mScratchBuffer; }
void handleError(VkResult result,
const char *file,
const char *function,
unsigned int line) override;
// TODO(jmadill): Remove this once refactor is done. http://anglebug.com/3041
egl::Error getEGLError(EGLint errorCode);
void populateFeatureList(angle::FeatureList *features) override;
ShareGroupImpl *createShareGroup() override;
protected:
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
private:
virtual SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state,
EGLNativeWindowType window) = 0;
void generateCaps(egl::Caps *outCaps) const override;
virtual angle::Result waitNativeImpl();
mutable angle::ScratchBuffer mScratchBuffer;
vk::Error mSavedError;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_