Commit a798819c by Cody Northrop Committed by Commit Bot

Capture/Replay: Dedup shaders to reduce capture size

This CL will track whether a string has already been declared and written in the output file. This cuts the shader string count in NBA2K20 trace by 85%, eliminating about 300K lines of code from setup. Test: Compile and link NBA2K20 trace for Android Bug: b/160014453 Bug: angleproject:4048 Change-Id: Id854b3314644c1e4aae41cd6bb4157f92e9b1945 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2339852Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Cody Northrop <cnorthrop@google.com>
parent 063d754b
...@@ -341,23 +341,32 @@ void WriteStringParamReplay(std::ostream &out, const ParamCapture &param) ...@@ -341,23 +341,32 @@ void WriteStringParamReplay(std::ostream &out, const ParamCapture &param)
out << "\"" << str << "\""; out << "\"" << str << "\"";
} }
void WriteStringPointerParamReplay(DataCounters *counters, void WriteStringPointerParamReplay(DataTracker *dataTracker,
std::ostream &out, std::ostream &out,
std::ostream &header, std::ostream &header,
const CallCapture &call, const CallCapture &call,
const ParamCapture &param) const ParamCapture &param)
{ {
int counter = counters->getAndIncrement(call.entryPoint, param.name); // Concatenate the strings to ensure we get an accurate counter
// TODO (anglebug.com/4941): Explore a way to avoid lumping the strings together
header << "const char *"; std::string str;
WriteParamStaticVarName(call, param, counter, header);
header << "[] = { \n";
for (const std::vector<uint8_t> &data : param.data) for (const std::vector<uint8_t> &data : param.data)
{ {
// null terminate C style string // null terminate C style string
ASSERT(data.size() > 0 && data.back() == '\0'); ASSERT(data.size() > 0 && data.back() == '\0');
std::string str(data.begin(), data.end() - 1); str += std::string(data.begin(), data.end() - 1);
}
int counter = dataTracker->getStringCounters().getStringCounter(str);
if (counter == kStringNotFound)
{
// This is a unique string, so set up its declaration and update its counter
counter = dataTracker->getCounters().getAndIncrement(call.entryPoint, param.name);
dataTracker->getStringCounters().setStringCounter(str, counter);
header << "const char *";
WriteParamStaticVarName(call, param, counter, header);
header << "[] = { \n";
// Break up long strings for MSVC // Break up long strings for MSVC
for (size_t i = 0; i < str.length(); i += kStringLengthLimit) for (size_t i = 0; i < str.length(); i += kStringLengthLimit)
...@@ -366,21 +375,21 @@ void WriteStringPointerParamReplay(DataCounters *counters, ...@@ -366,21 +375,21 @@ void WriteStringPointerParamReplay(DataCounters *counters,
: (str.length() - i); : (str.length() - i);
header << " R\"(" << str.substr(i, copyLength) << ")\"\n"; header << " R\"(" << str.substr(i, copyLength) << ")\"\n";
} }
header << ","; header << " };\n";
} }
header << " };\n"; ASSERT(counter >= 0);
WriteParamStaticVarName(call, param, counter, out); WriteParamStaticVarName(call, param, counter, out);
} }
template <typename ParamT> template <typename ParamT>
void WriteResourceIDPointerParamReplay(DataCounters *counters, void WriteResourceIDPointerParamReplay(DataTracker *dataTracker,
std::ostream &out, std::ostream &out,
std::ostream &header, std::ostream &header,
const CallCapture &call, const CallCapture &call,
const ParamCapture &param) const ParamCapture &param)
{ {
int counter = counters->getAndIncrement(call.entryPoint, param.name); int counter = dataTracker->getCounters().getAndIncrement(call.entryPoint, param.name);
header << "const GLuint "; header << "const GLuint ";
WriteParamStaticVarName(call, param, counter, header); WriteParamStaticVarName(call, param, counter, header);
...@@ -408,14 +417,14 @@ void WriteResourceIDPointerParamReplay(DataCounters *counters, ...@@ -408,14 +417,14 @@ void WriteResourceIDPointerParamReplay(DataCounters *counters,
WriteParamStaticVarName(call, param, counter, out); WriteParamStaticVarName(call, param, counter, out);
} }
void WriteBinaryParamReplay(DataCounters *counters, void WriteBinaryParamReplay(DataTracker *dataTracker,
std::ostream &out, std::ostream &out,
std::ostream &header, std::ostream &header,
const CallCapture &call, const CallCapture &call,
const ParamCapture &param, const ParamCapture &param,
std::vector<uint8_t> *binaryData) std::vector<uint8_t> *binaryData)
{ {
int counter = counters->getAndIncrement(call.entryPoint, param.name); int counter = dataTracker->getCounters().getAndIncrement(call.entryPoint, param.name);
ASSERT(param.data.size() == 1); ASSERT(param.data.size() == 1);
const std::vector<uint8_t> &data = param.data[0]; const std::vector<uint8_t> &data = param.data[0];
...@@ -462,7 +471,7 @@ uintptr_t SyncIndexValue(GLsync sync) ...@@ -462,7 +471,7 @@ uintptr_t SyncIndexValue(GLsync sync)
} }
void WriteCppReplayForCall(const CallCapture &call, void WriteCppReplayForCall(const CallCapture &call,
DataCounters *counters, DataTracker *dataTracker,
std::ostream &out, std::ostream &out,
std::ostream &header, std::ostream &header,
std::vector<uint8_t> *binaryData) std::vector<uint8_t> *binaryData)
...@@ -572,58 +581,58 @@ void WriteCppReplayForCall(const CallCapture &call, ...@@ -572,58 +581,58 @@ void WriteCppReplayForCall(const CallCapture &call,
WriteStringParamReplay(callOut, param); WriteStringParamReplay(callOut, param);
break; break;
case ParamType::TGLcharConstPointerPointer: case ParamType::TGLcharConstPointerPointer:
WriteStringPointerParamReplay(counters, callOut, header, call, param); WriteStringPointerParamReplay(dataTracker, callOut, header, call, param);
break; break;
case ParamType::TBufferIDConstPointer: case ParamType::TBufferIDConstPointer:
WriteResourceIDPointerParamReplay<gl::BufferID>(counters, callOut, out, call, WriteResourceIDPointerParamReplay<gl::BufferID>(dataTracker, callOut, out, call,
param); param);
break; break;
case ParamType::TFenceNVIDConstPointer: case ParamType::TFenceNVIDConstPointer:
WriteResourceIDPointerParamReplay<gl::FenceNVID>(counters, callOut, out, call, WriteResourceIDPointerParamReplay<gl::FenceNVID>(dataTracker, callOut, out,
param); call, param);
break; break;
case ParamType::TFramebufferIDConstPointer: case ParamType::TFramebufferIDConstPointer:
WriteResourceIDPointerParamReplay<gl::FramebufferID>(counters, callOut, out, WriteResourceIDPointerParamReplay<gl::FramebufferID>(dataTracker, callOut, out,
call, param); call, param);
break; break;
case ParamType::TMemoryObjectIDConstPointer: case ParamType::TMemoryObjectIDConstPointer:
WriteResourceIDPointerParamReplay<gl::MemoryObjectID>(counters, callOut, out, WriteResourceIDPointerParamReplay<gl::MemoryObjectID>(dataTracker, callOut, out,
call, param); call, param);
break; break;
case ParamType::TProgramPipelineIDConstPointer: case ParamType::TProgramPipelineIDConstPointer:
WriteResourceIDPointerParamReplay<gl::ProgramPipelineID>(counters, callOut, out, WriteResourceIDPointerParamReplay<gl::ProgramPipelineID>(dataTracker, callOut,
call, param); out, call, param);
break; break;
case ParamType::TQueryIDConstPointer: case ParamType::TQueryIDConstPointer:
WriteResourceIDPointerParamReplay<gl::QueryID>(counters, callOut, out, call, WriteResourceIDPointerParamReplay<gl::QueryID>(dataTracker, callOut, out, call,
param); param);
break; break;
case ParamType::TRenderbufferIDConstPointer: case ParamType::TRenderbufferIDConstPointer:
WriteResourceIDPointerParamReplay<gl::RenderbufferID>(counters, callOut, out, WriteResourceIDPointerParamReplay<gl::RenderbufferID>(dataTracker, callOut, out,
call, param); call, param);
break; break;
case ParamType::TSamplerIDConstPointer: case ParamType::TSamplerIDConstPointer:
WriteResourceIDPointerParamReplay<gl::SamplerID>(counters, callOut, out, call, WriteResourceIDPointerParamReplay<gl::SamplerID>(dataTracker, callOut, out,
param); call, param);
break; break;
case ParamType::TSemaphoreIDConstPointer: case ParamType::TSemaphoreIDConstPointer:
WriteResourceIDPointerParamReplay<gl::SemaphoreID>(counters, callOut, out, call, WriteResourceIDPointerParamReplay<gl::SemaphoreID>(dataTracker, callOut, out,
param); call, param);
break; break;
case ParamType::TTextureIDConstPointer: case ParamType::TTextureIDConstPointer:
WriteResourceIDPointerParamReplay<gl::TextureID>(counters, callOut, out, call, WriteResourceIDPointerParamReplay<gl::TextureID>(dataTracker, callOut, out,
param); call, param);
break; break;
case ParamType::TTransformFeedbackIDConstPointer: case ParamType::TTransformFeedbackIDConstPointer:
WriteResourceIDPointerParamReplay<gl::TransformFeedbackID>(counters, callOut, WriteResourceIDPointerParamReplay<gl::TransformFeedbackID>(dataTracker, callOut,
out, call, param); out, call, param);
break; break;
case ParamType::TVertexArrayIDConstPointer: case ParamType::TVertexArrayIDConstPointer:
WriteResourceIDPointerParamReplay<gl::VertexArrayID>(counters, callOut, out, WriteResourceIDPointerParamReplay<gl::VertexArrayID>(dataTracker, callOut, out,
call, param); call, param);
break; break;
default: default:
WriteBinaryParamReplay(counters, callOut, header, call, param, binaryData); WriteBinaryParamReplay(dataTracker, callOut, header, call, param, binaryData);
break; break;
} }
} }
...@@ -745,7 +754,7 @@ void WriteLoadBinaryDataCall(bool compression, ...@@ -745,7 +754,7 @@ void WriteLoadBinaryDataCall(bool compression,
void MaybeResetResources(std::stringstream &out, void MaybeResetResources(std::stringstream &out,
ResourceIDType resourceIDType, ResourceIDType resourceIDType,
DataCounters *counters, DataTracker *dataTracker,
std::stringstream &header, std::stringstream &header,
ResourceTracker *resourceTracker, ResourceTracker *resourceTracker,
std::vector<uint8_t> *binaryData) std::vector<uint8_t> *binaryData)
...@@ -789,7 +798,7 @@ void MaybeResetResources(std::stringstream &out, ...@@ -789,7 +798,7 @@ void MaybeResetResources(std::stringstream &out,
for (CallCapture &call : bufferRegenCalls[id]) for (CallCapture &call : bufferRegenCalls[id])
{ {
out << " "; out << " ";
WriteCppReplayForCall(call, counters, out, header, binaryData); WriteCppReplayForCall(call, dataTracker, out, header, binaryData);
out << ";\n"; out << ";\n";
} }
} }
...@@ -802,7 +811,7 @@ void MaybeResetResources(std::stringstream &out, ...@@ -802,7 +811,7 @@ void MaybeResetResources(std::stringstream &out,
for (CallCapture &call : bufferRestoreCalls[id]) for (CallCapture &call : bufferRestoreCalls[id])
{ {
out << " "; out << " ";
WriteCppReplayForCall(call, counters, out, header, binaryData); WriteCppReplayForCall(call, dataTracker, out, header, binaryData);
out << ";\n"; out << ";\n";
// Also note that this buffer has been implicitly unmapped by this call // Also note that this buffer has been implicitly unmapped by this call
...@@ -822,7 +831,7 @@ void MaybeResetResources(std::stringstream &out, ...@@ -822,7 +831,7 @@ void MaybeResetResources(std::stringstream &out,
for (CallCapture &call : bufferMapCalls[id]) for (CallCapture &call : bufferMapCalls[id])
{ {
out << " "; out << " ";
WriteCppReplayForCall(call, counters, out, header, binaryData); WriteCppReplayForCall(call, dataTracker, out, header, binaryData);
out << ";\n"; out << ";\n";
} }
} }
...@@ -834,7 +843,7 @@ void MaybeResetResources(std::stringstream &out, ...@@ -834,7 +843,7 @@ void MaybeResetResources(std::stringstream &out,
for (CallCapture &call : bufferUnmapCalls[id]) for (CallCapture &call : bufferUnmapCalls[id])
{ {
out << " "; out << " ";
WriteCppReplayForCall(call, counters, out, header, binaryData); WriteCppReplayForCall(call, dataTracker, out, header, binaryData);
out << ";\n"; out << ";\n";
} }
} }
...@@ -861,7 +870,7 @@ void WriteCppReplay(bool compression, ...@@ -861,7 +870,7 @@ void WriteCppReplay(bool compression,
std::vector<uint8_t> *binaryData, std::vector<uint8_t> *binaryData,
bool serializeStateEnabled) bool serializeStateEnabled)
{ {
DataCounters counters; DataTracker dataTracker;
std::stringstream out; std::stringstream out;
std::stringstream header; std::stringstream header;
...@@ -905,7 +914,7 @@ void WriteCppReplay(bool compression, ...@@ -905,7 +914,7 @@ void WriteCppReplay(bool compression,
for (const CallCapture &call : setupCalls) for (const CallCapture &call : setupCalls)
{ {
setupCallStreamParts << " "; setupCallStreamParts << " ";
WriteCppReplayForCall(call, &counters, setupCallStreamParts, header, binaryData); WriteCppReplayForCall(call, &dataTracker, setupCallStreamParts, header, binaryData);
setupCallStreamParts << ";\n"; setupCallStreamParts << ";\n";
if (partCount > 0 && ++callCount % kFunctionSizeLimit == 0) if (partCount > 0 && ++callCount % kFunctionSizeLimit == 0)
...@@ -956,8 +965,8 @@ void WriteCppReplay(bool compression, ...@@ -956,8 +965,8 @@ void WriteCppReplay(bool compression,
// TODO (http://anglebug.com/4599): Reset more state on frame loop // TODO (http://anglebug.com/4599): Reset more state on frame loop
for (ResourceIDType resourceType : AllEnums<ResourceIDType>()) for (ResourceIDType resourceType : AllEnums<ResourceIDType>())
{ {
MaybeResetResources(restoreCallStream, resourceType, &counters, header, resourceTracker, MaybeResetResources(restoreCallStream, resourceType, &dataTracker, header,
binaryData); resourceTracker, binaryData);
} }
out << restoreCallStream.str(); out << restoreCallStream.str();
...@@ -974,7 +983,7 @@ void WriteCppReplay(bool compression, ...@@ -974,7 +983,7 @@ void WriteCppReplay(bool compression,
for (const CallCapture &call : frameCalls) for (const CallCapture &call : frameCalls)
{ {
callStream << " "; callStream << " ";
WriteCppReplayForCall(call, &counters, callStream, header, binaryData); WriteCppReplayForCall(call, &dataTracker, callStream, header, binaryData);
callStream << ";\n"; callStream << ";\n";
} }
...@@ -4158,6 +4167,33 @@ int DataCounters::getAndIncrement(gl::EntryPoint entryPoint, const std::string & ...@@ -4158,6 +4167,33 @@ int DataCounters::getAndIncrement(gl::EntryPoint entryPoint, const std::string &
return mData[counterKey]++; return mData[counterKey]++;
} }
DataTracker::DataTracker() = default;
DataTracker::~DataTracker() = default;
StringCounters::StringCounters() = default;
StringCounters::~StringCounters() = default;
int StringCounters::getStringCounter(std::string &str)
{
const auto &id = mStringCounterMap.find(str);
if (id == mStringCounterMap.end())
{
return kStringNotFound;
}
else
{
return mStringCounterMap[str];
}
}
void StringCounters::setStringCounter(std::string &str, int &counter)
{
ASSERT(counter >= 0);
mStringCounterMap[str] = counter;
}
ResourceTracker::ResourceTracker() = default; ResourceTracker::ResourceTracker() = default;
ResourceTracker::~ResourceTracker() = default; ResourceTracker::~ResourceTracker() = default;
......
...@@ -23,6 +23,8 @@ enum class GLenumGroup; ...@@ -23,6 +23,8 @@ enum class GLenumGroup;
namespace angle namespace angle
{ {
using ParamData = std::vector<std::vector<uint8_t>>;
struct ParamCapture : angle::NonCopyable struct ParamCapture : angle::NonCopyable
{ {
ParamCapture(); ParamCapture();
...@@ -36,7 +38,7 @@ struct ParamCapture : angle::NonCopyable ...@@ -36,7 +38,7 @@ struct ParamCapture : angle::NonCopyable
ParamType type; ParamType type;
ParamValue value; ParamValue value;
gl::GLenumGroup enumGroup; // only used for param type GLenum, GLboolean and GLbitfield gl::GLenumGroup enumGroup; // only used for param type GLenum, GLboolean and GLbitfield
std::vector<std::vector<uint8_t>> data; ParamData data;
int arrayClientPointerIndex = -1; int arrayClientPointerIndex = -1;
size_t readBufferSizeBytes = 0; size_t readBufferSizeBytes = 0;
}; };
...@@ -177,6 +179,34 @@ class DataCounters final : angle::NonCopyable ...@@ -177,6 +179,34 @@ class DataCounters final : angle::NonCopyable
std::map<Counter, int> mData; std::map<Counter, int> mData;
}; };
constexpr int kStringNotFound = -1;
class StringCounters final : angle::NonCopyable
{
public:
StringCounters();
~StringCounters();
int getStringCounter(std::string &str);
void setStringCounter(std::string &str, int &counter);
private:
std::map<std::string, int> mStringCounterMap;
};
class DataTracker final : angle::NonCopyable
{
public:
DataTracker();
~DataTracker();
DataCounters &getCounters() { return mCounters; }
StringCounters &getStringCounters() { return mStringCounters; }
private:
DataCounters mCounters;
StringCounters mStringCounters;
};
using BufferSet = std::set<gl::BufferID>; using BufferSet = std::set<gl::BufferID>;
using BufferCalls = std::map<gl::BufferID, std::vector<CallCapture>>; using BufferCalls = std::map<gl::BufferID, std::vector<CallCapture>>;
......
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