Commit 609d45f6 by Jamie Madill Committed by Commit Bot

Capture/Replay: Use Renderbuffer ID map.

This should give a more robust replay. Devices are not guaranteed to return IDs in the same order in each instance of a program. Also for mid-execution capture we often won't have the same resources available. Once the Renderbuffer implementation lands we can switch to using more resource maps for different types of resources. Bug: angleproject:3611 Change-Id: I84a5b84856be3e8eb13e424e1990a39553adb82e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1719066Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent cc25d9fb
...@@ -59,6 +59,13 @@ void WriteInlineData(const std::vector<uint8_t> &vec, std::ostream &out) ...@@ -59,6 +59,13 @@ void WriteInlineData(const std::vector<uint8_t> &vec, std::ostream &out)
} }
constexpr size_t kInlineDataThreshold = 128; constexpr size_t kInlineDataThreshold = 128;
void WriteStringParamReplay(std::ostream &out, const ParamCapture &param)
{
const std::vector<uint8_t> &data = param.data[0];
std::string str(data.begin(), data.end());
out << "\"" << str << "\"";
}
} // anonymous namespace } // anonymous namespace
ParamCapture::ParamCapture() : type(ParamType::TGLenum), enumGroup(gl::GLenumGroup::DefaultGroup) {} ParamCapture::ParamCapture() : type(ParamType::TGLenum), enumGroup(gl::GLenumGroup::DefaultGroup) {}
...@@ -110,6 +117,13 @@ ParamCapture &ParamBuffer::getParam(const char *paramName, ParamType paramType, ...@@ -110,6 +117,13 @@ ParamCapture &ParamBuffer::getParam(const char *paramName, ParamType paramType,
return capture; return capture;
} }
const ParamCapture &ParamBuffer::getParam(const char *paramName,
ParamType paramType,
int index) const
{
return const_cast<ParamBuffer *>(this)->getParam(paramName, paramType, index);
}
void ParamBuffer::addParam(ParamCapture &&param) void ParamBuffer::addParam(ParamCapture &&param)
{ {
if (param.arrayClientPointerIndex != -1) if (param.arrayClientPointerIndex != -1)
...@@ -176,42 +190,51 @@ FrameCapture::FrameCapture() : mFrameIndex(0), mReadBufferSize(0) ...@@ -176,42 +190,51 @@ FrameCapture::FrameCapture() : mFrameIndex(0), mReadBufferSize(0)
FrameCapture::~FrameCapture() = default; FrameCapture::~FrameCapture() = default;
void FrameCapture::captureCall(const gl::Context *context, CallCapture &&call) void FrameCapture::maybeCaptureClientData(const gl::Context *context, const CallCapture &call)
{ {
if (call.entryPoint == gl::EntryPoint::VertexAttribPointer) switch (call.entryPoint)
{
case gl::EntryPoint::VertexAttribPointer:
{ {
// Get array location // Get array location
GLuint index = call.params.getParam("index", ParamType::TGLuint, 0).value.GLuintVal; GLuint index = call.params.getParam("index", ParamType::TGLuint, 0).value.GLuintVal;
if (call.params.hasClientArrayData()) if (call.params.hasClientArrayData())
{ {
mClientVertexArrayMap[index] = static_cast<uint32_t>(mCalls.size()); mClientVertexArrayMap[index] = static_cast<int>(mCalls.size());
} }
else else
{ {
mClientVertexArrayMap[index] = -1; mClientVertexArrayMap[index] = -1;
} }
break;
} }
else if (call.entryPoint == gl::EntryPoint::DrawArrays)
case gl::EntryPoint::DrawArrays:
{ {
if (context->getStateCache().hasAnyActiveClientAttrib()) if (context->getStateCache().hasAnyActiveClientAttrib())
{ {
// Get counts from paramBuffer. // Get counts from paramBuffer.
GLint firstVertex = call.params.getParam("first", ParamType::TGLint, 1).value.GLintVal; GLint firstVertex =
call.params.getParam("first", ParamType::TGLint, 1).value.GLintVal;
GLsizei drawCount = GLsizei drawCount =
call.params.getParam("count", ParamType::TGLsizei, 2).value.GLsizeiVal; call.params.getParam("count", ParamType::TGLsizei, 2).value.GLsizeiVal;
captureClientArraySnapshot(context, firstVertex + drawCount, 1); captureClientArraySnapshot(context, firstVertex + drawCount, 1);
} }
break;
} }
else if (call.entryPoint == gl::EntryPoint::DrawElements)
case gl::EntryPoint::DrawElements:
{ {
if (context->getStateCache().hasAnyActiveClientAttrib()) if (context->getStateCache().hasAnyActiveClientAttrib())
{ {
GLsizei count = call.params.getParam("count", ParamType::TGLsizei, 1).value.GLsizeiVal; GLsizei count =
call.params.getParam("count", ParamType::TGLsizei, 1).value.GLsizeiVal;
gl::DrawElementsType drawElementsType = gl::DrawElementsType drawElementsType =
call.params.getParam("typePacked", ParamType::TDrawElementsType, 2) call.params.getParam("typePacked", ParamType::TDrawElementsType, 2)
.value.DrawElementsTypeVal; .value.DrawElementsTypeVal;
const void *indices = call.params.getParam("indices", ParamType::TvoidConstPointer, 3) const void *indices =
call.params.getParam("indices", ParamType::TvoidConstPointer, 3)
.value.voidConstPointerVal; .value.voidConstPointerVal;
gl::IndexRange indexRange; gl::IndexRange indexRange;
...@@ -223,8 +246,8 @@ void FrameCapture::captureCall(const gl::Context *context, CallCapture &&call) ...@@ -223,8 +246,8 @@ void FrameCapture::captureCall(const gl::Context *context, CallCapture &&call)
if (elementArrayBuffer) if (elementArrayBuffer)
{ {
size_t offset = reinterpret_cast<size_t>(indices); size_t offset = reinterpret_cast<size_t>(indices);
(void)elementArrayBuffer->getIndexRange(context, drawElementsType, offset, count, (void)elementArrayBuffer->getIndexRange(context, drawElementsType, offset,
restart, &indexRange); count, restart, &indexRange);
} }
else else
{ {
...@@ -233,10 +256,55 @@ void FrameCapture::captureCall(const gl::Context *context, CallCapture &&call) ...@@ -233,10 +256,55 @@ void FrameCapture::captureCall(const gl::Context *context, CallCapture &&call)
captureClientArraySnapshot(context, indexRange.end, 1); captureClientArraySnapshot(context, indexRange.end, 1);
} }
break;
} }
default:
break;
}
}
void FrameCapture::captureCall(const gl::Context *context, CallCapture &&call)
{
// Process client data snapshots.
maybeCaptureClientData(context, call);
mReadBufferSize = std::max(mReadBufferSize, call.params.getReadBufferSize()); mReadBufferSize = std::max(mReadBufferSize, call.params.getReadBufferSize());
mCalls.emplace_back(std::move(call)); mCalls.emplace_back(std::move(call));
// Process resource ID updates.
maybeUpdateResourceIDs(context, mCalls.back());
}
void FrameCapture::maybeUpdateResourceIDs(const gl::Context *context, const CallCapture &call)
{
switch (call.entryPoint)
{
case gl::EntryPoint::GenRenderbuffers:
case gl::EntryPoint::GenRenderbuffersOES:
{
GLsizei n = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
const ParamCapture &renderbuffers =
call.params.getParam("renderbuffersPacked", ParamType::TRenderbufferIDPointer, 1);
ASSERT(renderbuffers.data.size() == 1);
const gl::RenderbufferID *returnedIDs =
reinterpret_cast<const gl::RenderbufferID *>(renderbuffers.data[0].data());
for (GLsizei idIndex = 0; idIndex < n; ++idIndex)
{
gl::RenderbufferID id = returnedIDs[idIndex];
GLsizei readBufferOffset = idIndex * sizeof(gl::RenderbufferID);
ParamBuffer params;
params.addValueParam("id", ParamType::TGLuint, id.value);
params.addValueParam("readBufferOffset", ParamType::TGLsizei, readBufferOffset);
mCalls.emplace_back("UpdateRenderbufferID", std::move(params));
}
break;
}
default:
break;
}
} }
void FrameCapture::captureClientArraySnapshot(const gl::Context *context, void FrameCapture::captureClientArraySnapshot(const gl::Context *context,
...@@ -322,6 +390,7 @@ void FrameCapture::saveCapturedFrameAsCpp() ...@@ -322,6 +390,7 @@ void FrameCapture::saveCapturedFrameAsCpp()
header << "#include <cstdio>\n"; header << "#include <cstdio>\n";
header << "#include <cstring>\n"; header << "#include <cstring>\n";
header << "#include <vector>\n"; header << "#include <vector>\n";
header << "#include <unordered_map>\n";
header << "\n"; header << "\n";
header << "namespace\n"; header << "namespace\n";
header << "{\n"; header << "{\n";
...@@ -339,6 +408,14 @@ void FrameCapture::saveCapturedFrameAsCpp() ...@@ -339,6 +408,14 @@ void FrameCapture::saveCapturedFrameAsCpp()
header << "}\n"; header << "}\n";
} }
header << "std::unordered_map<GLuint, GLuint> gRenderbufferMap;\n";
header << "void UpdateRenderbufferID(GLuint id, GLsizei readBufferOffset)\n";
header << "{\n";
header << " GLuint returnedID;\n";
header << " memcpy(&returnedID, &gReadBuffer[readBufferOffset], sizeof(GLuint));\n";
header << " gRenderbufferMap[id] = returnedID;\n";
header << "}\n";
out << "void ReplayFrame" << mFrameIndex << "()\n"; out << "void ReplayFrame" << mFrameIndex << "()\n";
out << "{\n"; out << "{\n";
out << " LoadBinaryData();\n"; out << " LoadBinaryData();\n";
...@@ -409,54 +486,11 @@ int FrameCapture::getAndIncrementCounter(gl::EntryPoint entryPoint, const std::s ...@@ -409,54 +486,11 @@ int FrameCapture::getAndIncrementCounter(gl::EntryPoint entryPoint, const std::s
return mDataCounters[counterKey]++; return mDataCounters[counterKey]++;
} }
void FrameCapture::writeCallReplay(const CallCapture &call, void FrameCapture::writeStringPointerParamReplay(std::ostream &out,
std::ostream &out,
std::ostream &header, std::ostream &header,
std::vector<uint8_t> *binaryData) const CallCapture &call,
const ParamCapture &param)
{ {
out << call.name() << "(";
bool first = true;
for (const ParamCapture &param : call.params.getParamCaptures())
{
if (!first)
{
out << ", ";
}
if (param.arrayClientPointerIndex != -1)
{
out << "gClientArrays[" << param.arrayClientPointerIndex << "].data()";
}
else if (param.readBufferSizeBytes > 0)
{
out << "reinterpret_cast<" << ParamTypeToString(param.type) << ">(gReadBuffer.data())";
}
else if (param.data.empty())
{
if (param.type == ParamType::TGLenum)
{
out << GLenumToString(param.enumGroup, param.value.GLenumVal);
}
else if (param.type == ParamType::TGLbitfield)
{
out << GLbitfieldToString(param.enumGroup, param.value.GLbitfieldVal);
}
else
{
out << param;
}
}
else
{
if (param.type == ParamType::TGLcharConstPointer)
{
const std::vector<uint8_t> &data = param.data[0];
std::string str(data.begin(), data.end());
out << "\"" << str << "\"";
}
else if (param.type == ParamType::TGLcharConstPointerPointer)
{
int counter = getAndIncrementCounter(call.entryPoint, param.name); int counter = getAndIncrementCounter(call.entryPoint, param.name);
header << "const char *"; header << "const char *";
...@@ -471,9 +505,46 @@ void FrameCapture::writeCallReplay(const CallCapture &call, ...@@ -471,9 +505,46 @@ void FrameCapture::writeCallReplay(const CallCapture &call,
header << " };\n"; header << " };\n";
WriteParamStaticVarName(call, param, counter, out); WriteParamStaticVarName(call, param, counter, out);
} }
else
void FrameCapture::writeRenderbufferIDPointerParamReplay(std::ostream &out,
std::ostream &header,
const CallCapture &call,
const ParamCapture &param)
{
int counter = getAndIncrementCounter(call.entryPoint, param.name);
header << "const GLuint ";
WriteParamStaticVarName(call, param, counter, header);
header << "[] = { ";
GLsizei n = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
const ParamCapture &renderbuffers =
call.params.getParam("renderbuffersPacked", ParamType::TRenderbufferIDConstPointer, 1);
ASSERT(renderbuffers.data.size() == 1);
const gl::RenderbufferID *returnedIDs =
reinterpret_cast<const gl::RenderbufferID *>(renderbuffers.data[0].data());
for (GLsizei resIndex = 0; resIndex < n; ++resIndex)
{
gl::RenderbufferID id = returnedIDs[resIndex];
if (resIndex > 0)
{ {
header << ", ";
}
header << "gRenderbufferMap[" << id.value << "]";
}
header << " };\n ";
WriteParamStaticVarName(call, param, counter, out);
}
void FrameCapture::writeBinaryParamReplay(std::ostream &out,
std::ostream &header,
const CallCapture &call,
const ParamCapture &param,
std::vector<uint8_t> *binaryData)
{
int counter = getAndIncrementCounter(call.entryPoint, param.name); int counter = getAndIncrementCounter(call.entryPoint, param.name);
ASSERT(param.data.size() == 1); ASSERT(param.data.size() == 1);
...@@ -484,15 +555,14 @@ void FrameCapture::writeCallReplay(const CallCapture &call, ...@@ -484,15 +555,14 @@ void FrameCapture::writeCallReplay(const CallCapture &call,
size_t offset = binaryData->size(); size_t offset = binaryData->size();
binaryData->resize(offset + data.size()); binaryData->resize(offset + data.size());
memcpy(binaryData->data() + offset, data.data(), data.size()); memcpy(binaryData->data() + offset, data.data(), data.size());
if (param.type == ParamType::TvoidConstPointer || if (param.type == ParamType::TvoidConstPointer || param.type == ParamType::TvoidPointer)
param.type == ParamType::TvoidPointer)
{ {
out << "&gBinaryData[" << offset << "]"; out << "&gBinaryData[" << offset << "]";
} }
else else
{ {
out << "reinterpret_cast<" << ParamTypeToString(param.type) out << "reinterpret_cast<" << ParamTypeToString(param.type) << ">(&gBinaryData["
<< ">(&gBinaryData[" << offset << "])"; << offset << "])";
} }
} }
else else
...@@ -537,13 +607,77 @@ void FrameCapture::writeCallReplay(const CallCapture &call, ...@@ -537,13 +607,77 @@ void FrameCapture::writeCallReplay(const CallCapture &call,
WriteParamStaticVarName(call, param, counter, out); WriteParamStaticVarName(call, param, counter, out);
} }
}
void FrameCapture::writeCallReplay(const CallCapture &call,
std::ostream &out,
std::ostream &header,
std::vector<uint8_t> *binaryData)
{
std::ostringstream callOut;
callOut << call.name() << "(";
bool first = true;
for (const ParamCapture &param : call.params.getParamCaptures())
{
if (!first)
{
callOut << ", ";
}
if (param.arrayClientPointerIndex != -1)
{
callOut << "gClientArrays[" << param.arrayClientPointerIndex << "].data()";
}
else if (param.readBufferSizeBytes > 0)
{
callOut << "reinterpret_cast<" << ParamTypeToString(param.type)
<< ">(gReadBuffer.data())";
}
else if (param.data.empty())
{
if (param.type == ParamType::TGLenum)
{
callOut << GLenumToString(param.enumGroup, param.value.GLenumVal);
}
else if (param.type == ParamType::TGLbitfield)
{
callOut << GLbitfieldToString(param.enumGroup, param.value.GLbitfieldVal);
}
else
{
callOut << param;
}
}
else
{
switch (param.type)
{
case ParamType::TGLcharConstPointer:
WriteStringParamReplay(callOut, param);
break;
case ParamType::TGLcharConstPointerPointer:
writeStringPointerParamReplay(callOut, header, call, param);
break;
case ParamType::TRenderbufferIDConstPointer:
writeRenderbufferIDPointerParamReplay(callOut, out, call, param);
break;
case ParamType::TRenderbufferIDPointer:
UNIMPLEMENTED();
break;
default:
writeBinaryParamReplay(callOut, header, call, param, binaryData);
break;
} }
} }
first = false; first = false;
} }
out << ")"; callOut << ")";
out << callOut.str();
} }
bool FrameCapture::enabled() const bool FrameCapture::enabled() const
...@@ -623,11 +757,10 @@ void WriteParamValueToStream<ParamType::TBufferID>(std::ostream &os, gl::BufferI ...@@ -623,11 +757,10 @@ void WriteParamValueToStream<ParamType::TBufferID>(std::ostream &os, gl::BufferI
os << value.value; os << value.value;
} }
// TODO(jmadill): Use renderbuffer ID map. http://anglebug.com/3611
template <> template <>
void WriteParamValueToStream<ParamType::TRenderbufferID>(std::ostream &os, gl::RenderbufferID value) void WriteParamValueToStream<ParamType::TRenderbufferID>(std::ostream &os, gl::RenderbufferID value)
{ {
os << value.value; os << "gRenderbufferMap[" << value.value << "]";
} }
// TODO(jmadill): Use texture ID map. http://anglebug.com/3611 // TODO(jmadill): Use texture ID map. http://anglebug.com/3611
......
...@@ -61,6 +61,8 @@ class ParamBuffer final : angle::NonCopyable ...@@ -61,6 +61,8 @@ class ParamBuffer final : angle::NonCopyable
T paramValue); T paramValue);
ParamCapture &getParam(const char *paramName, ParamType paramType, int index); ParamCapture &getParam(const char *paramName, ParamType paramType, int index);
const ParamCapture &getParam(const char *paramName, ParamType paramType, int index) const;
const ParamCapture &getReturnValue() const { return mReturnValueCapture; }
void addParam(ParamCapture &&param); void addParam(ParamCapture &&param);
void addReturnValue(ParamCapture &&returnValue); void addReturnValue(ParamCapture &&returnValue);
...@@ -119,6 +121,21 @@ class FrameCapture final : angle::NonCopyable ...@@ -119,6 +121,21 @@ class FrameCapture final : angle::NonCopyable
int getAndIncrementCounter(gl::EntryPoint entryPoint, const std::string &paramName); int getAndIncrementCounter(gl::EntryPoint entryPoint, const std::string &paramName);
bool anyClientArray() const; bool anyClientArray() const;
void saveCapturedFrameAsCpp(); void saveCapturedFrameAsCpp();
void writeStringPointerParamReplay(std::ostream &out,
std::ostream &header,
const CallCapture &call,
const ParamCapture &param);
void writeRenderbufferIDPointerParamReplay(std::ostream &out,
std::ostream &header,
const CallCapture &call,
const ParamCapture &param);
void writeBinaryParamReplay(std::ostream &out,
std::ostream &header,
const CallCapture &call,
const ParamCapture &param,
std::vector<uint8_t> *binaryData);
void maybeCaptureClientData(const gl::Context *context, const CallCapture &call);
void maybeUpdateResourceIDs(const gl::Context *context, const CallCapture &call);
std::vector<CallCapture> mCalls; std::vector<CallCapture> mCalls;
gl::AttribArray<int> mClientVertexArrayMap; gl::AttribArray<int> mClientVertexArrayMap;
......
...@@ -109,7 +109,7 @@ void CaptureDeleteFramebuffers_framebuffers(const Context *context, ...@@ -109,7 +109,7 @@ void CaptureDeleteFramebuffers_framebuffers(const Context *context,
const GLuint *framebuffers, const GLuint *framebuffers,
ParamCapture *paramCapture) ParamCapture *paramCapture)
{ {
UNIMPLEMENTED(); CaptureMemory(framebuffers, sizeof(GLuint) * n, paramCapture);
} }
void CaptureDeleteRenderbuffers_renderbuffersPacked(const Context *context, void CaptureDeleteRenderbuffers_renderbuffersPacked(const Context *context,
...@@ -118,7 +118,7 @@ void CaptureDeleteRenderbuffers_renderbuffersPacked(const Context *context, ...@@ -118,7 +118,7 @@ void CaptureDeleteRenderbuffers_renderbuffersPacked(const Context *context,
const RenderbufferID *renderbuffers, const RenderbufferID *renderbuffers,
ParamCapture *paramCapture) ParamCapture *paramCapture)
{ {
UNIMPLEMENTED(); CaptureMemory(renderbuffers, sizeof(RenderbufferID) * n, paramCapture);
} }
void CaptureDeleteTextures_texturesPacked(const Context *context, void CaptureDeleteTextures_texturesPacked(const Context *context,
...@@ -175,6 +175,7 @@ void CaptureGenRenderbuffers_renderbuffersPacked(const Context *context, ...@@ -175,6 +175,7 @@ void CaptureGenRenderbuffers_renderbuffersPacked(const Context *context,
ParamCapture *paramCapture) ParamCapture *paramCapture)
{ {
paramCapture->readBufferSizeBytes = sizeof(RenderbufferID) * n; paramCapture->readBufferSizeBytes = sizeof(RenderbufferID) * n;
CaptureMemory(renderbuffers, paramCapture->readBufferSizeBytes, paramCapture);
} }
void CaptureGenTextures_texturesPacked(const Context *context, void CaptureGenTextures_texturesPacked(const Context *context,
......
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