Skip to content
7 changes: 7 additions & 0 deletions android/tools/replay/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ android {
}
}
buildTypes {
debug {
externalNativeBuild {
cmake {
cppFlags "-O2", "-DNDEBUG"
}
}
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
Expand Down
13 changes: 10 additions & 3 deletions framework/application/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ Application::Application(const std::string& name,
decode::FileProcessor* file_processor,
const std::string& cli_wsi_extension,
void* platform_specific_wsi_data) :
name_(name),
file_processor_(file_processor), running_(false), paused_(false), pause_frame_(0),
name_(name), file_processor_(file_processor), running_(false), paused_(false), pause_frame_(0),
cli_wsi_extension_(cli_wsi_extension), fps_info_(nullptr)
{
if (!cli_wsi_extension_.empty())
Expand Down Expand Up @@ -198,6 +197,14 @@ void Application::SetPaused(bool paused)
paused_ = paused;
}

void Application::SetRepeatFrameNTimes(uint32_t repeat_frame_n_times)
{
if (file_processor_)
{
file_processor_->SetRepeatFrameNTimes(repeat_frame_n_times);
}
}

bool Application::PlaySingleFrame()
{
bool success = false;
Expand Down Expand Up @@ -238,7 +245,7 @@ void Application::ProcessEvents(bool wait_for_input)
bool activeWsiContext = wsi_context && !wsi_context->GetWindows().empty();
auto pWindowFactory = wsi_context ? wsi_context->GetWindowFactory() : nullptr;
bool androidWsiContext = pWindowFactory && (strcmp(pWindowFactory->GetSurfaceExtensionName(),
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0);
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0);
if (activeWsiContext || androidWsiContext)
{
wsi_context->ProcessEvents(wait_for_input);
Expand Down
7 changes: 3 additions & 4 deletions framework/application/application.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class Application final

void SetPauseFrame(uint32_t pause_frame) { pause_frame_ = pause_frame; }

void SetRepeatFrameNTimes(uint32_t repeat_frame_n_times);

bool PlaySingleFrame();

void ProcessEvents(bool wait_for_input);
Expand All @@ -87,10 +89,7 @@ class Application final

void StopRunning() { running_ = false; }

uint32_t GetCurrentFrameNumber() const
{
return file_processor_->GetCurrentFrameNumber();
}
uint32_t GetCurrentFrameNumber() const { return file_processor_->GetCurrentFrameNumber(); }

private:
// clang-format off
Expand Down
76 changes: 69 additions & 7 deletions framework/decode/file_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@
#include "util/logging.h"

#include <string>
#include <limits>
#if defined(__ANDROID__)
#include <android/trace.h>
#else
#define ATrace_beginSection(name)
#define ATrace_endSection()
#endif

GFXRECON_BEGIN_NAMESPACE(gfxrecon)
GFXRECON_BEGIN_NAMESPACE(decode)
Expand Down Expand Up @@ -111,12 +118,60 @@ bool FileProcessor::ProcessNextFrame()

bool FileProcessor::ProcessBlocksOneFrame()
{
for (ApiDecoder* decoder : decoders_)
ATrace_beginSection("ProcessBlocksOneFrame");
block_parser_->SetDecompressionPolicy(BlockParser::DecompressionPolicy::kAlways);
if (current_frame_number_ == kFirstFrame)
{
decoder->SetCurrentFrameNumber(current_frame_number_);
// Process initial resources state
ATrace_beginSection("InitState");
if (!ProcessBlocks())
{
return false;
}
ATrace_endSection();
}
block_parser_->SetDecompressionPolicy(BlockParser::DecompressionPolicy::kAlways);
return ProcessBlocks();

int64_t start_offset = 0;
bool do_repeat = (repeat_frame_n_times_ > 0) && (!file_stack_.empty());

if (do_repeat)
{
start_offset = GetCurrentFile().active_file->Tell();
}

uint32_t start_frame = current_frame_number_;

// Handle limited command counts (e.g. from trim ranges or secondary files)
uint32_t remaining_commands_before = 0;

remaining_commands_before = GetCurrentFile().remaining_commands;

for (uint32_t i = 0; i <= repeat_frame_n_times_; ++i)
{
// Ensure we replay with the same frame number
current_frame_number_ = start_frame;

for (ApiDecoder* decoder : decoders_)
{
decoder->SetCurrentFrameNumber(current_frame_number_);
}

GetCurrentFile().remaining_commands =
(i < repeat_frame_n_times_) ? remaining_commands_before + 1 : remaining_commands_before;

if (!ProcessBlocks())
{
return false;
}

if (i < repeat_frame_n_times_)
{
SeekActiveFile(start_offset, util::platform::FileSeekSet);
}
}

ATrace_endSection();
return true;
}

bool FileProcessor::DoProcessNextFrame(const std::function<bool()>& block_processor)
Expand Down Expand Up @@ -274,6 +329,7 @@ void FileProcessor::DecrementRemainingCommands()

bool FileProcessor::ProcessBlocks()
{
ATrace_beginSection("ProcessBlocks");
BlockBuffer block_buffer;
bool success = true;

Expand Down Expand Up @@ -330,12 +386,19 @@ bool FileProcessor::ProcessBlocks()
}

// NOTE: Warnings for unknown/invalid blocks are handled in the BlockParser

if (process_visitor.IsStateDelimiter())
{
++block_index_;
DecrementRemainingCommands();
break;
}
if (process_visitor.IsFrameDelimiter())
{
// The ProcessVisitor (pre-dispatch) is not the right place to update the frame state, so do it
// here
UpdateEndFrameState();
++block_index_;
DecrementRemainingCommands();
break;
}
}
Expand All @@ -348,8 +411,8 @@ bool FileProcessor::ProcessBlocks()
++block_index_;
DecrementRemainingCommands();
}
ATrace_endSection();

DecrementRemainingCommands();
return success;
}

Expand Down Expand Up @@ -525,7 +588,6 @@ void FileProcessor::UpdateEndFrameState()

// Make sure to increment the frame number on the way out.
++current_frame_number_;
++block_index_;
}

