diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a2e2e976e5..4204ace2b2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -463,9 +463,6 @@ add_library(core STATIC settings.h telemetry_session.cpp telemetry_session.h - tracer/citrace.h - tracer/recorder.cpp - tracer/recorder.h ) create_target_directory_groups(core) diff --git a/src/core/tracer/citrace.h b/src/core/tracer/citrace.h deleted file mode 100644 index 21fdc127a8..0000000000 --- a/src/core/tracer/citrace.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_types.h" - -namespace CiTrace { - -// NOTE: Things are stored in little-endian - -#pragma pack(1) - -struct CTHeader { - static const char* ExpectedMagicWord() { - return "CiTr"; - } - - static u32 ExpectedVersion() { - return 1; - } - - char magic[4]; - u32 version; - u32 header_size; - - struct { - // NOTE: Register range sizes are technically hardware-constants, but the actual limits - // aren't known. Hence we store the presumed limits along the offsets. - // Sizes are given in u32 units. - u32 gpu_registers; - u32 gpu_registers_size; - u32 lcd_registers; - u32 lcd_registers_size; - u32 pica_registers; - u32 pica_registers_size; - u32 default_attributes; - u32 default_attributes_size; - u32 vs_program_binary; - u32 vs_program_binary_size; - u32 vs_swizzle_data; - u32 vs_swizzle_data_size; - u32 vs_float_uniforms; - u32 vs_float_uniforms_size; - u32 gs_program_binary; - u32 gs_program_binary_size; - u32 gs_swizzle_data; - u32 gs_swizzle_data_size; - u32 gs_float_uniforms; - u32 gs_float_uniforms_size; - - // Other things we might want to store here: - // - Initial framebuffer data, maybe even a full copy of FCRAM/VRAM - // - Lookup tables for fragment lighting - // - Lookup tables for procedural textures - } initial_state_offsets; - - u32 stream_offset; - u32 stream_size; -}; - -enum CTStreamElementType : u32 { - FrameMarker = 0xE1, - MemoryLoad = 0xE2, - RegisterWrite = 0xE3, -}; - -struct CTMemoryLoad { - u32 file_offset; - u32 size; - u32 physical_address; - u32 pad; -}; - -struct CTRegisterWrite { - u32 physical_address; - - enum : u32 { - SIZE_8 = 0xD1, - SIZE_16 = 0xD2, - SIZE_32 = 0xD3, - SIZE_64 = 0xD4, - } size; - - // TODO: Make it clearer which bits of this member are used for sizes other than 32 bits - u64 value; -}; - -struct CTStreamElement { - CTStreamElementType type; - - union { - CTMemoryLoad memory_load; - CTRegisterWrite register_write; - }; -}; - -#pragma pack() -} // namespace CiTrace diff --git a/src/core/tracer/recorder.cpp b/src/core/tracer/recorder.cpp deleted file mode 100644 index 73cacb47f3..0000000000 --- a/src/core/tracer/recorder.cpp +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include "common/assert.h" -#include "common/file_util.h" -#include "common/logging/log.h" -#include "core/tracer/recorder.h" - -namespace CiTrace { - -Recorder::Recorder(const InitialState& initial_state) : initial_state(initial_state) {} - -void Recorder::Finish(const std::string& filename) { - // Setup CiTrace header - CTHeader header; - std::memcpy(header.magic, CTHeader::ExpectedMagicWord(), 4); - header.version = CTHeader::ExpectedVersion(); - header.header_size = sizeof(CTHeader); - - // Calculate file offsets - auto& initial = header.initial_state_offsets; - - initial.gpu_registers_size = static_cast(initial_state.gpu_registers.size()); - initial.lcd_registers_size = static_cast(initial_state.lcd_registers.size()); - initial.pica_registers_size = static_cast(initial_state.pica_registers.size()); - initial.default_attributes_size = static_cast(initial_state.default_attributes.size()); - initial.vs_program_binary_size = static_cast(initial_state.vs_program_binary.size()); - initial.vs_swizzle_data_size = static_cast(initial_state.vs_swizzle_data.size()); - initial.vs_float_uniforms_size = static_cast(initial_state.vs_float_uniforms.size()); - initial.gs_program_binary_size = static_cast(initial_state.gs_program_binary.size()); - initial.gs_swizzle_data_size = static_cast(initial_state.gs_swizzle_data.size()); - initial.gs_float_uniforms_size = static_cast(initial_state.gs_float_uniforms.size()); - header.stream_size = static_cast(stream.size()); - - initial.gpu_registers = sizeof(header); - initial.lcd_registers = initial.gpu_registers + initial.gpu_registers_size * sizeof(u32); - initial.pica_registers = initial.lcd_registers + initial.lcd_registers_size * sizeof(u32); - ; - initial.default_attributes = initial.pica_registers + initial.pica_registers_size * sizeof(u32); - initial.vs_program_binary = - initial.default_attributes + initial.default_attributes_size * sizeof(u32); - initial.vs_swizzle_data = - initial.vs_program_binary + initial.vs_program_binary_size * sizeof(u32); - initial.vs_float_uniforms = - initial.vs_swizzle_data + initial.vs_swizzle_data_size * sizeof(u32); - initial.gs_program_binary = - initial.vs_float_uniforms + initial.vs_float_uniforms_size * sizeof(u32); - initial.gs_swizzle_data = - initial.gs_program_binary + initial.gs_program_binary_size * sizeof(u32); - initial.gs_float_uniforms = - initial.gs_swizzle_data + initial.gs_swizzle_data_size * sizeof(u32); - header.stream_offset = initial.gs_float_uniforms + initial.gs_float_uniforms_size * sizeof(u32); - - // Iterate through stream elements, update relevant stream element data - for (auto& stream_element : stream) { - switch (stream_element.data.type) { - case MemoryLoad: { - auto& file_offset = memory_regions[stream_element.hash]; - if (!stream_element.uses_existing_data) { - file_offset = header.stream_offset; - } - stream_element.data.memory_load.file_offset = file_offset; - break; - } - - default: - // Other commands don't use any extra data - DEBUG_ASSERT(stream_element.extra_data.size() == 0); - break; - } - header.stream_offset += static_cast(stream_element.extra_data.size()); - } - - try { - // Open file and write header - FileUtil::IOFile file(filename, "wb"); - std::size_t written = file.WriteObject(header); - if (written != 1 || file.Tell() != initial.gpu_registers) - throw "Failed to write header"; - - // Write initial state - written = - file.WriteArray(initial_state.gpu_registers.data(), initial_state.gpu_registers.size()); - if (written != initial_state.gpu_registers.size() || file.Tell() != initial.lcd_registers) - throw "Failed to write GPU registers"; - - written = - file.WriteArray(initial_state.lcd_registers.data(), initial_state.lcd_registers.size()); - if (written != initial_state.lcd_registers.size() || file.Tell() != initial.pica_registers) - throw "Failed to write LCD registers"; - - written = file.WriteArray(initial_state.pica_registers.data(), - initial_state.pica_registers.size()); - if (written != initial_state.pica_registers.size() || - file.Tell() != initial.default_attributes) - throw "Failed to write Pica registers"; - - written = file.WriteArray(initial_state.default_attributes.data(), - initial_state.default_attributes.size()); - if (written != initial_state.default_attributes.size() || - file.Tell() != initial.vs_program_binary) - throw "Failed to write default vertex attributes"; - - written = file.WriteArray(initial_state.vs_program_binary.data(), - initial_state.vs_program_binary.size()); - if (written != initial_state.vs_program_binary.size() || - file.Tell() != initial.vs_swizzle_data) - throw "Failed to write vertex shader program binary"; - - written = file.WriteArray(initial_state.vs_swizzle_data.data(), - initial_state.vs_swizzle_data.size()); - if (written != initial_state.vs_swizzle_data.size() || - file.Tell() != initial.vs_float_uniforms) - throw "Failed to write vertex shader swizzle data"; - - written = file.WriteArray(initial_state.vs_float_uniforms.data(), - initial_state.vs_float_uniforms.size()); - if (written != initial_state.vs_float_uniforms.size() || - file.Tell() != initial.gs_program_binary) - throw "Failed to write vertex shader float uniforms"; - - written = file.WriteArray(initial_state.gs_program_binary.data(), - initial_state.gs_program_binary.size()); - if (written != initial_state.gs_program_binary.size() || - file.Tell() != initial.gs_swizzle_data) - throw "Failed to write geomtry shader program binary"; - - written = file.WriteArray(initial_state.gs_swizzle_data.data(), - initial_state.gs_swizzle_data.size()); - if (written != initial_state.gs_swizzle_data.size() || - file.Tell() != initial.gs_float_uniforms) - throw "Failed to write geometry shader swizzle data"; - - written = file.WriteArray(initial_state.gs_float_uniforms.data(), - initial_state.gs_float_uniforms.size()); - if (written != initial_state.gs_float_uniforms.size() || - file.Tell() != initial.gs_float_uniforms + sizeof(u32) * initial.gs_float_uniforms_size) - throw "Failed to write geometry shader float uniforms"; - - // Iterate through stream elements, write "extra data" - for (const auto& stream_element : stream) { - if (stream_element.extra_data.size() == 0) - continue; - - written = - file.WriteBytes(stream_element.extra_data.data(), stream_element.extra_data.size()); - if (written != stream_element.extra_data.size()) - throw "Failed to write extra data"; - } - - if (file.Tell() != header.stream_offset) - throw "Unexpected end of extra data"; - - // Write actual stream elements - for (const auto& stream_element : stream) { - if (1 != file.WriteObject(stream_element.data)) - throw "Failed to write stream element"; - } - } catch (const char* str) { - LOG_ERROR(HW_GPU, "Writing CiTrace file failed: {}", str); - } -} - -void Recorder::FrameFinished() { - stream.push_back({{FrameMarker}}); -} - -void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) { - StreamElement element = {{MemoryLoad}}; - element.data.memory_load.size = size; - element.data.memory_load.physical_address = physical_address; - - // Compute hash over given memory region to check if the contents are already stored internally - boost::crc_32_type result; - result.process_bytes(data, size); - element.hash = result.checksum(); - - element.uses_existing_data = (memory_regions.find(element.hash) != memory_regions.end()); - if (!element.uses_existing_data) { - element.extra_data.resize(size); - memcpy(element.extra_data.data(), data, size); - memory_regions.insert({element.hash, 0}); // file offset will be initialized in Finish() - } - - stream.push_back(element); -} - -template -void Recorder::RegisterWritten(u32 physical_address, T value) { - StreamElement element = {{RegisterWrite}}; - element.data.register_write.size = - (sizeof(T) == 1) ? CTRegisterWrite::SIZE_8 - : (sizeof(T) == 2) ? CTRegisterWrite::SIZE_16 - : (sizeof(T) == 4) ? CTRegisterWrite::SIZE_32 - : CTRegisterWrite::SIZE_64; - element.data.register_write.physical_address = physical_address; - element.data.register_write.value = value; - - stream.push_back(element); -} - -template void Recorder::RegisterWritten(u32, u8); -template void Recorder::RegisterWritten(u32, u16); -template void Recorder::RegisterWritten(u32, u32); -template void Recorder::RegisterWritten(u32, u64); -} // namespace CiTrace diff --git a/src/core/tracer/recorder.h b/src/core/tracer/recorder.h deleted file mode 100644 index e1cefd5fec..0000000000 --- a/src/core/tracer/recorder.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include -#include "common/common_types.h" -#include "core/tracer/citrace.h" - -namespace CiTrace { - -class Recorder { -public: - struct InitialState { - std::vector gpu_registers; - std::vector lcd_registers; - std::vector pica_registers; - std::vector default_attributes; - std::vector vs_program_binary; - std::vector vs_swizzle_data; - std::vector vs_float_uniforms; - std::vector gs_program_binary; - std::vector gs_swizzle_data; - std::vector gs_float_uniforms; - }; - - /** - * Recorder constructor - * @param initial_state Initial recorder state - */ - explicit 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 - 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 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 stream; - - /** - * Internal cache which maps hashes of memory contents to file offsets at which those memory - * contents are stored. - */ - std::unordered_map memory_regions; -}; - -} // namespace CiTrace diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 3451d321d8..aafd6f31b5 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -18,7 +18,6 @@ #include "core/perf_stats.h" #include "core/settings.h" #include "core/telemetry_session.h" -#include "core/tracer/recorder.h" #include "video_core/morton.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/renderer_opengl.h"