aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/tracer/recorder.h
blob: 6e4b700156a19a754023df73eff2f0a89b4a492e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#pragma once

#include <unordered_map>
#include <vector>

#include <boost/crc.hpp>

#include "common/common_types.h"

#include "citrace.h"

namespace CiTrace {

class Recorder {
public:
    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;
    };

    /**
     * Recorder constructor
     * @param default_attributes Pointer to an array of 32-bit-aligned 24-bit floating point values.
     * @param vs_float_uniforms Pointer to an array of 32-bit-aligned 24-bit floating point values.
     */
    Recorder(const InitialState& initial_state);

    /// 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.
     */
    template<typename T>
    void RegisterWritten(u32 physical_address, T value);

private:
    // Initial state of recording start
    InitialState initial_state;

    // Command stream
    struct StreamElement {
        CTStreamElement data;

        /**
          * Extra data to store along "core" data.
          * This is e.g. used for data used in MemoryUpdates.
          */
        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;
};

} // namespace