Commit 05114fe7 by Jiacheng Lu Committed by Commit Bot

Support in memory frame capture replay

Enable FrameCapture to dispatch its calls back to Context and replay them. Bug: angleproject:3785 Change-Id: I580eff1fca3e39414a9b45bb296e0f3866ea33bc Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1747055 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 6f24d8a7
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
"scripts/entry_point_packed_gl_enums.json": "scripts/entry_point_packed_gl_enums.json":
"7a8fdb26e6c70a091039789d51d6c30a", "7a8fdb26e6c70a091039789d51d6c30a",
"scripts/generate_entry_points.py": "scripts/generate_entry_points.py":
"0e171ae96ddf02733e37acc8942e3e0d", "00dc8410ad87e122314ac58579445188",
"scripts/gl.xml": "scripts/gl.xml":
"b470cb06b06cbbe7adb2c8129ec85708", "b470cb06b06cbbe7adb2c8129ec85708",
"scripts/gl_angle_ext.xml": "scripts/gl_angle_ext.xml":
...@@ -87,10 +87,12 @@ ...@@ -87,10 +87,12 @@
"97b5fe98b95b4ae36c68f723e64f993a", "97b5fe98b95b4ae36c68f723e64f993a",
"src/libANGLE/entry_points_enum_autogen.h": "src/libANGLE/entry_points_enum_autogen.h":
"f028ca107fe86e586e676a32863d2167", "f028ca107fe86e586e676a32863d2167",
"src/libANGLE/frame_capture_replay_autogen.cpp":
"0775906ffd94eb20b8012a3e22c13dad",
"src/libANGLE/frame_capture_utils_autogen.cpp": "src/libANGLE/frame_capture_utils_autogen.cpp":
"1b9e6440e9c7a67cfeb37aba06e7f9a8", "1b9e6440e9c7a67cfeb37aba06e7f9a8",
"src/libANGLE/frame_capture_utils_autogen.h": "src/libANGLE/frame_capture_utils_autogen.h":
"1dc4ceba91b09953ec935d6e683d9a1c", "d847a610224faa286787dae4fe81dc83",
"src/libANGLE/validationES1_autogen.h": "src/libANGLE/validationES1_autogen.h":
"8d3131d2bf2e6f521f46b44e64a6bff9", "8d3131d2bf2e6f521f46b44e64a6bff9",
"src/libANGLE/validationES2_autogen.h": "src/libANGLE/validationES2_autogen.h":
......
...@@ -354,6 +354,49 @@ template_parameter_capture_pointer = """ ...@@ -354,6 +354,49 @@ template_parameter_capture_pointer = """
template_parameter_capture_pointer_func = """void {name}({params});""" template_parameter_capture_pointer_func = """void {name}({params});"""
template_capture_replay_source = """// GENERATED FILE - DO NOT EDIT.
// Generated by {script_name} using data from {data_source_name}.
//
// Copyright {year} The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// frame_capture_replay_autogen.cpp:
// Util function to dispatch captured GL calls through Context and replay them.
#include "angle_gl.h"
#include "common/debug.h"
#include "common/debug.h"
#include "libANGLE/Context.h"
#include "libANGLE/Context.inl.h"
#include "libANGLE/FrameCapture.h"
using namespace gl;
namespace angle
{{
void FrameCapture::ReplayCall(gl::Context *context,
ReplayContext *replayContext,
const CallCapture &call)
{{
const ParamBuffer &params = call.params;
switch (call.entryPoint)
{{
{call_replay_cases}
default:
UNREACHABLE();
}}
}}
}} // namespace angle
"""
template_capture_replay_call_case = """case gl::EntryPoint::{entry_point}:
context->{context_call}({param_value_access});break;"""
static_cast_to_dict = { static_cast_to_dict = {
"GLintptr": "unsigned long long", "GLintptr": "unsigned long long",
"GLsizeiptr": "unsigned long long", "GLsizeiptr": "unsigned long long",
...@@ -485,6 +528,28 @@ union ParamValue ...@@ -485,6 +528,28 @@ union ParamValue
}}; }};
template <ParamType PType, typename T> template <ParamType PType, typename T>
T GetParamVal(const ParamValue &value);
{get_param_val_specializations}
template <ParamType PType, typename T>
T GetParamVal(const ParamValue &value)
{{
UNREACHABLE();
return T();
}}
template <typename T>
T AccessParamValue(ParamType paramType, const ParamValue &value)
{{
switch (paramType)
{{
{access_param_value_cases}
}}
}}
template <ParamType PType, typename T>
void SetParamVal(T valueIn, ParamValue *valueOut); void SetParamVal(T valueIn, ParamValue *valueOut);
{set_param_val_specializations} {set_param_val_specializations}
...@@ -551,6 +616,15 @@ const char *ParamTypeToString(ParamType paramType) ...@@ -551,6 +616,15 @@ const char *ParamTypeToString(ParamType paramType)
}} // namespace angle }} // namespace angle
""" """
template_get_param_val_specialization = """template <>
inline {type} GetParamVal<ParamType::T{enum}, {type}>(const ParamValue &value)
{{
return value.{union_name};
}}"""
template_access_param_value_case = """ case ParamType::T{enum}:
return GetParamVal<ParamType::T{enum}, T>(value);"""
template_set_param_val_specialization = """template <> template_set_param_val_specialization = """template <>
inline void SetParamVal<ParamType::T{enum}>({type} valueIn, ParamValue *valueOut) inline void SetParamVal<ParamType::T{enum}>({type} valueIn, ParamValue *valueOut)
{{ {{
...@@ -1213,6 +1287,17 @@ def format_param_type_union_type(param_type): ...@@ -1213,6 +1287,17 @@ def format_param_type_union_type(param_type):
return "%s %s;" % (get_param_type_type(param_type), get_param_type_union_name(param_type)) return "%s %s;" % (get_param_type_type(param_type), get_param_type_union_name(param_type))
def format_get_param_val_specialization(param_type):
return template_get_param_val_specialization.format(
enum=param_type,
type=get_param_type_type(param_type),
union_name=get_param_type_union_name(param_type))
def format_access_param_value_case(param_type):
return template_access_param_value_case.format(enum=param_type)
def format_set_param_val_specialization(param_type): def format_set_param_val_specialization(param_type):
return template_set_param_val_specialization.format( return template_set_param_val_specialization.format(
enum=param_type, enum=param_type,
...@@ -1233,6 +1318,10 @@ def write_capture_helper_header(all_param_types): ...@@ -1233,6 +1318,10 @@ def write_capture_helper_header(all_param_types):
param_types = "\n ".join(["T%s," % t for t in all_param_types]) param_types = "\n ".join(["T%s," % t for t in all_param_types])
param_union_values = "\n ".join([format_param_type_union_type(t) for t in all_param_types]) param_union_values = "\n ".join([format_param_type_union_type(t) for t in all_param_types])
get_param_val_specializations = "\n\n".join(
[format_get_param_val_specialization(t) for t in all_param_types])
access_param_value_cases = "\n".join(
[format_access_param_value_case(t) for t in all_param_types])
set_param_val_specializations = "\n\n".join( set_param_val_specializations = "\n\n".join(
[format_set_param_val_specialization(t) for t in all_param_types]) [format_set_param_val_specialization(t) for t in all_param_types])
init_param_value_cases = "\n".join([format_init_param_value_case(t) for t in all_param_types]) init_param_value_cases = "\n".join([format_init_param_value_case(t) for t in all_param_types])
...@@ -1243,6 +1332,8 @@ def write_capture_helper_header(all_param_types): ...@@ -1243,6 +1332,8 @@ def write_capture_helper_header(all_param_types):
year=date.today().year, year=date.today().year,
param_types=param_types, param_types=param_types,
param_union_values=param_union_values, param_union_values=param_union_values,
get_param_val_specializations=get_param_val_specializations,
access_param_value_cases=access_param_value_cases,
set_param_val_specializations=set_param_val_specializations, set_param_val_specializations=set_param_val_specializations,
init_param_value_cases=init_param_value_cases) init_param_value_cases=init_param_value_cases)
...@@ -1279,6 +1370,89 @@ def write_capture_helper_source(all_param_types): ...@@ -1279,6 +1370,89 @@ def write_capture_helper_source(all_param_types):
out.close() out.close()
def get_command_params_text(command_node, cmd_name):
param_text_list = list()
for param_node in command_node.findall('param'):
param_text_list.append("".join(param_node.itertext()))
return param_text_list
def is_get_pointer_command(command_name):
return command_name.endswith('Pointerv') and command_name.startswith('glGet')
def format_capture_replay_param_access(command_name, param_text_list, cmd_packed_gl_enums):
param_access_strs = list()
cmd_packed_enums = get_packed_enums(cmd_packed_gl_enums, command_name)
for i, param_text in enumerate(param_text_list):
param_type = just_the_type_packed(param_text, cmd_packed_enums)
param_name = just_the_name_packed(param_text, cmd_packed_enums)
pointer_count = param_type.count('*')
is_const = 'const' in param_type
if pointer_count == 0:
param_template = 'params.getParam("{name}", ParamType::T{enum_type}, {index}).value.{enum_type}Val'
elif pointer_count == 1 and is_const:
param_template = 'replayContext->getAsConstPointer<{type}>(params.getParam("{name}", ParamType::T{enum_type}, {index}))'
elif pointer_count == 2 and is_const:
param_template = 'replayContext->getAsPointerConstPointer<{type}>(params.getParam("{name}", ParamType::T{enum_type}, {index}))'
elif pointer_count == 1 or (pointer_count == 2 and is_get_pointer_command(command_name)):
param_template = 'replayContext->getReadBufferPointer<{type}>(params.getParam("{name}", ParamType::T{enum_type}, {index}))'
else:
assert False, "Not supported param type %s" % param_type
param_access_strs.append(
param_template.format(
index=i,
name=param_name,
type=param_type,
enum_type=get_capture_param_type_name(param_type)))
return ",".join(param_access_strs)
def format_capture_replay_call_case(command_to_param_types_mapping, cmd_packed_gl_enums):
call_str_list = list()
for command_name, cmd_param_texts in sorted(command_to_param_types_mapping.items()):
entry_point_name = command_name[2:] # strip the 'gl' prefix
call_str_list.append(
template_capture_replay_call_case.format(
entry_point=entry_point_name,
param_value_access=format_capture_replay_param_access(
command_name, cmd_param_texts, cmd_packed_gl_enums),
context_call=entry_point_name[0].lower() + entry_point_name[1:],
))
return '\n'.join(call_str_list)
def write_capture_replay_source(all_commands_nodes, gles_command_names, cmd_packed_gl_enums):
all_commands_names = set(gles_command_names)
command_to_param_types_mapping = dict()
for command_node in all_commands_nodes:
command_name = command_node.find('proto').find('name').text
if command_name not in all_commands_names:
continue
command_to_param_types_mapping[command_name] = get_command_params_text(
command_node, command_name)
call_replay_cases = format_capture_replay_call_case(command_to_param_types_mapping,
cmd_packed_gl_enums)
source_content = template_capture_replay_source.format(
script_name=os.path.basename(sys.argv[0]),
data_source_name="gl.xml and gl_angle_ext.xml",
year=date.today().year,
call_replay_cases=call_replay_cases,
)
source_file_path = registry_xml.script_relative(
"../src/libANGLE/frame_capture_replay_autogen.cpp")
with open(source_file_path, 'w') as f:
f.write(source_content)
def write_windows_def_file(data_source_name, lib, libexport, folder, exports): def write_windows_def_file(data_source_name, lib, libexport, folder, exports):
content = template_windows_def_file.format( content = template_windows_def_file.format(
...@@ -1379,6 +1553,7 @@ def main(): ...@@ -1379,6 +1553,7 @@ def main():
'../src/libANGLE/capture_gles_3_1_autogen.h', '../src/libANGLE/capture_gles_3_1_autogen.h',
'../src/libANGLE/capture_gles_ext_autogen.cpp', '../src/libANGLE/capture_gles_ext_autogen.cpp',
'../src/libANGLE/capture_gles_ext_autogen.h', '../src/libANGLE/capture_gles_ext_autogen.h',
'../src/libANGLE/frame_capture_replay_autogen.cpp',
'../src/libANGLE/frame_capture_utils_autogen.cpp', '../src/libANGLE/frame_capture_utils_autogen.cpp',
'../src/libANGLE/frame_capture_utils_autogen.h', '../src/libANGLE/frame_capture_utils_autogen.h',
'../src/libANGLE/entry_points_enum_autogen.cpp', '../src/libANGLE/entry_points_enum_autogen.cpp',
...@@ -1894,6 +2069,7 @@ def main(): ...@@ -1894,6 +2069,7 @@ def main():
all_gles_param_types = sorted(all_gles_param_types) all_gles_param_types = sorted(all_gles_param_types)
write_capture_helper_header(all_gles_param_types) write_capture_helper_header(all_gles_param_types)
write_capture_helper_source(all_gles_param_types) write_capture_helper_source(all_gles_param_types)
write_capture_replay_source(xml.all_commands, all_commands_no_suffix, cmd_packed_gl_enums)
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -61,6 +61,7 @@ ParamCapture::~ParamCapture() {} ...@@ -61,6 +61,7 @@ ParamCapture::~ParamCapture() {}
FrameCapture::FrameCapture() {} FrameCapture::FrameCapture() {}
FrameCapture::~FrameCapture() {} FrameCapture::~FrameCapture() {}
void FrameCapture::onEndFrame() {} void FrameCapture::onEndFrame() {}
void FrameCapture::replay(gl::Context *context) {}
#else #else
namespace namespace
{ {
...@@ -219,6 +220,18 @@ const char *CallCapture::name() const ...@@ -219,6 +220,18 @@ const char *CallCapture::name() const
return gl::GetEntryPointName(entryPoint); return gl::GetEntryPointName(entryPoint);
} }
ReplayContext::ReplayContext(size_t readBufferSizebytes,
const gl::AttribArray<size_t> &clientArraysSizebytes)
{
mReadBuffer.resize(readBufferSizebytes);
for (uint32_t i = 0; i < clientArraysSizebytes.size(); i++)
{
mClientArraysBuffer[i].resize(clientArraysSizebytes[i]);
}
}
ReplayContext::~ReplayContext() {}
FrameCapture::FrameCapture() : mFrameIndex(0), mReadBufferSize(0) FrameCapture::FrameCapture() : mFrameIndex(0), mReadBufferSize(0)
{ {
reset(); reset();
...@@ -290,7 +303,8 @@ void FrameCapture::maybeCaptureClientData(const gl::Context *context, const Call ...@@ -290,7 +303,8 @@ void FrameCapture::maybeCaptureClientData(const gl::Context *context, const Call
indexRange = gl::ComputeIndexRange(drawElementsType, indices, count, restart); indexRange = gl::ComputeIndexRange(drawElementsType, indices, count, restart);
} }
captureClientArraySnapshot(context, indexRange.end, 1); // index starts from 0
captureClientArraySnapshot(context, indexRange.end + 1, 1);
} }
break; break;
} }
...@@ -729,6 +743,41 @@ bool FrameCapture::enabled() const ...@@ -729,6 +743,41 @@ bool FrameCapture::enabled() const
return mFrameIndex < 100; return mFrameIndex < 100;
} }
void FrameCapture::replay(gl::Context *context)
{
ReplayContext replayContext(mReadBufferSize, mClientArraySizes);
for (const CallCapture &call : mCalls)
{
INFO() << "frame index: " << mFrameIndex << " " << call.name();
if (call.entryPoint == gl::EntryPoint::Invalid)
{
if (call.customFunctionName == "UpdateClientArrayPointer")
{
GLint arrayIndex =
call.params.getParam("arrayIndex", ParamType::TGLint, 0).value.GLintVal;
ASSERT(arrayIndex < gl::MAX_VERTEX_ATTRIBS);
const ParamCapture &pointerParam =
call.params.getParam("pointer", ParamType::TvoidConstPointer, 1);
ASSERT(pointerParam.data.size() == 1);
const void *pointer = pointerParam.data[0].data();
size_t size = static_cast<size_t>(
call.params.getParam("size", ParamType::TGLuint64, 2).value.GLuint64Val);
std::vector<uint8_t> &curClientArrayBuffer =
replayContext.getClientArraysBuffer()[arrayIndex];
ASSERT(curClientArrayBuffer.size() >= size);
memcpy(curClientArrayBuffer.data(), pointer, size);
}
continue;
}
ReplayCall(context, &replayContext, call);
}
}
void FrameCapture::reset() void FrameCapture::reset()
{ {
mCalls.clear(); mCalls.clear();
...@@ -753,7 +802,8 @@ void CaptureMemory(const void *source, size_t size, ParamCapture *paramCapture) ...@@ -753,7 +802,8 @@ void CaptureMemory(const void *source, size_t size, ParamCapture *paramCapture)
void CaptureString(const GLchar *str, ParamCapture *paramCapture) void CaptureString(const GLchar *str, ParamCapture *paramCapture)
{ {
CaptureMemory(str, strlen(str), paramCapture); // include the '\0' suffix
CaptureMemory(str, strlen(str) + 1, paramCapture);
} }
template <> template <>
......
...@@ -95,6 +95,60 @@ struct CallCapture ...@@ -95,6 +95,60 @@ struct CallCapture
ParamBuffer params; ParamBuffer params;
}; };
class ReplayContext
{
public:
ReplayContext(size_t readBufferSizebytes, const gl::AttribArray<size_t> &clientArraysSizebytes);
~ReplayContext();
template <typename T>
T getReadBufferPointer(const ParamCapture &param)
{
ASSERT(param.readBufferSizeBytes > 0);
ASSERT(mReadBuffer.size() >= param.readBufferSizeBytes);
return reinterpret_cast<T>(mReadBuffer.data());
}
template <typename T>
T getAsConstPointer(const ParamCapture &param)
{
if (param.arrayClientPointerIndex != -1)
{
return reinterpret_cast<T>(mClientArraysBuffer[param.arrayClientPointerIndex].data());
}
if (!param.data.empty())
{
ASSERT(param.data.size() == 1);
return reinterpret_cast<T>(param.data[0].data());
}
return nullptr;
}
template <typename T>
T getAsPointerConstPointer(const ParamCapture &param)
{
static_assert(sizeof(typename std::remove_pointer<T>::type) == sizeof(uint8_t *),
"pointer size not match!");
ASSERT(!param.data.empty());
mPointersBuffer.clear();
mPointersBuffer.reserve(param.data.size());
for (const std::vector<uint8_t> &data : param.data)
{
mPointersBuffer.emplace_back(data.data());
}
return reinterpret_cast<T>(mPointersBuffer.data());
}
gl::AttribArray<std::vector<uint8_t>> &getClientArraysBuffer() { return mClientArraysBuffer; }
private:
std::vector<uint8_t> mReadBuffer;
std::vector<const uint8_t *> mPointersBuffer;
gl::AttribArray<std::vector<uint8_t>> mClientArraysBuffer;
};
class FrameCapture final : angle::NonCopyable class FrameCapture final : angle::NonCopyable
{ {
public: public:
...@@ -104,6 +158,7 @@ class FrameCapture final : angle::NonCopyable ...@@ -104,6 +158,7 @@ class FrameCapture final : angle::NonCopyable
void captureCall(const gl::Context *context, CallCapture &&call); void captureCall(const gl::Context *context, CallCapture &&call);
void onEndFrame(); void onEndFrame();
bool enabled() const; bool enabled() const;
void replay(gl::Context *context);
private: private:
// <CallName, ParamName> // <CallName, ParamName>
...@@ -143,6 +198,10 @@ class FrameCapture final : angle::NonCopyable ...@@ -143,6 +198,10 @@ class FrameCapture final : angle::NonCopyable
gl::AttribArray<size_t> mClientArraySizes; gl::AttribArray<size_t> mClientArraySizes;
std::map<Counter, int> mDataCounters; std::map<Counter, int> mDataCounters;
size_t mReadBufferSize; size_t mReadBufferSize;
static void ReplayCall(gl::Context *context,
ReplayContext *replayContext,
const CallCapture &call);
}; };
template <typename CaptureFuncT, typename... ArgsT> template <typename CaptureFuncT, typename... ArgsT>
......
...@@ -643,8 +643,10 @@ void CaptureShaderSource_string(const Context *context, ...@@ -643,8 +643,10 @@ void CaptureShaderSource_string(const Context *context,
{ {
for (GLsizei index = 0; index < count; ++index) for (GLsizei index = 0; index < count; ++index)
{ {
size_t len = length ? length[index] : strlen(string[index]); // includes the '\0' suffix
size_t len = (length ? length[index] : strlen(string[index])) + 1;
CaptureMemory(string[index], len, paramCapture); CaptureMemory(string[index], len, paramCapture);
paramCapture->data[paramCapture->data.size() - 1][len] = '\0';
} }
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -938,6 +938,7 @@ libangle_capture_sources = [ ...@@ -938,6 +938,7 @@ libangle_capture_sources = [
"src/libANGLE/capture_gles_3_1_params.cpp", "src/libANGLE/capture_gles_3_1_params.cpp",
"src/libANGLE/capture_gles_ext_autogen.cpp", "src/libANGLE/capture_gles_ext_autogen.cpp",
"src/libANGLE/capture_gles_ext_params.cpp", "src/libANGLE/capture_gles_ext_params.cpp",
"src/libANGLE/frame_capture_replay_autogen.cpp",
"src/libANGLE/frame_capture_utils_autogen.cpp", "src/libANGLE/frame_capture_utils_autogen.cpp",
"src/libANGLE/gl_enum_utils_autogen.cpp", "src/libANGLE/gl_enum_utils_autogen.cpp",
] ]
......
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