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 @@ ...@@ -31,6 +31,7 @@
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Device.h" #include "libANGLE/Device.h"
#include "libANGLE/EGLSync.h" #include "libANGLE/EGLSync.h"
#include "libANGLE/FrameCapture.h"
#include "libANGLE/Image.h" #include "libANGLE/Image.h"
#include "libANGLE/ResourceManager.h" #include "libANGLE/ResourceManager.h"
#include "libANGLE/Stream.h" #include "libANGLE/Stream.h"
...@@ -457,7 +458,9 @@ static constexpr uint32_t kScratchBufferLifetime = 64u; ...@@ -457,7 +458,9 @@ static constexpr uint32_t kScratchBufferLifetime = 64u;
// ShareGroup // ShareGroup
ShareGroup::ShareGroup(rx::EGLImplFactory *factory) ShareGroup::ShareGroup(rx::EGLImplFactory *factory)
: mRefCount(1), mImplementation(factory->createShareGroup()) : mRefCount(1),
mImplementation(factory->createShareGroup()),
mFrameCaptureShared(new angle::FrameCaptureShared)
{} {}
ShareGroup::~ShareGroup() ShareGroup::~ShareGroup()
......
...@@ -28,6 +28,11 @@ ...@@ -28,6 +28,11 @@
#include "platform/Feature.h" #include "platform/Feature.h"
#include "platform/FrontendFeatures.h" #include "platform/FrontendFeatures.h"
namespace angle
{
class FrameCaptureShared;
} // namespace angle
namespace gl namespace gl
{ {
class Context; class Context;
...@@ -79,6 +84,8 @@ class ShareGroup final : angle::NonCopyable ...@@ -79,6 +84,8 @@ class ShareGroup final : angle::NonCopyable
rx::Serial generateFramebufferSerial() { return mFramebufferSerialFactory.generate(); } rx::Serial generateFramebufferSerial() { return mFramebufferSerialFactory.generate(); }
angle::FrameCaptureShared *getFrameCaptureShared() { return mFrameCaptureShared.get(); }
protected: protected:
~ShareGroup(); ~ShareGroup();
...@@ -86,6 +93,9 @@ class ShareGroup final : angle::NonCopyable ...@@ -86,6 +93,9 @@ class ShareGroup final : angle::NonCopyable
size_t mRefCount; size_t mRefCount;
rx::ShareGroupImpl *mImplementation; rx::ShareGroupImpl *mImplementation;
rx::SerialFactory mFramebufferSerialFactory; 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. // Constant coded here as a reasonable limit.
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "common/system_utils.h" #include "common/system_utils.h"
#include "libANGLE/Config.h" #include "libANGLE/Config.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/Fence.h" #include "libANGLE/Fence.h"
#include "libANGLE/Framebuffer.h" #include "libANGLE/Framebuffer.h"
#include "libANGLE/Query.h" #include "libANGLE/Query.h"
...@@ -2270,7 +2271,6 @@ void CaptureMidExecutionSetup(const gl::Context *context, ...@@ -2270,7 +2271,6 @@ void CaptureMidExecutionSetup(const gl::Context *context,
ResourceTracker *resourceTracker, ResourceTracker *resourceTracker,
const ShaderSourceMap &cachedShaderSources, const ShaderSourceMap &cachedShaderSources,
const ProgramSourceMap &cachedProgramSources, const ProgramSourceMap &cachedProgramSources,
const TextureLevelDataMap &cachedTextureLevelData,
FrameCapture *frameCapture) FrameCapture *frameCapture)
{ {
const gl::State &apiState = context->getState(); const gl::State &apiState = context->getState();
...@@ -2582,16 +2582,9 @@ void CaptureMidExecutionSetup(const gl::Context *context, ...@@ -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 // 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. // use that rather than try to read data back that may have been converted.
const std::vector<uint8_t> &capturedTextureLevel =
// Look up the data for the requested texture context->getShareGroup()->getFrameCaptureShared()->retrieveCachedTextureLevel(
const auto &foundTextureLevels = cachedTextureLevelData.find(texture->id()); texture->id(), index.getLevelIndex());
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;
// Use the shadow copy of the data to populate the call // Use the shadow copy of the data to populate the call
CaptureTextureContents(setupCalls, &replayState, texture, index, desc, CaptureTextureContents(setupCalls, &replayState, texture, index, desc,
...@@ -3761,37 +3754,10 @@ void FrameCapture::captureCompressedTextureData(const gl::Context *context, cons ...@@ -3761,37 +3754,10 @@ void FrameCapture::captureCompressedTextureData(const gl::Context *context, cons
ASSERT(texture); ASSERT(texture);
// Record the data, indexed by textureID and level // Record the data, indexed by textureID and level
GLint level = call.params.getParam("level", ParamType::TGLint, 1).value.GLintVal; GLint level = call.params.getParam("level", ParamType::TGLint, 1).value.GLintVal;
auto foundTextureLevels = mCachedTextureLevelData.find(texture->id()); std::vector<uint8_t> &levelData =
if (foundTextureLevels == mCachedTextureLevelData.end()) context->getShareGroup()->getFrameCaptureShared()->getTextureLevelCacheLocation(
{ texture, targetPacked, level);
// 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;
}
// Unpack the various pixel rectangle parameters. // Unpack the various pixel rectangle parameters.
ASSERT(widthParamOffset != -1); ASSERT(widthParamOffset != -1);
...@@ -3829,6 +3795,12 @@ void FrameCapture::captureCompressedTextureData(const gl::Context *context, cons ...@@ -3829,6 +3795,12 @@ void FrameCapture::captureCompressedTextureData(const gl::Context *context, cons
call.params.getParam("zoffset", ParamType::TGLint, zoffsetParamOffset).value.GLintVal; 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 // Scale down the width/height pixel offsets to reflect block size
int widthScale = static_cast<int>(format.compressedBlockWidth); int widthScale = static_cast<int>(format.compressedBlockWidth);
int heightScale = static_cast<int>(format.compressedBlockHeight); int heightScale = static_cast<int>(format.compressedBlockHeight);
...@@ -3838,9 +3810,6 @@ void FrameCapture::captureCompressedTextureData(const gl::Context *context, cons ...@@ -3838,9 +3810,6 @@ void FrameCapture::captureCompressedTextureData(const gl::Context *context, cons
xoffset /= widthScale; xoffset /= widthScale;
yoffset /= heightScale; yoffset /= heightScale;
// Update pixel data.
std::vector<uint8_t> &levelData = foundLevel->second;
GLint pixelBytes = static_cast<GLint>(format.pixelBytes); GLint pixelBytes = static_cast<GLint>(format.pixelBytes);
GLint pixelRowPitch = pixelWidth * pixelBytes; GLint pixelRowPitch = pixelWidth * pixelBytes;
...@@ -4081,12 +4050,8 @@ void FrameCapture::maybeCapturePreCallUpdates(const gl::Context *context, CallCa ...@@ -4081,12 +4050,8 @@ void FrameCapture::maybeCapturePreCallUpdates(const gl::Context *context, CallCa
for (int32_t i = 0; i < n; ++i) for (int32_t i = 0; i < n; ++i)
{ {
// Look it up in the cache, and delete it if found // Look it up in the cache, and delete it if found
const auto &foundTextureLevels = mCachedTextureLevelData.find(textureIDs[i]); context->getShareGroup()->getFrameCaptureShared()->deleteCachedTextureLevelData(
if (foundTextureLevels != mCachedTextureLevelData.end()) textureIDs[i]);
{
// Delete all texture levels at once
mCachedTextureLevelData.erase(foundTextureLevels);
}
} }
break; break;
} }
...@@ -4429,7 +4394,7 @@ void FrameCapture::onEndFrame(const gl::Context *context) ...@@ -4429,7 +4394,7 @@ void FrameCapture::onEndFrame(const gl::Context *context)
{ {
mSetupCalls.clear(); mSetupCalls.clear();
CaptureMidExecutionSetup(context, &mSetupCalls, &mResourceTracker, mCachedShaderSources, CaptureMidExecutionSetup(context, &mSetupCalls, &mResourceTracker, mCachedShaderSources,
mCachedProgramSources, mCachedTextureLevelData, this); mCachedProgramSources, this);
} }
} }
...@@ -4628,6 +4593,78 @@ void FrameCapture::reset() ...@@ -4628,6 +4593,78 @@ void FrameCapture::reset()
// necessary. // 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) void CaptureMemory(const void *source, size_t size, ParamCapture *paramCapture)
{ {
std::vector<uint8_t> data(size); std::vector<uint8_t> data(size);
......
...@@ -373,16 +373,36 @@ class FrameCapture final : angle::NonCopyable ...@@ -373,16 +373,36 @@ class FrameCapture final : angle::NonCopyable
ShaderSourceMap mCachedShaderSources; ShaderSourceMap mCachedShaderSources;
ProgramSourceMap mCachedProgramSources; 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. // 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 // 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. // you reach the content you want to capture. Currently only available on Android.
uint32_t mCaptureTrigger; 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> template <typename CaptureFuncT, typename... ArgsT>
void CaptureCallToFrameCapture(CaptureFuncT captureFunc, void CaptureCallToFrameCapture(CaptureFuncT captureFunc,
bool isCallValid, bool isCallValid,
......
...@@ -27,4 +27,7 @@ void FrameCapture::onEndFrame(const gl::Context *context) {} ...@@ -27,4 +27,7 @@ void FrameCapture::onEndFrame(const gl::Context *context) {}
void FrameCapture::onMakeCurrent(const egl::Surface *drawSurface) {} void FrameCapture::onMakeCurrent(const egl::Surface *drawSurface) {}
void FrameCapture::onDestroyContext(const gl::Context *context) {} void FrameCapture::onDestroyContext(const gl::Context *context) {}
void FrameCapture::replay(gl::Context *context) {} void FrameCapture::replay(gl::Context *context) {}
FrameCaptureShared::FrameCaptureShared() {}
FrameCaptureShared::~FrameCaptureShared() {}
} // namespace angle } // 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