Commit 996628a4 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Add support for VkPipelineCache

The cache is initialized from the application's blob cache and is occasionally written back to it for disk storage. Bug: angleproject:2516 Change-Id: I4cba4b00a7b9641c2983ef07159bc62cd10a5519 Reviewed-on: https://chromium-review.googlesource.com/1241373Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent 5ddbdbf7
...@@ -956,7 +956,7 @@ if (is_android) { ...@@ -956,7 +956,7 @@ if (is_android) {
} }
android_apk("angle_apk") { android_apk("angle_apk") {
deps = [ deps = [
":angle_apk_assets" ":angle_apk_assets",
] ]
if (build_apk_secondary_abi && android_64bit_target_cpu) { if (build_apk_secondary_abi && android_64bit_target_cpu) {
secondary_abi_shared_libraries = [ secondary_abi_shared_libraries = [
......
...@@ -15,10 +15,6 @@ namespace angle ...@@ -15,10 +15,6 @@ namespace angle
{ {
// MemoryBuffer implementation. // MemoryBuffer implementation.
MemoryBuffer::MemoryBuffer() : mSize(0), mData(nullptr)
{
}
MemoryBuffer::~MemoryBuffer() MemoryBuffer::~MemoryBuffer()
{ {
free(mData); free(mData);
......
...@@ -20,7 +20,8 @@ namespace angle ...@@ -20,7 +20,8 @@ namespace angle
class MemoryBuffer final : NonCopyable class MemoryBuffer final : NonCopyable
{ {
public: public:
MemoryBuffer(); MemoryBuffer() = default;
MemoryBuffer(size_t size) { resize(size); }
~MemoryBuffer(); ~MemoryBuffer();
MemoryBuffer(MemoryBuffer &&other); MemoryBuffer(MemoryBuffer &&other);
...@@ -51,8 +52,8 @@ class MemoryBuffer final : NonCopyable ...@@ -51,8 +52,8 @@ class MemoryBuffer final : NonCopyable
void fill(uint8_t datum); void fill(uint8_t datum);
private: private:
size_t mSize; size_t mSize = 0;
uint8_t *mData; uint8_t *mData = nullptr;
}; };
class ScratchBuffer final : NonCopyable class ScratchBuffer final : NonCopyable
......
...@@ -52,6 +52,14 @@ void BlobCache::put(const BlobCache::Key &key, angle::MemoryBuffer &&value) ...@@ -52,6 +52,14 @@ void BlobCache::put(const BlobCache::Key &key, angle::MemoryBuffer &&value)
} }
} }
void BlobCache::putApplication(const BlobCache::Key &key, const angle::MemoryBuffer &value)
{
if (areBlobCacheFuncsSet())
{
mSetBlobFunc(key.data(), key.size(), value.data(), value.size());
}
}
void BlobCache::populate(const BlobCache::Key &key, angle::MemoryBuffer &&value, CacheSource source) void BlobCache::populate(const BlobCache::Key &key, angle::MemoryBuffer &&value, CacheSource source)
{ {
CacheEntry newEntry; CacheEntry newEntry;
...@@ -66,7 +74,7 @@ void BlobCache::populate(const BlobCache::Key &key, angle::MemoryBuffer &&value, ...@@ -66,7 +74,7 @@ void BlobCache::populate(const BlobCache::Key &key, angle::MemoryBuffer &&value,
} }
} }
bool BlobCache::get(const gl::Context *context, bool BlobCache::get(angle::ScratchBuffer *scratchBuffer,
const BlobCache::Key &key, const BlobCache::Key &key,
BlobCache::Value *valueOut) BlobCache::Value *valueOut)
{ {
...@@ -79,19 +87,19 @@ bool BlobCache::get(const gl::Context *context, ...@@ -79,19 +87,19 @@ bool BlobCache::get(const gl::Context *context,
return false; return false;
} }
angle::MemoryBuffer *scratchBuffer; angle::MemoryBuffer *scratchMemory;
bool result = context->getScratchBuffer(valueSize, &scratchBuffer); bool result = scratchBuffer->get(valueSize, &scratchMemory);
if (!result) if (!result)
{ {
ERR() << "Failed to allocate memory for binary blob"; ERR() << "Failed to allocate memory for binary blob";
return false; return false;
} }
valueSize = mGetBlobFunc(key.data(), key.size(), scratchBuffer->data(), valueSize); valueSize = mGetBlobFunc(key.data(), key.size(), scratchMemory->data(), valueSize);
// Make sure the key/value pair still exists/is unchanged after the second call // Make sure the key/value pair still exists/is unchanged after the second call
// (modifications to the application cache by another thread are a possibility) // (modifications to the application cache by another thread are a possibility)
if (static_cast<size_t>(valueSize) != scratchBuffer->size()) if (static_cast<size_t>(valueSize) != scratchMemory->size())
{ {
// This warning serves to find issues with the application cache, none of which are // This warning serves to find issues with the application cache, none of which are
// currently known to be thread-safe. If such a use ever arises, this WARN can be // currently known to be thread-safe. If such a use ever arises, this WARN can be
...@@ -100,7 +108,7 @@ bool BlobCache::get(const gl::Context *context, ...@@ -100,7 +108,7 @@ bool BlobCache::get(const gl::Context *context,
return false; return false;
} }
*valueOut = BlobCache::Value(scratchBuffer->data(), scratchBuffer->size()); *valueOut = BlobCache::Value(scratchMemory->data(), scratchMemory->size());
return true; return true;
} }
......
...@@ -61,7 +61,7 @@ class BlobCache final : angle::NonCopyable ...@@ -61,7 +61,7 @@ class BlobCache final : angle::NonCopyable
Value(const uint8_t *ptr, size_t sz) : mPtr(ptr), mSize(sz) {} Value(const uint8_t *ptr, size_t sz) : mPtr(ptr), mSize(sz) {}
// A very basic struct to hold the pointer and size together. The objects of this class // A very basic struct to hold the pointer and size together. The objects of this class
// doesn't own the memory. // don't own the memory.
const uint8_t *data() { return mPtr; } const uint8_t *data() { return mPtr; }
size_t size() { return mSize; } size_t size() { return mSize; }
...@@ -88,6 +88,9 @@ class BlobCache final : angle::NonCopyable ...@@ -88,6 +88,9 @@ class BlobCache final : angle::NonCopyable
// will be used. Otherwise the value is cached in this object. // will be used. Otherwise the value is cached in this object.
void put(const BlobCache::Key &key, angle::MemoryBuffer &&value); void put(const BlobCache::Key &key, angle::MemoryBuffer &&value);
// Store a key-blob pair in the application cache, only if application callbacks are set.
void putApplication(const BlobCache::Key &key, const angle::MemoryBuffer &value);
// Store a key-blob pair in the cache without making callbacks to the application. This is used // Store a key-blob pair in the cache without making callbacks to the application. This is used
// to repopulate this object's cache on startup without generating callback calls. // to repopulate this object's cache on startup without generating callback calls.
void populate(const BlobCache::Key &key, void populate(const BlobCache::Key &key,
...@@ -96,10 +99,14 @@ class BlobCache final : angle::NonCopyable ...@@ -96,10 +99,14 @@ class BlobCache final : angle::NonCopyable
// Check if the cache contains the blob corresponding to this key. If application callbacks are // Check if the cache contains the blob corresponding to this key. If application callbacks are
// set, those will be used. Otherwise they key is looked up in this object's cache. // set, those will be used. Otherwise they key is looked up in this object's cache.
bool get(const gl::Context *context, const BlobCache::Key &key, BlobCache::Value *valueOut); ANGLE_NO_DISCARD bool get(angle::ScratchBuffer *scratchBuffer,
const BlobCache::Key &key,
BlobCache::Value *valueOut);
// For querying the contents of the cache. // For querying the contents of the cache.
bool getAt(size_t index, const BlobCache::Key **keyOut, BlobCache::Value *valueOut); ANGLE_NO_DISCARD bool getAt(size_t index,
const BlobCache::Key **keyOut,
BlobCache::Value *valueOut);
// Evict a blob from the binary cache. // Evict a blob from the binary cache.
void remove(const BlobCache::Key &key); void remove(const BlobCache::Key &key);
......
...@@ -1543,6 +1543,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl ...@@ -1543,6 +1543,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
angle::MemoryBuffer **scratchBufferOut) const; angle::MemoryBuffer **scratchBufferOut) const;
ANGLE_NO_DISCARD bool getZeroFilledBuffer(size_t requstedSizeBytes, ANGLE_NO_DISCARD bool getZeroFilledBuffer(size_t requstedSizeBytes,
angle::MemoryBuffer **zeroBufferOut) const; angle::MemoryBuffer **zeroBufferOut) const;
angle::ScratchBuffer *getScratchBuffer() const { return &mScratchBuffer; }
Error prepareForDispatch(); Error prepareForDispatch();
......
...@@ -447,6 +447,8 @@ void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap ...@@ -447,6 +447,8 @@ void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap
Error Display::initialize() Error Display::initialize()
{ {
mImplementation->setBlobCache(&mBlobCache);
// TODO(jmadill): Store Platform in Display and init here. // TODO(jmadill): Store Platform in Display and init here.
const angle::PlatformMethods *platformMethods = const angle::PlatformMethods *platformMethods =
reinterpret_cast<const angle::PlatformMethods *>( reinterpret_cast<const angle::PlatformMethods *>(
......
...@@ -113,13 +113,13 @@ namespace angle ...@@ -113,13 +113,13 @@ namespace angle
{ {
Result::operator gl::Error() const Result::operator gl::Error() const
{ {
if (mStop) if (mResult == ResultValue::kContinue)
{ {
return gl::Error(GL_INTERNAL_ERROR_ANGLEX); return gl::NoError();
} }
else else
{ {
return gl::NoError(); return gl::Error(GL_INTERNAL_ERROR_ANGLEX);
} }
} }
} // namespace angle } // namespace angle
...@@ -241,16 +241,15 @@ inline Error NoError() ...@@ -241,16 +241,15 @@ inline Error NoError()
// TODO(jmadill): Remove this once refactor is complete. http://anglebug.com/2491 // TODO(jmadill): Remove this once refactor is complete. http://anglebug.com/2491
#define ANGLE_TRY_HANDLE(CONTEXT, EXPR) \ #define ANGLE_TRY_HANDLE(CONTEXT, EXPR) \
\ { \
{ \
auto ANGLE_LOCAL_VAR = (EXPR); \ auto ANGLE_LOCAL_VAR = (EXPR); \
if (ANGLE_UNLIKELY(ANGLE_LOCAL_VAR.isError())) \ if (ANGLE_UNLIKELY(ANGLE_LOCAL_VAR.isError())) \
{ \ { \
CONTEXT->handleError(ANGLE_LOCAL_VAR); \ CONTEXT->handleError(ANGLE_LOCAL_VAR); \
return angle::Result::Stop(); \ return angle::Result::Stop(); \
} \ } \
\ } \
} ANGLE_EMPTY_STATEMENT
#define ANGLE_TRY_RESULT(EXPR, RESULT) \ #define ANGLE_TRY_RESULT(EXPR, RESULT) \
{ \ { \
...@@ -281,15 +280,20 @@ inline Error NoError() ...@@ -281,15 +280,20 @@ inline Error NoError()
namespace angle namespace angle
{ {
// Result signals if calling code should continue running or early exit. A value of Stop() can // Result signals if calling code should continue running or early exit. A value of Stop() can
// either indicate and Error or a non-Error early exit condition such as a detected no-op. // either indicate an Error or a non-Error early exit condition such as a detected no-op. A few
// other values exist to signal special cases that are neither success nor failure but require
// special attention.
class ANGLE_NO_DISCARD Result class ANGLE_NO_DISCARD Result
{ {
public: public:
// TODO(jmadill): Rename when refactor is complete. http://anglebug.com/2491 // TODO(jmadill): Rename when refactor is complete. http://anglebug.com/2491
bool isError() const { return mStop; } bool isError() const { return mResult == ResultValue::kStop; }
Result getError() { return *this; }
Result getResult() { return *this; }
static Result Stop() { return Result(true); } static Result Continue() { return Result(ResultValue::kContinue); }
static Result Continue() { return Result(false); } static Result Stop() { return Result(ResultValue::kStop); }
static Result Incomplete() { return Result(ResultValue::kIncomplete); }
// TODO(jmadill): Remove when refactor is complete. http://anglebug.com/2491 // TODO(jmadill): Remove when refactor is complete. http://anglebug.com/2491
operator gl::Error() const; operator gl::Error() const;
...@@ -301,13 +305,20 @@ class ANGLE_NO_DISCARD Result ...@@ -301,13 +305,20 @@ class ANGLE_NO_DISCARD Result
return operator gl::Error(); return operator gl::Error();
} }
bool operator==(Result other) const { return mStop == other.mStop; } bool operator==(Result other) const { return mResult == other.mResult; }
bool operator!=(Result other) const { return mStop != other.mStop; } bool operator!=(Result other) const { return mResult != other.mResult; }
private: private:
Result(bool stop) : mStop(stop) {} enum class ResultValue
bool mStop; {
kContinue = 0,
kStop,
kIncomplete,
};
Result(ResultValue stop) : mResult(stop) {}
ResultValue mResult;
}; };
} // namespace angle } // namespace angle
......
...@@ -681,7 +681,7 @@ bool MemoryProgramCache::get(const Context *context, ...@@ -681,7 +681,7 @@ bool MemoryProgramCache::get(const Context *context,
const egl::BlobCache::Key &programHash, const egl::BlobCache::Key &programHash,
egl::BlobCache::Value *programOut) egl::BlobCache::Value *programOut)
{ {
return mBlobCache.get(context, programHash, programOut); return mBlobCache.get(context->getScratchBuffer(), programHash, programOut);
} }
bool MemoryProgramCache::getAt(size_t index, bool MemoryProgramCache::getAt(size_t index,
......
...@@ -15,7 +15,7 @@ namespace rx ...@@ -15,7 +15,7 @@ namespace rx
{ {
DisplayImpl::DisplayImpl(const egl::DisplayState &state) DisplayImpl::DisplayImpl(const egl::DisplayState &state)
: mState(state), mExtensionsInitialized(false), mCapsInitialized(false) : mState(state), mExtensionsInitialized(false), mCapsInitialized(false), mBlobCache(nullptr)
{ {
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
namespace egl namespace egl
{ {
class AttributeMap; class AttributeMap;
class BlobCache;
class Display; class Display;
struct DisplayState; struct DisplayState;
struct Config; struct Config;
...@@ -79,6 +80,9 @@ class DisplayImpl : public EGLImplFactory ...@@ -79,6 +80,9 @@ class DisplayImpl : public EGLImplFactory
const egl::DisplayExtensions &getExtensions() const; const egl::DisplayExtensions &getExtensions() const;
void setBlobCache(egl::BlobCache *blobCache) { mBlobCache = blobCache; }
egl::BlobCache *getBlobCache() const { return mBlobCache; }
protected: protected:
const egl::DisplayState &mState; const egl::DisplayState &mState;
...@@ -91,6 +95,8 @@ class DisplayImpl : public EGLImplFactory ...@@ -91,6 +95,8 @@ class DisplayImpl : public EGLImplFactory
mutable bool mCapsInitialized; mutable bool mCapsInitialized;
mutable egl::Caps mCaps; mutable egl::Caps mCaps;
egl::BlobCache *mBlobCache;
}; };
} }
......
...@@ -150,6 +150,8 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer) ...@@ -150,6 +150,8 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
mDirtyBits = mNewCommandBufferDirtyBits; mDirtyBits = mNewCommandBufferDirtyBits;
} }
#undef INIT
ContextVk::~ContextVk() = default; ContextVk::~ContextVk() = default;
void ContextVk::onDestroy(const gl::Context *context) void ContextVk::onDestroy(const gl::Context *context)
......
...@@ -20,7 +20,7 @@ namespace rx ...@@ -20,7 +20,7 @@ namespace rx
{ {
DisplayVk::DisplayVk(const egl::DisplayState &state) DisplayVk::DisplayVk(const egl::DisplayState &state)
: DisplayImpl(state), vk::Context(new RendererVk()) : DisplayImpl(state), vk::Context(new RendererVk()), mScratchBuffer(1000u)
{ {
} }
...@@ -181,6 +181,12 @@ void DisplayVk::generateCaps(egl::Caps *outCaps) const ...@@ -181,6 +181,12 @@ void DisplayVk::generateCaps(egl::Caps *outCaps) const
outCaps->textureNPOT = true; outCaps->textureNPOT = true;
} }
bool DisplayVk::getScratchBuffer(size_t requstedSizeBytes,
angle::MemoryBuffer **scratchBufferOut) const
{
return mScratchBuffer.get(requstedSizeBytes, scratchBufferOut);
}
void DisplayVk::handleError(VkResult result, const char *file, unsigned int line) void DisplayVk::handleError(VkResult result, const char *file, unsigned int line)
{ {
std::stringstream errorStream; std::stringstream errorStream;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#ifndef LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_ #ifndef LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_
#define LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_ #define LIBANGLE_RENDERER_VULKAN_DISPLAYVK_H_
#include "common/MemoryBuffer.h"
#include "libANGLE/renderer/DisplayImpl.h" #include "libANGLE/renderer/DisplayImpl.h"
#include "libANGLE/renderer/vulkan/vk_utils.h" #include "libANGLE/renderer/vulkan/vk_utils.h"
...@@ -74,6 +75,10 @@ class DisplayVk : public DisplayImpl, public vk::Context ...@@ -74,6 +75,10 @@ class DisplayVk : public DisplayImpl, public vk::Context
// returning a bool to indicate if the config should be supported. // returning a bool to indicate if the config should be supported.
virtual bool checkConfigSupport(egl::Config *config) = 0; virtual bool 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, unsigned int line) override; void handleError(VkResult result, const char *file, unsigned int line) override;
// TODO(jmadill): Remove this once refactor is done. http://anglebug.com/2491 // TODO(jmadill): Remove this once refactor is done. http://anglebug.com/2491
...@@ -87,6 +92,8 @@ class DisplayVk : public DisplayImpl, public vk::Context ...@@ -87,6 +92,8 @@ class DisplayVk : public DisplayImpl, public vk::Context
void generateExtensions(egl::DisplayExtensions *outExtensions) const override; void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
void generateCaps(egl::Caps *outCaps) const override; void generateCaps(egl::Caps *outCaps) const override;
mutable angle::ScratchBuffer mScratchBuffer;
std::string mStoredErrorString; std::string mStoredErrorString;
}; };
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <memory> #include <memory>
#include "common/angleutils.h" #include "common/angleutils.h"
#include "libANGLE/BlobCache.h"
#include "libANGLE/Caps.h" #include "libANGLE/Caps.h"
#include "libANGLE/renderer/vulkan/CommandGraph.h" #include "libANGLE/renderer/vulkan/CommandGraph.h"
#include "libANGLE/renderer/vulkan/FeaturesVk.h" #include "libANGLE/renderer/vulkan/FeaturesVk.h"
...@@ -23,10 +24,12 @@ ...@@ -23,10 +24,12 @@
namespace egl namespace egl
{ {
class AttributeMap; class AttributeMap;
class BlobCache;
} }
namespace rx namespace rx
{ {
class DisplayVk;
class FramebufferVk; class FramebufferVk;
namespace vk namespace vk
...@@ -40,7 +43,7 @@ class RendererVk : angle::NonCopyable ...@@ -40,7 +43,7 @@ class RendererVk : angle::NonCopyable
RendererVk(); RendererVk();
~RendererVk(); ~RendererVk();
angle::Result initialize(vk::Context *context, angle::Result initialize(DisplayVk *displayVk,
const egl::AttributeMap &attribs, const egl::AttributeMap &attribs,
const char *wsiName); const char *wsiName);
void onDestroy(vk::Context *context); void onDestroy(vk::Context *context);
...@@ -57,7 +60,7 @@ class RendererVk : angle::NonCopyable ...@@ -57,7 +60,7 @@ class RendererVk : angle::NonCopyable
VkQueue getQueue() const { return mQueue; } VkQueue getQueue() const { return mQueue; }
VkDevice getDevice() const { return mDevice; } VkDevice getDevice() const { return mDevice; }
angle::Result selectPresentQueueForSurface(vk::Context *context, angle::Result selectPresentQueueForSurface(DisplayVk *displayVk,
VkSurfaceKHR surface, VkSurfaceKHR surface,
uint32_t *presentQueueOut); uint32_t *presentQueueOut);
...@@ -132,6 +135,8 @@ class RendererVk : angle::NonCopyable ...@@ -132,6 +135,8 @@ class RendererVk : angle::NonCopyable
const vk::DescriptorSetLayoutPointerArray &descriptorSetLayouts, const vk::DescriptorSetLayoutPointerArray &descriptorSetLayouts,
vk::BindingPointer<vk::PipelineLayout> *pipelineLayoutOut); vk::BindingPointer<vk::PipelineLayout> *pipelineLayoutOut);
angle::Result syncPipelineCacheVk(DisplayVk *displayVk);
// This should only be called from ResourceVk. // This should only be called from ResourceVk.
// TODO(jmadill): Keep in ContextVk to enable threaded rendering. // TODO(jmadill): Keep in ContextVk to enable threaded rendering.
vk::CommandGraph *getCommandGraph(); vk::CommandGraph *getCommandGraph();
...@@ -143,7 +148,7 @@ class RendererVk : angle::NonCopyable ...@@ -143,7 +148,7 @@ class RendererVk : angle::NonCopyable
const FeaturesVk &getFeatures() const { return mFeatures; } const FeaturesVk &getFeatures() const { return mFeatures; }
private: private:
angle::Result initializeDevice(vk::Context *context, uint32_t queueFamilyIndex); angle::Result initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex);
void ensureCapsInitialized() const; void ensureCapsInitialized() const;
angle::Result submitFrame(vk::Context *context, angle::Result submitFrame(vk::Context *context,
const VkSubmitInfo &submitInfo, const VkSubmitInfo &submitInfo,
...@@ -152,6 +157,8 @@ class RendererVk : angle::NonCopyable ...@@ -152,6 +157,8 @@ class RendererVk : angle::NonCopyable
void freeAllInFlightResources(); void freeAllInFlightResources();
angle::Result flushCommandGraph(vk::Context *context, vk::CommandBuffer *commandBatch); angle::Result flushCommandGraph(vk::Context *context, vk::CommandBuffer *commandBatch);
void initFeatures(); void initFeatures();
void initPipelineCacheVkKey();
angle::Result initPipelineCacheVk(DisplayVk *display);
mutable bool mCapsInitialized; mutable bool mCapsInitialized;
mutable gl::Caps mNativeCaps; mutable gl::Caps mNativeCaps;
...@@ -198,6 +205,10 @@ class RendererVk : angle::NonCopyable ...@@ -198,6 +205,10 @@ class RendererVk : angle::NonCopyable
RenderPassCache mRenderPassCache; RenderPassCache mRenderPassCache;
PipelineCache mPipelineCache; PipelineCache mPipelineCache;
vk::PipelineCache mPipelineCacheVk;
egl::BlobCache::Key mPipelineCacheVkBlobKey;
uint32_t mPipelineCacheVkUpdateTimeout;
// See CommandGraph.h for a desription of the Command Graph. // See CommandGraph.h for a desription of the Command Graph.
vk::CommandGraph mCommandGraph; vk::CommandGraph mCommandGraph;
......
...@@ -588,6 +588,8 @@ angle::Result WindowSurfaceVk::swapImpl(DisplayVk *displayVk) ...@@ -588,6 +588,8 @@ angle::Result WindowSurfaceVk::swapImpl(DisplayVk *displayVk)
// Get the next available swapchain image. // Get the next available swapchain image.
ANGLE_TRY(nextSwapchainImage(displayVk)); ANGLE_TRY(nextSwapchainImage(displayVk));
ANGLE_TRY(renderer->syncPipelineCacheVk(displayVk));
return angle::Result::Continue(); return angle::Result::Continue();
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include "libANGLE/renderer/vulkan/vk_cache_utils.h" #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
#include "common/aligned_memory.h" #include "common/aligned_memory.h"
#include "libANGLE/SizedMRUCache.h" #include "libANGLE/BlobCache.h"
#include "libANGLE/VertexAttribute.h" #include "libANGLE/VertexAttribute.h"
#include "libANGLE/renderer/vulkan/FramebufferVk.h" #include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include "libANGLE/renderer/vulkan/ProgramVk.h" #include "libANGLE/renderer/vulkan/ProgramVk.h"
...@@ -436,6 +436,7 @@ void PipelineDesc::initDefaults() ...@@ -436,6 +436,7 @@ void PipelineDesc::initDefaults()
} }
angle::Result PipelineDesc::initializePipeline(vk::Context *context, angle::Result PipelineDesc::initializePipeline(vk::Context *context,
const vk::PipelineCache &pipelineCacheVk,
const RenderPass &compatibleRenderPass, const RenderPass &compatibleRenderPass,
const PipelineLayout &pipelineLayout, const PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
...@@ -617,7 +618,7 @@ angle::Result PipelineDesc::initializePipeline(vk::Context *context, ...@@ -617,7 +618,7 @@ angle::Result PipelineDesc::initializePipeline(vk::Context *context,
createInfo.basePipelineHandle = VK_NULL_HANDLE; createInfo.basePipelineHandle = VK_NULL_HANDLE;
createInfo.basePipelineIndex = 0; createInfo.basePipelineIndex = 0;
ANGLE_TRY(pipelineOut->initGraphics(context, createInfo)); ANGLE_TRY(pipelineOut->initGraphics(context, createInfo, pipelineCacheVk));
return angle::Result::Continue(); return angle::Result::Continue();
} }
...@@ -1125,6 +1126,7 @@ void PipelineCache::destroy(VkDevice device) ...@@ -1125,6 +1126,7 @@ void PipelineCache::destroy(VkDevice device)
} }
angle::Result PipelineCache::getPipeline(vk::Context *context, angle::Result PipelineCache::getPipeline(vk::Context *context,
const vk::PipelineCache &pipelineCacheVk,
const vk::RenderPass &compatibleRenderPass, const vk::RenderPass &compatibleRenderPass,
const vk::PipelineLayout &pipelineLayout, const vk::PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
...@@ -1145,9 +1147,9 @@ angle::Result PipelineCache::getPipeline(vk::Context *context, ...@@ -1145,9 +1147,9 @@ angle::Result PipelineCache::getPipeline(vk::Context *context,
// This "if" is left here for the benefit of VulkanPipelineCachePerfTest. // This "if" is left here for the benefit of VulkanPipelineCachePerfTest.
if (context != nullptr) if (context != nullptr)
{ {
ANGLE_TRY(desc.initializePipeline(context, compatibleRenderPass, pipelineLayout, ANGLE_TRY(desc.initializePipeline(context, pipelineCacheVk, compatibleRenderPass,
activeAttribLocationsMask, vertexModule, fragmentModule, pipelineLayout, activeAttribLocationsMask, vertexModule,
&newPipeline)); fragmentModule, &newPipeline));
} }
// The Serial will be updated outside of this query. // The Serial will be updated outside of this query.
......
...@@ -344,6 +344,7 @@ class PipelineDesc final ...@@ -344,6 +344,7 @@ class PipelineDesc final
void initDefaults(); void initDefaults();
angle::Result initializePipeline(vk::Context *context, angle::Result initializePipeline(vk::Context *context,
const vk::PipelineCache &pipelineCacheVk,
const RenderPass &compatibleRenderPass, const RenderPass &compatibleRenderPass,
const PipelineLayout &pipelineLayout, const PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
...@@ -612,6 +613,7 @@ class PipelineCache final : angle::NonCopyable ...@@ -612,6 +613,7 @@ class PipelineCache final : angle::NonCopyable
void populate(const vk::PipelineDesc &desc, vk::Pipeline &&pipeline); void populate(const vk::PipelineDesc &desc, vk::Pipeline &&pipeline);
angle::Result getPipeline(vk::Context *context, angle::Result getPipeline(vk::Context *context,
const vk::PipelineCache &pipelineCacheVk,
const vk::RenderPass &compatibleRenderPass, const vk::RenderPass &compatibleRenderPass,
const vk::PipelineLayout &pipelineLayout, const vk::PipelineLayout &pipelineLayout,
const gl::AttributesMask &activeAttribLocationsMask, const gl::AttributesMask &activeAttribLocationsMask,
......
...@@ -826,48 +826,92 @@ angle::Result ShaderModule::init(Context *context, const VkShaderModuleCreateInf ...@@ -826,48 +826,92 @@ angle::Result ShaderModule::init(Context *context, const VkShaderModuleCreateInf
return angle::Result::Continue(); return angle::Result::Continue();
} }
// Pipeline implementation. // PipelineLayout implementation.
Pipeline::Pipeline() PipelineLayout::PipelineLayout()
{ {
} }
void Pipeline::destroy(VkDevice device) void PipelineLayout::destroy(VkDevice device)
{ {
if (valid()) if (valid())
{ {
vkDestroyPipeline(device, mHandle, nullptr); vkDestroyPipelineLayout(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE; mHandle = VK_NULL_HANDLE;
} }
} }
angle::Result Pipeline::initGraphics(Context *context, angle::Result PipelineLayout::init(Context *context, const VkPipelineLayoutCreateInfo &createInfo)
const VkGraphicsPipelineCreateInfo &createInfo)
{ {
ASSERT(!valid()); ASSERT(!valid());
ANGLE_VK_TRY(context, vkCreateGraphicsPipelines(context->getDevice(), VK_NULL_HANDLE, 1, ANGLE_VK_TRY(context,
&createInfo, nullptr, &mHandle)); vkCreatePipelineLayout(context->getDevice(), &createInfo, nullptr, &mHandle));
return angle::Result::Continue(); return angle::Result::Continue();
} }
// PipelineLayout implementation. // PipelineCache implementation.
PipelineLayout::PipelineLayout() PipelineCache::PipelineCache()
{ {
} }
void PipelineLayout::destroy(VkDevice device) void PipelineCache::destroy(VkDevice device)
{ {
if (valid()) if (valid())
{ {
vkDestroyPipelineLayout(device, mHandle, nullptr); vkDestroyPipelineCache(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE; mHandle = VK_NULL_HANDLE;
} }
} }
angle::Result PipelineLayout::init(Context *context, const VkPipelineLayoutCreateInfo &createInfo) angle::Result PipelineCache::init(Context *context, const VkPipelineCacheCreateInfo &createInfo)
{ {
ASSERT(!valid()); ASSERT(!valid());
// Note: if we are concerned with memory usage of this cache, we should give it custom
// allocators. Also, failure of this function is of little importance.
ANGLE_VK_TRY(context, ANGLE_VK_TRY(context,
vkCreatePipelineLayout(context->getDevice(), &createInfo, nullptr, &mHandle)); vkCreatePipelineCache(context->getDevice(), &createInfo, nullptr, &mHandle));
return angle::Result::Continue();
}
angle::Result PipelineCache::getCacheData(Context *context, size_t *cacheSize, void *cacheData)
{
ASSERT(valid());
// Note: vkGetPipelineCacheData can return VK_INCOMPLETE if cacheSize is smaller than actual
// size. There are two usages of this function. One is with *cacheSize == 0 to query the size
// of the cache, and one is with an appropriate buffer to retrieve the cache contents.
// VK_INCOMPLETE in the first case is an expected output. In the second case, VK_INCOMPLETE is
// also acceptable and the resulting buffer will contain valid value by spec. Angle currently
// ensures *cacheSize to be either 0 or of enough size, therefore VK_INCOMPLETE is not expected.
angle::Result result = angle::Result::Stop();
ANGLE_VK_TRY_ALLOW_INCOMPLETE(
context, vkGetPipelineCacheData(context->getDevice(), mHandle, cacheSize, cacheData),
result);
return result;
}
// Pipeline implementation.
Pipeline::Pipeline()
{
}
void Pipeline::destroy(VkDevice device)
{
if (valid())
{
vkDestroyPipeline(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
angle::Result Pipeline::initGraphics(Context *context,
const VkGraphicsPipelineCreateInfo &createInfo,
const PipelineCache &pipelineCacheVk)
{
ASSERT(!valid());
ANGLE_VK_TRY(context,
vkCreateGraphicsPipelines(context->getDevice(), pipelineCacheVk.getHandle(), 1,
&createInfo, nullptr, &mHandle));
return angle::Result::Continue(); return angle::Result::Continue();
} }
......
...@@ -94,7 +94,7 @@ namespace vk ...@@ -94,7 +94,7 @@ namespace vk
{ {
struct Format; struct Format;
// Abstracts error handling. Implemented by both ContextVk for GL and RendererVk for EGL errors. // Abstracts error handling. Implemented by both ContextVk for GL and DisplayVk for EGL errors.
class Context : angle::NonCopyable class Context : angle::NonCopyable
{ {
public: public:
...@@ -531,22 +531,34 @@ class ShaderModule final : public WrappedObject<ShaderModule, VkShaderModule> ...@@ -531,22 +531,34 @@ class ShaderModule final : public WrappedObject<ShaderModule, VkShaderModule>
angle::Result init(Context *context, const VkShaderModuleCreateInfo &createInfo); angle::Result init(Context *context, const VkShaderModuleCreateInfo &createInfo);
}; };
class Pipeline final : public WrappedObject<Pipeline, VkPipeline> class PipelineLayout final : public WrappedObject<PipelineLayout, VkPipelineLayout>
{ {
public: public:
Pipeline(); PipelineLayout();
void destroy(VkDevice device); void destroy(VkDevice device);
angle::Result initGraphics(Context *context, const VkGraphicsPipelineCreateInfo &createInfo); angle::Result init(Context *context, const VkPipelineLayoutCreateInfo &createInfo);
}; };
class PipelineLayout final : public WrappedObject<PipelineLayout, VkPipelineLayout> class PipelineCache final : public WrappedObject<PipelineCache, VkPipelineCache>
{ {
public: public:
PipelineLayout(); PipelineCache();
void destroy(VkDevice device); void destroy(VkDevice device);
angle::Result init(Context *context, const VkPipelineLayoutCreateInfo &createInfo); angle::Result init(Context *context, const VkPipelineCacheCreateInfo &createInfo);
angle::Result getCacheData(Context *context, size_t *cacheSize, void *cacheData);
};
class Pipeline final : public WrappedObject<Pipeline, VkPipeline>
{
public:
Pipeline();
void destroy(VkDevice device);
angle::Result initGraphics(Context *context,
const VkGraphicsPipelineCreateInfo &createInfo,
const PipelineCache &pipelineCacheVk);
}; };
class DescriptorSetLayout final : public WrappedObject<DescriptorSetLayout, VkDescriptorSetLayout> class DescriptorSetLayout final : public WrappedObject<DescriptorSetLayout, VkDescriptorSetLayout>
...@@ -757,6 +769,19 @@ VkColorComponentFlags GetColorComponentFlags(bool red, bool green, bool blue, bo ...@@ -757,6 +769,19 @@ VkColorComponentFlags GetColorComponentFlags(bool red, bool green, bool blue, bo
} \ } \
ANGLE_EMPTY_STATEMENT ANGLE_EMPTY_STATEMENT
#define ANGLE_VK_TRY_ALLOW_INCOMPLETE(context, command, result) \
{ \
auto ANGLE_LOCAL_VAR = command; \
if (ANGLE_UNLIKELY(ANGLE_LOCAL_VAR != VK_SUCCESS && ANGLE_LOCAL_VAR != VK_INCOMPLETE)) \
{ \
context->handleError(ANGLE_LOCAL_VAR, __FILE__, __LINE__); \
return angle::Result::Stop(); \
} \
result = ANGLE_LOCAL_VAR == VK_INCOMPLETE ? angle::Result::Incomplete() \
: angle::Result::Continue(); \
} \
ANGLE_EMPTY_STATEMENT
#define ANGLE_VK_CHECK(context, test, error) ANGLE_VK_TRY(context, test ? VK_SUCCESS : error) #define ANGLE_VK_CHECK(context, test, error) ANGLE_VK_TRY(context, test ? VK_SUCCESS : error)
#define ANGLE_VK_CHECK_MATH(context, result) \ #define ANGLE_VK_CHECK_MATH(context, result) \
......
...@@ -80,6 +80,7 @@ void VulkanPipelineCachePerfTest::step() ...@@ -80,6 +80,7 @@ void VulkanPipelineCachePerfTest::step()
{ {
vk::RenderPass rp; vk::RenderPass rp;
vk::PipelineLayout pl; vk::PipelineLayout pl;
vk::PipelineCache pc;
vk::ShaderModule sm; vk::ShaderModule sm;
vk::PipelineAndSerial *result = nullptr; vk::PipelineAndSerial *result = nullptr;
gl::AttributesMask am; gl::AttributesMask am;
...@@ -88,7 +89,7 @@ void VulkanPipelineCachePerfTest::step() ...@@ -88,7 +89,7 @@ void VulkanPipelineCachePerfTest::step()
{ {
for (const auto &hit : mCacheHits) for (const auto &hit : mCacheHits)
{ {
(void)mCache.getPipeline(VK_NULL_HANDLE, rp, pl, am, sm, sm, hit, &result); (void)mCache.getPipeline(VK_NULL_HANDLE, pc, rp, pl, am, sm, sm, hit, &result);
} }
} }
...@@ -96,7 +97,7 @@ void VulkanPipelineCachePerfTest::step() ...@@ -96,7 +97,7 @@ void VulkanPipelineCachePerfTest::step()
++missCount, ++mMissIndex) ++missCount, ++mMissIndex)
{ {
const auto &miss = mCacheMisses[mMissIndex]; const auto &miss = mCacheMisses[mMissIndex];
(void)mCache.getPipeline(VK_NULL_HANDLE, rp, pl, am, sm, sm, miss, &result); (void)mCache.getPipeline(VK_NULL_HANDLE, pc, rp, pl, am, sm, sm, miss, &result);
} }
} }
......
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