Commit 1fb7f648 by Amy Liu Committed by Commit Bot

Compression of the data from vkGetPipelineCacheData.

The size of pipelineCacheData sometimes is greater than 64k which cannot be saved because of the Android blob cache limitation (single cache data size should be < 64k). Implement the compression to store more cache data. Re-land this patch before fixing the performance regression of big pipeline cache. Bug: angleproject:4722 Change-Id: I4bc05a88334c3e7e9e945d1a0877429db1750422 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2771840 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 9f796506
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
#include "libANGLE/histogram_macros.h" #include "libANGLE/histogram_macros.h"
#include "platform/PlatformMethods.h" #include "platform/PlatformMethods.h"
#define USE_SYSTEM_ZLIB
#include "compression_utils_portable.h"
namespace egl namespace egl
{ {
...@@ -29,6 +32,73 @@ enum CacheResult ...@@ -29,6 +32,73 @@ enum CacheResult
} // anonymous namespace } // anonymous namespace
// In oder to store more cache in blob cache, compress cacheData to compressedData
// before being stored.
bool CompressBlobCacheData(angle::MemoryBuffer *cacheData, angle::MemoryBuffer *compressedData)
{
uLong uncompressedSize = static_cast<uLong>(cacheData->size());
uLong expectedCompressedSize = zlib_internal::GzipExpectedCompressedSize(uncompressedSize);
// Allocate memory.
if (!compressedData->resize(expectedCompressedSize))
{
ERR() << "Failed to allocate memory for compression";
return false;
}
int zResult =
zlib_internal::GzipCompressHelper(compressedData->data(), &expectedCompressedSize,
cacheData->data(), uncompressedSize, nullptr, nullptr);
if (zResult != Z_OK)
{
ERR() << "Failed to compress cache data: " << zResult;
return false;
}
// Resize it to expected size.
if (!compressedData->resize(expectedCompressedSize))
{
return false;
}
return true;
}
bool DecompressBlobCacheData(const uint8_t *compressedData,
const size_t compressedSize,
angle::MemoryBuffer *uncompressedData)
{
// Call zlib function to decompress.
uint32_t uncompressedSize =
zlib_internal::GetGzipUncompressedSize(compressedData, compressedSize);
// Allocate enough memory.
if (!uncompressedData->resize(uncompressedSize))
{
ERR() << "Failed to allocate memory for decompression";
return false;
}
uLong destLen = uncompressedSize;
int zResult = zlib_internal::GzipUncompressHelper(
uncompressedData->data(), &destLen, compressedData, static_cast<uLong>(compressedSize));
if (zResult != Z_OK)
{
ERR() << "Failed to decompress data: " << zResult << "\n";
return false;
}
// Resize it to expected size.
if (!uncompressedData->resize(destLen))
{
return false;
}
return true;
}
BlobCache::BlobCache(size_t maxCacheSizeBytes) BlobCache::BlobCache(size_t maxCacheSizeBytes)
: mBlobCache(maxCacheSizeBytes), mSetBlobFunc(nullptr), mGetBlobFunc(nullptr) : mBlobCache(maxCacheSizeBytes), mSetBlobFunc(nullptr), mGetBlobFunc(nullptr)
{} {}
......
...@@ -48,6 +48,11 @@ struct hash<egl::BlobCacheKey> ...@@ -48,6 +48,11 @@ struct hash<egl::BlobCacheKey>
namespace egl namespace egl
{ {
bool CompressBlobCacheData(angle::MemoryBuffer *cacheData, angle::MemoryBuffer *compressedData);
bool DecompressBlobCacheData(const uint8_t *compressedData,
const size_t compressedSize,
angle::MemoryBuffer *uncompressedData);
class BlobCache final : angle::NonCopyable class BlobCache final : angle::NonCopyable
{ {
public: public:
......
...@@ -21,9 +21,6 @@ ...@@ -21,9 +21,6 @@
#include "libANGLE/renderer/ProgramImpl.h" #include "libANGLE/renderer/ProgramImpl.h"
#include "platform/PlatformMethods.h" #include "platform/PlatformMethods.h"
#define USE_SYSTEM_ZLIB
#include "compression_utils_portable.h"
namespace gl namespace gl
{ {
...@@ -146,18 +143,10 @@ angle::Result MemoryProgramCache::getProgram(const Context *context, ...@@ -146,18 +143,10 @@ angle::Result MemoryProgramCache::getProgram(const Context *context,
size_t programSize = 0; size_t programSize = 0;
if (get(context, *hashOut, &binaryProgram, &programSize)) if (get(context, *hashOut, &binaryProgram, &programSize))
{ {
uint32_t uncompressedSize = angle::MemoryBuffer uncompressedData;
zlib_internal::GetGzipUncompressedSize(binaryProgram.data(), programSize); if (!egl::DecompressBlobCacheData(binaryProgram.data(), programSize, &uncompressedData))
std::vector<uint8_t> uncompressedData(uncompressedSize);
uLong destLen = uncompressedSize;
int zResult = zlib_internal::GzipUncompressHelper(uncompressedData.data(), &destLen,
binaryProgram.data(),
static_cast<uLong>(programSize));
if (zResult != Z_OK)
{ {
ERR() << "Failure to decompressed binary data: " << zResult << "\n"; ERR() << "Error decompressing binary data.";
return angle::Result::Incomplete; return angle::Result::Incomplete;
} }
...@@ -220,33 +209,10 @@ angle::Result MemoryProgramCache::putProgram(const egl::BlobCache::Key &programH ...@@ -220,33 +209,10 @@ angle::Result MemoryProgramCache::putProgram(const egl::BlobCache::Key &programH
angle::MemoryBuffer serializedProgram; angle::MemoryBuffer serializedProgram;
ANGLE_TRY(program->serialize(context, &serializedProgram)); ANGLE_TRY(program->serialize(context, &serializedProgram));
// Compress the program data
uLong uncompressedSize = static_cast<uLong>(serializedProgram.size());
uLong expectedCompressedSize = zlib_internal::GzipExpectedCompressedSize(uncompressedSize);
angle::MemoryBuffer compressedData; angle::MemoryBuffer compressedData;
if (!compressedData.resize(expectedCompressedSize)) if (!egl::CompressBlobCacheData(&serializedProgram, &compressedData))
{
ERR() << "Failed to allocate enough memory to hold compressed program. ("
<< expectedCompressedSize << " bytes )";
return angle::Result::Incomplete;
}
int zResult = zlib_internal::GzipCompressHelper(compressedData.data(), &expectedCompressedSize,
serializedProgram.data(), uncompressedSize,
nullptr, nullptr);
if (zResult != Z_OK)
{
FATAL() << "Error compressing binary data: " << zResult;
return angle::Result::Incomplete;
}
// Resize the buffer to the actual compressed size
if (!compressedData.resize(expectedCompressedSize))
{ {
ERR() << "Failed to resize to actual compressed program size. (" << expectedCompressedSize ERR() << "Error compressing binary data.";
<< " bytes )";
return angle::Result::Incomplete; return angle::Result::Incomplete;
} }
......
...@@ -165,7 +165,7 @@ class RendererVk : angle::NonCopyable ...@@ -165,7 +165,7 @@ class RendererVk : angle::NonCopyable
const vk::Format &getFormat(angle::FormatID formatID) const { return mFormatTable[formatID]; } const vk::Format &getFormat(angle::FormatID formatID) const { return mFormatTable[formatID]; }
angle::Result getPipelineCacheSize(DisplayVk *displayVk, size_t *pipelineCacheSizeOut); angle::Result getPipelineCacheSize(DisplayVk *displayVk, size_t *pipelineCacheSizeOut);
angle::Result syncPipelineCacheVk(DisplayVk *displayVk); angle::Result syncPipelineCacheVk(DisplayVk *displayVk, ContextVk *contextVk);
// Issues a new serial for linked shader modules. Used in the pipeline cache. // Issues a new serial for linked shader modules. Used in the pipeline cache.
Serial issueShaderSerial(); Serial issueShaderSerial();
...@@ -376,7 +376,6 @@ class RendererVk : angle::NonCopyable ...@@ -376,7 +376,6 @@ class RendererVk : angle::NonCopyable
void queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceExtensionNames); void queryDeviceExtensionFeatures(const vk::ExtensionNameList &deviceExtensionNames);
void initFeatures(DisplayVk *display, const vk::ExtensionNameList &extensions); void initFeatures(DisplayVk *display, const vk::ExtensionNameList &extensions);
void initPipelineCacheVkKey();
angle::Result initPipelineCache(DisplayVk *display, angle::Result initPipelineCache(DisplayVk *display,
vk::PipelineCache *pipelineCache, vk::PipelineCache *pipelineCache,
bool *success); bool *success);
...@@ -447,7 +446,6 @@ class RendererVk : angle::NonCopyable ...@@ -447,7 +446,6 @@ class RendererVk : angle::NonCopyable
// a lock. // a lock.
std::mutex mPipelineCacheMutex; std::mutex mPipelineCacheMutex;
vk::PipelineCache mPipelineCache; vk::PipelineCache mPipelineCache;
egl::BlobCache::Key mPipelineCacheVkBlobKey;
uint32_t mPipelineCacheVkUpdateTimeout; uint32_t mPipelineCacheVkUpdateTimeout;
bool mPipelineCacheDirty; bool mPipelineCacheDirty;
bool mPipelineCacheInitialized; bool mPipelineCacheInitialized;
......
...@@ -1543,7 +1543,7 @@ angle::Result WindowSurfaceVk::doDeferredAcquireNextImage(const gl::Context *con ...@@ -1543,7 +1543,7 @@ angle::Result WindowSurfaceVk::doDeferredAcquireNextImage(const gl::Context *con
} }
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
ANGLE_TRY(renderer->syncPipelineCacheVk(displayVk)); ANGLE_TRY(renderer->syncPipelineCacheVk(displayVk, contextVk));
return angle::Result::Continue; return angle::Result::Continue;
} }
......
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