2015-04-04 11:57:31 +01:00
|
|
|
// Copyright 2015 Citra Emulator Project
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2023-07-06 23:52:40 +01:00
|
|
|
#include <span>
|
2016-04-30 16:34:51 +01:00
|
|
|
#include <string>
|
2015-04-04 11:57:31 +01:00
|
|
|
#include <unordered_map>
|
|
|
|
#include <vector>
|
|
|
|
#include <boost/crc.hpp>
|
2016-09-20 16:21:23 +01:00
|
|
|
#include "common/common_types.h"
|
2017-05-28 00:31:42 +01:00
|
|
|
#include "core/tracer/citrace.h"
|
2015-04-04 11:57:31 +01:00
|
|
|
|
|
|
|
namespace CiTrace {
|
|
|
|
|
|
|
|
class Recorder {
|
|
|
|
public:
|
2015-07-12 02:20:19 +01:00
|
|
|
struct InitialState {
|
|
|
|
std::vector<u32> gpu_registers;
|
|
|
|
std::vector<u32> lcd_registers;
|
|
|
|
std::vector<u32> pica_registers;
|
|
|
|
std::vector<u32> default_attributes;
|
|
|
|
std::vector<u32> vs_program_binary;
|
|
|
|
std::vector<u32> vs_swizzle_data;
|
|
|
|
std::vector<u32> vs_float_uniforms;
|
|
|
|
std::vector<u32> gs_program_binary;
|
|
|
|
std::vector<u32> gs_swizzle_data;
|
|
|
|
std::vector<u32> gs_float_uniforms;
|
|
|
|
};
|
|
|
|
|
2015-04-04 11:57:31 +01:00
|
|
|
/**
|
|
|
|
* Recorder constructor
|
2015-09-10 16:07:33 +01:00
|
|
|
* @param initial_state Initial recorder state
|
2015-04-04 11:57:31 +01:00
|
|
|
*/
|
2018-07-24 04:10:48 +01:00
|
|
|
explicit Recorder(const InitialState& initial_state);
|
2015-04-04 11:57:31 +01:00
|
|
|
|
|
|
|
/// Finish recording of this Citrace and save it using the given filename.
|
|
|
|
void Finish(const std::string& filename);
|
|
|
|
|
|
|
|
/// Mark end of a frame
|
|
|
|
void FrameFinished();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Store a copy of the given memory range in the recording.
|
|
|
|
* @note Use this whenever the GPU is about to access a particular memory region.
|
|
|
|
* @note The implementation will make sure to minimize redundant memory updates.
|
|
|
|
*/
|
|
|
|
void MemoryAccessed(const u8* data, u32 size, u32 physical_address);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Record a register write.
|
|
|
|
* @note Use this whenever a GPU-related MMIO register has been written to.
|
|
|
|
*/
|
2016-09-18 01:38:01 +01:00
|
|
|
template <typename T>
|
2015-04-04 11:57:31 +01:00
|
|
|
void RegisterWritten(u32 physical_address, T value);
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Initial state of recording start
|
2015-07-12 02:20:19 +01:00
|
|
|
InitialState initial_state;
|
2015-04-04 11:57:31 +01:00
|
|
|
|
|
|
|
// Command stream
|
|
|
|
struct StreamElement {
|
|
|
|
CTStreamElement data;
|
|
|
|
|
|
|
|
/**
|
2018-03-09 17:54:43 +00:00
|
|
|
* Extra data to store along "core" data.
|
|
|
|
* This is e.g. used for data used in MemoryUpdates.
|
|
|
|
*/
|
2015-04-04 11:57:31 +01:00
|
|
|
std::vector<u8> extra_data;
|
|
|
|
|
|
|
|
/// Optional CRC hash (e.g. for hashing memory regions)
|
|
|
|
boost::crc_32_type::value_type hash;
|
|
|
|
|
|
|
|
/// If true, refer to data already written to the output file instead of extra_data
|
|
|
|
bool uses_existing_data;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<StreamElement> stream;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal cache which maps hashes of memory contents to file offsets at which those memory
|
|
|
|
* contents are stored.
|
|
|
|
*/
|
|
|
|
std::unordered_map<boost::crc_32_type::value_type /*hash*/, u32 /*file_offset*/> memory_regions;
|
|
|
|
};
|
|
|
|
|
2018-03-09 17:54:43 +00:00
|
|
|
} // namespace CiTrace
|