Commit 3e8305f5 by Cody Northrop Committed by Commit Bot

FrameCapture: Move compressed texture cache to shared location

In support of tracking compressed texture data across multiple threads and contexts, move our cache to FrameCaptureShared. Make this accessible only via egl::ShareGroup, which will ensure unique texture IDs. Test: Asphalt 8 MEC Bug: b/150484427 Bug: angleproject:4048 Change-Id: I4e75b323d7aedc0333ceffba305439e54c4d6ac1 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2455266 Commit-Queue: Cody Northrop <cnorthrop@google.com> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 0f55e3e5
......@@ -31,6 +31,7 @@
#include "libANGLE/Context.h"
#include "libANGLE/Device.h"
#include "libANGLE/EGLSync.h"
#include "libANGLE/FrameCapture.h"
#include "libANGLE/Image.h"
#include "libANGLE/ResourceManager.h"
#include "libANGLE/Stream.h"
......@@ -457,7 +458,9 @@ static constexpr uint32_t kScratchBufferLifetime = 64u;
// ShareGroup
ShareGroup::ShareGroup(rx::EGLImplFactory *factory)
: mRefCount(1), mImplementation(factory->createShareGroup())
: mRefCount(1),
mImplementation(factory->createShareGroup()),
mFrameCaptureShared(new angle::FrameCaptureShared)
{}
ShareGroup::~ShareGroup()
......
......@@ -28,6 +28,11 @@
#include "platform/Feature.h"
#include "platform/FrontendFeatures.h"
namespace angle
{
class FrameCaptureShared;
} // namespace angle
namespace gl
{
class Context;
......@@ -79,6 +84,8 @@ class ShareGroup final : angle::NonCopyable
rx::Serial generateFramebufferSerial() { return mFramebufferSerialFactory.generate(); }
angle::FrameCaptureShared *getFrameCaptureShared() { return mFrameCaptureShared.get(); }
protected:
~ShareGroup();
......@@ -86,6 +93,9 @@ class ShareGroup final : angle::NonCopyable
size_t mRefCount;
rx::ShareGroupImpl *mImplementation;
rx::SerialFactory mFramebufferSerialFactory;
// Note: we use a raw pointer here so we can exclude frame capture sources from the build.
std::unique_ptr<angle::FrameCaptureShared> mFrameCaptureShared;
};
// Constant coded here as a reasonable limit.
......
......@@ -21,6 +21,7 @@
#include "common/system_utils.h"
#include "libANGLE/Config.h"
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/Fence.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/Query.h"
......@@ -2270,7 +2271,6 @@ void CaptureMidExecutionSetup(const gl::Context *context,
ResourceTracker *resourceTracker,
const ShaderSourceMap &cachedShaderSources,
const ProgramSourceMap &cachedProgramSources,
const TextureLevelDataMap &cachedTextureLevelData,
FrameCapture *frameCapture)
{
const gl::State &apiState = context->getState();
......@@ -2582,16 +2582,9 @@ void CaptureMidExecutionSetup(const gl::Context *context,
{
// For compressed images, we've tracked a copy of the incoming data, so we can
// use that rather than try to read data back that may have been converted.
// Look up the data for the requested texture
const auto &foundTextureLevels = cachedTextureLevelData.find(texture->id());
ASSERT(foundTextureLevels != cachedTextureLevelData.end());
// For that texture, look up the data for the given level
GLint level = index.getLevelIndex();
const auto &foundTextureLevel = foundTextureLevels->second.find(level);
ASSERT(foundTextureLevel != foundTextureLevels->second.end());
const std::vector<uint8_t> &capturedTextureLevel = foundTextureLevel->second;
const std::vector<uint8_t> &capturedTextureLevel =
context->getShareGroup()->getFrameCaptureShared()->retrieveCachedTextureLevel(
texture->id(), index.getLevelIndex());
// Use the shadow copy of the data to populate the call
CaptureTextureContents(setupCalls, &replayState, texture, index, desc,
......@@ -3761,37 +3754,10 @@ void FrameCapture::captureCompressedTextureData(const gl::Context *context, cons
ASSERT(texture);
// Record the data, indexed by textureID and level
GLint level = call.params.getParam("level", ParamType::TGLint, 1).value.GLintVal;
auto foundTextureLevels = mCachedTextureLevelData.find(texture->id());
if (foundTextureLevels == mCachedTextureLevelData.end())
{
// Initialize the texture ID data.
auto emplaceResult = mCachedTextureLevelData.emplace(texture->id(), TextureLevels());
ASSERT(emplaceResult.second);
foundTextureLevels = emplaceResult.first;
}
// Get the format of the texture for use with the compressed block size math.
const gl::InternalFormat &format = *texture->getFormat(targetPacked, level).info;
TextureLevels &foundLevels = foundTextureLevels->second;
auto foundLevel = foundLevels.find(level);
// Divide dimensions according to block size.
const gl::Extents &levelExtents = texture->getExtents(targetPacked, level);
if (foundLevel == foundLevels.end())
{
// Initialize texture rectangle data. Default init to zero for stability.
GLuint sizeInBytes;
bool result = format.computeCompressedImageSize(levelExtents, &sizeInBytes);
ASSERT(result);
std::vector<uint8_t> newPixelData(sizeInBytes, 0);
auto emplaceResult = foundLevels.emplace(level, std::move(newPixelData));
ASSERT(emplaceResult.second);
foundLevel = emplaceResult.first;
}
GLint level = call.params.getParam("level", ParamType::TGLint, 1).value.GLintVal;
std::vector<uint8_t> &levelData =
context->getShareGroup()->getFrameCaptureShared()->getTextureLevelCacheLocation(
texture, targetPacked, level);
// Unpack the various pixel rectangle parameters.
ASSERT(widthParamOffset != -1);
......@@ -3829,6 +3795,12 @@ void FrameCapture::captureCompressedTextureData(const gl::Context *context, cons
call.params.getParam("zoffset", ParamType::TGLint, zoffsetParamOffset).value.GLintVal;
}
// Get the format of the texture for use with the compressed block size math.
const gl::InternalFormat &format = *texture->getFormat(targetPacked, level).info;
// Divide dimensions according to block size.
const gl::Extents &levelExtents = texture->getExtents(targetPacked, level);
// Scale down the width/height pixel offsets to reflect block size
int widthScale = static_cast<int>(format.compressedBlockWidth);
int heightScale = static_cast<int>(format.compressedBlockHeight);
......@@ -3838,9 +3810,6 @@ void FrameCapture::captureCompressedTextureData(const gl::Context *context, cons
xoffset /= widthScale;
yoffset /= heightScale;
// Update pixel data.
std::vector<uint8_t> &levelData = foundLevel->second;
GLint pixelBytes = static_cast<GLint>(format.pixelBytes);
GLint pixelRowPitch = pixelWidth * pixelBytes;
......@@ -4081,12 +4050,8 @@ void FrameCapture::maybeCapturePreCallUpdates(const gl::Context *context, CallCa
for (int32_t i = 0; i < n; ++i)
{
// Look it up in the cache, and delete it if found
const auto &foundTextureLevels = mCachedTextureLevelData.find(textureIDs[i]);
if (foundTextureLevels != mCachedTextureLevelData.end())
{
// Delete all texture levels at once
mCachedTextureLevelData.erase(foundTextureLevels);
}
context->getShareGroup()->getFrameCaptureShared()->deleteCachedTextureLevelData(
textureIDs[i]);
}
break;
}
......@@ -4429,7 +4394,7 @@ void FrameCapture::onEndFrame(const gl::Context *context)
{
mSetupCalls.clear();
CaptureMidExecutionSetup(context, &mSetupCalls, &mResourceTracker, mCachedShaderSources,
mCachedProgramSources, mCachedTextureLevelData, this);
mCachedProgramSources, this);
}
}
......@@ -4628,6 +4593,78 @@ void FrameCapture::reset()
// necessary.
}
FrameCaptureShared::FrameCaptureShared() = default;
FrameCaptureShared::~FrameCaptureShared() = default;
const std::vector<uint8_t> &FrameCaptureShared::retrieveCachedTextureLevel(gl::TextureID id,
GLint level)
{
// Look up the data for the requested texture
const auto &foundTextureLevels = mCachedTextureLevelData.find(id);
ASSERT(foundTextureLevels != mCachedTextureLevelData.end());
// For that texture, look up the data for the given level
const auto &foundTextureLevel = foundTextureLevels->second.find(level);
ASSERT(foundTextureLevel != foundTextureLevels->second.end());
const std::vector<uint8_t> &capturedTextureLevel = foundTextureLevel->second;
return capturedTextureLevel;
}
std::vector<uint8_t> &FrameCaptureShared::getTextureLevelCacheLocation(gl::Texture *texture,
gl::TextureTarget target,
GLint level)
{
auto foundTextureLevels = mCachedTextureLevelData.find(texture->id());
if (foundTextureLevels == mCachedTextureLevelData.end())
{
// If we haven't cached this texture, initialize the texture ID data.
auto emplaceResult = mCachedTextureLevelData.emplace(texture->id(), TextureLevels());
ASSERT(emplaceResult.second);
foundTextureLevels = emplaceResult.first;
}
TextureLevels &foundLevels = foundTextureLevels->second;
TextureLevels::iterator foundLevel = foundLevels.find(level);
if (foundLevel != foundLevels.end())
{
// If we have a cache for this level, return it now
return foundLevel->second;
}
// Otherwise, create an appropriately sized cache for this level
// Get the format of the texture for use with the compressed block size math.
const gl::InternalFormat &format = *texture->getFormat(target, level).info;
// Divide dimensions according to block size.
const gl::Extents &levelExtents = texture->getExtents(target, level);
// Calculate the size needed to store the compressed level
GLuint sizeInBytes;
bool result = format.computeCompressedImageSize(levelExtents, &sizeInBytes);
ASSERT(result);
// Initialize texture rectangle data. Default init to zero for stability.
std::vector<uint8_t> newPixelData(sizeInBytes, 0);
auto emplaceResult = foundLevels.emplace(level, std::move(newPixelData));
ASSERT(emplaceResult.second);
// Using the level entry we just created, return the location (a byte vector) where compressed
// texture level data should be stored
return emplaceResult.first->second;
}
void FrameCaptureShared::deleteCachedTextureLevelData(gl::TextureID id)
{
const auto &foundTextureLevels = mCachedTextureLevelData.find(id);
if (foundTextureLevels != mCachedTextureLevelData.end())
{
// Delete all texture levels at once
mCachedTextureLevelData.erase(foundTextureLevels);
}
}
void CaptureMemory(const void *source, size_t size, ParamCapture *paramCapture)
{
std::vector<uint8_t> data(size);
......
......@@ -373,16 +373,36 @@ class FrameCapture final : angle::NonCopyable
ShaderSourceMap mCachedShaderSources;
ProgramSourceMap mCachedProgramSources;
// Cache a shadow copy of texture level data
TextureLevels mCachedTextureLevels;
TextureLevelDataMap mCachedTextureLevelData;
// If you don't know which frame you want to start capturing at, use the capture trigger.
// Initialize it to the number of frames you want to capture, and then clear the value to 0 when
// you reach the content you want to capture. Currently only available on Android.
uint32_t mCaptureTrigger;
};
// Shared class for any items that need to be tracked by FrameCapture across shared contexts
class FrameCaptureShared final : angle::NonCopyable
{
public:
FrameCaptureShared();
~FrameCaptureShared();
// Load data from a previously stored texture level
const std::vector<uint8_t> &retrieveCachedTextureLevel(gl::TextureID id, GLint level);
// Create the location that should be used to cache texture level data
std::vector<uint8_t> &getTextureLevelCacheLocation(gl::Texture *texture,
gl::TextureTarget target,
GLint level);
// Remove any cached texture levels on deletion
void deleteCachedTextureLevelData(gl::TextureID id);
private:
// Cache a shadow copy of texture level data
TextureLevels mCachedTextureLevels;
TextureLevelDataMap mCachedTextureLevelData;
};
template <typename CaptureFuncT, typename... ArgsT>
void CaptureCallToFrameCapture(CaptureFuncT captureFunc,
bool isCallValid,
......
......@@ -27,4 +27,7 @@ void FrameCapture::onEndFrame(const gl::Context *context) {}
void FrameCapture::onMakeCurrent(const egl::Surface *drawSurface) {}
void FrameCapture::onDestroyContext(const gl::Context *context) {}
void FrameCapture::replay(gl::Context *context) {}
FrameCaptureShared::FrameCaptureShared() {}
FrameCaptureShared::~FrameCaptureShared() {}
} // namespace angle
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