bool FileProcessor::ProcessFrameDelimiter(gfxrecon::format::ApiCallId call_id)
Expand Down
21 changes: 11 additions & 10 deletions framework/decode/file_processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ class FileProcessor
block_index_to_ = block_index_to;
}

void SetRepeatFrameNTimes(uint32_t repeat_frame_n_times) { repeat_frame_n_times_ = repeat_frame_n_times; }

bool IsFrameDelimiter(format::BlockType block_type, format::MarkerType marker_type) const;
bool IsFrameDelimiter(format::ApiCallId call_id) const;

Expand Down Expand Up @@ -320,41 +322,37 @@ class FileProcessor
void operator()(const ExecuteBlocksFromFileArgs& execute_blocks)
{
// The block and marker type are implied by the Args type
is_frame_delimiter = false;
success = file_processor_.ProcessExecuteBlocksFromFile(execute_blocks);
success = file_processor_.ProcessExecuteBlocksFromFile(execute_blocks);
}

// State Marker control
void operator()(const StateBeginMarkerArgs& state_begin)
{
// The block and marker type are implied by the Args type
is_frame_delimiter = false;
success = true;
success = true;
file_processor_.ProcessStateBeginMarker(state_begin);
}

void operator()(const StateEndMarkerArgs& state_end)
{
// The block and marker type are implied by the Args type
is_frame_delimiter = false;
is_state_delimiter = true;
success = true;
file_processor_.ProcessStateEndMarker(state_end);
}

void operator()(const AnnotationArgs& annotation)
{
// The block and marker type are implied by the Command type
is_frame_delimiter = false;
success = true;
success = true;
file_processor_.ProcessAnnotation(annotation);
}

template <typename Args>
void operator()(const Args&)
{
// The default behavior for a Visit is a successful, non-frame-delimiter
is_frame_delimiter = false;
success = true;
success = true;
}

// Avoid unpacking the Arg from it's store in the Arg specific overloads
Expand All @@ -366,10 +364,12 @@ class FileProcessor

bool IsSuccess() const { return success; }
bool IsFrameDelimiter() const { return is_frame_delimiter; }
bool IsStateDelimiter() const { return is_state_delimiter; }
ProcessVisitor(FileProcessor& file_processor) : file_processor_(file_processor) {}

private:
bool is_frame_delimiter = false;
bool is_state_delimiter = false;
bool success = true;
FileProcessor& file_processor_;
};
Expand Down Expand Up @@ -420,6 +420,7 @@ class FileProcessor
int64_t block_index_from_{ 0 };
int64_t block_index_to_{ 0 };
bool loading_trimmed_capture_state_;
uint32_t repeat_frame_n_times_{ 0 };

std::string absolute_path_;
format::FileHeader file_header_;
Expand All @@ -432,7 +433,7 @@ class FileProcessor
struct ActiveFileContext
{
ActiveFileContext(FileInputStreamPtr&& active_file_, bool execute_til_eof_ = false) :
active_file(std::move(active_file_)), execute_till_eof(execute_til_eof_){};
active_file(std::move(active_file_)), execute_till_eof(execute_til_eof_) {};

FileInputStreamPtr active_file;
uint32_t remaining_commands{ 0 };
Expand Down
Loading