From fd62580985b2f2d8f65b940148211bedc8d08404 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Thu, 21 May 2015 02:51:28 +0200 Subject: CiTrace: Record default vertex attributes. --- src/citra_qt/debugger/graphics_tracing.cpp | 8 +++ src/core/CMakeLists.txt | 2 +- src/core/tracer/citrace.h | 101 +++++++++++++++++++++++++++++ src/core/tracer/recorder.cpp | 70 +++++++++++--------- src/core/tracer/recorder.h | 23 ++++--- src/core/tracer/tracer.h | 98 ---------------------------- 6 files changed, 162 insertions(+), 140 deletions(-) create mode 100644 src/core/tracer/citrace.h delete mode 100644 src/core/tracer/tracer.h diff --git a/src/citra_qt/debugger/graphics_tracing.cpp b/src/citra_qt/debugger/graphics_tracing.cpp index eac40582..3e88346c 100644 --- a/src/citra_qt/debugger/graphics_tracing.cpp +++ b/src/citra_qt/debugger/graphics_tracing.cpp @@ -62,12 +62,20 @@ void GraphicsTracingWidget::StartRecording() { // Encode floating point numbers to 24-bit values // TODO: Drop this explicit conversion once we store float24 values bit-correctly internally. + std::array, 16> default_attributes; + for (unsigned i = 0; i < 16; ++i) { + for (unsigned comp = 0; comp < 3; ++comp) { + default_attributes[i][comp] = nihstro::to_float24(Pica::g_state.vs.default_attributes[i][comp].ToFloat32()); + } + } + std::array, 96> vs_float_uniforms; for (unsigned i = 0; i < 96; ++i) for (unsigned comp = 0; comp < 3; ++comp) vs_float_uniforms[i][comp] = nihstro::to_float24(Pica::g_state.vs.uniforms.f[i][comp].ToFloat32()); auto recorder = new CiTrace::Recorder((u32*)&GPU::g_regs, 0x700, nullptr, 0, (u32*)&Pica::g_state.regs, 0x300, + (u32*)default_attributes.data(), default_attributes.size() * 4, shader_binary.data(), shader_binary.size(), swizzle_data.data(), swizzle_data.size(), (u32*)vs_float_uniforms.data(), vs_float_uniforms.size() * 4, diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5066eb25..8267ee58 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -245,7 +245,7 @@ set(HEADERS loader/loader.h loader/ncch.h tracer/recorder.h - tracer/tracer.h + tracer/citrace.h mem_map.h memory.h memory_setup.h diff --git a/src/core/tracer/citrace.h b/src/core/tracer/citrace.h new file mode 100644 index 00000000..5deb6ce9 --- /dev/null +++ b/src/core/tracer/citrace.h @@ -0,0 +1,101 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +namespace CiTrace { + +// NOTE: Things are stored in little-endian + +#pragma pack(1) + +struct CTHeader { + static const char* ExpectedMagicWord() { + return "CiTr"; + } + + static uint32_t ExpectedVersion() { + return 1; + } + + char magic[4]; + uint32_t version; + uint32_t 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 uint32_t units. + uint32_t gpu_registers; + uint32_t gpu_registers_size; + uint32_t lcd_registers; + uint32_t lcd_registers_size; + uint32_t pica_registers; + uint32_t pica_registers_size; + uint32_t default_attributes; + uint32_t default_attributes_size; + uint32_t vs_program_binary; + uint32_t vs_program_binary_size; + uint32_t vs_swizzle_data; + uint32_t vs_swizzle_data_size; + uint32_t vs_float_uniforms; + uint32_t vs_float_uniforms_size; + uint32_t gs_program_binary; + uint32_t gs_program_binary_size; + uint32_t gs_swizzle_data; + uint32_t gs_swizzle_data_size; + uint32_t gs_float_uniforms; + uint32_t 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; + + uint32_t stream_offset; + uint32_t stream_size; +}; + +enum CTStreamElementType : uint32_t { + FrameMarker = 0xE1, + MemoryLoad = 0xE2, + RegisterWrite = 0xE3, +}; + +struct CTMemoryLoad { + uint32_t file_offset; + uint32_t size; + uint32_t physical_address; + uint32_t pad; +}; + +struct CTRegisterWrite { + uint32_t physical_address; + + enum : uint32_t { + 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 + uint64_t value; +}; + +struct CTStreamElement { + CTStreamElementType type; + + union { + CTMemoryLoad memory_load; + CTRegisterWrite register_write; + }; +}; + +#pragma pack() + +} diff --git a/src/core/tracer/recorder.cpp b/src/core/tracer/recorder.cpp index 73ebdd38..c5251634 100644 --- a/src/core/tracer/recorder.cpp +++ b/src/core/tracer/recorder.cpp @@ -12,18 +12,20 @@ namespace CiTrace { -Recorder::Recorder(u32* gpu_registers, u32 gpu_registers_size, - u32* lcd_registers, u32 lcd_registers_size, - u32* pica_registers, u32 pica_registers_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) +Recorder::Recorder(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) : gpu_registers(gpu_registers, gpu_registers + gpu_registers_size), lcd_registers(lcd_registers, lcd_registers + lcd_registers_size), pica_registers(pica_registers, pica_registers + pica_registers_size), + default_attributes(default_attributes, default_attributes + default_attributes_size), vs_program_binary(vs_program_binary, vs_program_binary + vs_program_binary_size), vs_swizzle_data(vs_swizzle_data, vs_swizzle_data + vs_swizzle_data_size), vs_float_uniforms(vs_float_uniforms, vs_float_uniforms + vs_float_uniforms_size), @@ -43,27 +45,29 @@ void Recorder::Finish(const std::string& filename) { // Calculate file offsets auto& initial = header.initial_state_offsets; - initial.gpu_registers_size = gpu_registers.size(); - initial.lcd_registers_size = lcd_registers.size(); - initial.pica_registers_size = pica_registers.size(); - initial.vs_program_binary_size = vs_program_binary.size(); - initial.vs_swizzle_data_size = vs_swizzle_data.size(); - initial.vs_float_uniforms_size = vs_float_uniforms.size(); - initial.gs_program_binary_size = gs_program_binary.size(); - initial.gs_swizzle_data_size = gs_swizzle_data.size(); - initial.gs_float_uniforms_size = gs_float_uniforms.size(); - header.stream_size = 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.vs_program_binary = initial.pica_registers + initial.pica_registers_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); + initial.gpu_registers_size = gpu_registers.size(); + initial.lcd_registers_size = lcd_registers.size(); + initial.pica_registers_size = pica_registers.size(); + initial.default_attributes_size = default_attributes.size(); + initial.vs_program_binary_size = vs_program_binary.size(); + initial.vs_swizzle_data_size = vs_swizzle_data.size(); + initial.vs_float_uniforms_size = vs_float_uniforms.size(); + initial.gs_program_binary_size = gs_program_binary.size(); + initial.gs_swizzle_data_size = gs_swizzle_data.size(); + initial.gs_float_uniforms_size = gs_float_uniforms.size(); + header.stream_size = 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) { @@ -103,9 +107,13 @@ void Recorder::Finish(const std::string& filename) { throw "Failed to write LCD registers"; written = file.WriteArray(pica_registers.data(), pica_registers.size()); - if (written != pica_registers.size() || file.Tell() != initial.vs_program_binary) + if (written != pica_registers.size() || file.Tell() != initial.default_attributes) throw "Failed to write Pica registers"; + written = file.WriteArray(default_attributes.data(), default_attributes.size()); + if (written != default_attributes.size() || file.Tell() != initial.vs_program_binary) + throw "Failed to write default vertex attributes"; + written = file.WriteArray(vs_program_binary.data(), vs_program_binary.size()); if (written != vs_program_binary.size() || file.Tell() != initial.vs_swizzle_data) throw "Failed to write vertex shader program binary"; diff --git a/src/core/tracer/recorder.h b/src/core/tracer/recorder.h index 8fec0a97..da77aac5 100644 --- a/src/core/tracer/recorder.h +++ b/src/core/tracer/recorder.h @@ -11,7 +11,7 @@ #include "common/common_types.h" -#include "tracer.h" +#include "citrace.h" namespace CiTrace { @@ -19,17 +19,19 @@ class Recorder { public: /** * 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(u32* gpu_registers, u32 gpu_registers_size, - u32* lcd_registers, u32 lcd_registers_size, - u32* pica_registers, u32 pica_registers_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); + Recorder(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); /// Finish recording of this Citrace and save it using the given filename. void Finish(const std::string& filename); @@ -56,6 +58,7 @@ private: 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; diff --git a/src/core/tracer/tracer.h b/src/core/tracer/tracer.h deleted file mode 100644 index 1545d743..00000000 --- a/src/core/tracer/tracer.h +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include - -namespace CiTrace { - -// NOTE: Things are stored in little-endian - -#pragma pack(1) - -struct CTHeader { - static const char* ExpectedMagicWord() { - return "CiTr"; - } - - static uint32_t ExpectedVersion() { - return 1; - } - - char magic[4]; - uint32_t version; - uint32_t 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 uint32_t units. - uint32_t gpu_registers; - uint32_t gpu_registers_size; - uint32_t lcd_registers; - uint32_t lcd_registers_size; - uint32_t pica_registers; - uint32_t pica_registers_size; - uint32_t vs_program_binary; - uint32_t vs_program_binary_size; - uint32_t vs_swizzle_data; - uint32_t vs_swizzle_data_size; - uint32_t vs_float_uniforms; - uint32_t vs_float_uniforms_size; - uint32_t gs_program_binary; - uint32_t gs_program_binary_size; - uint32_t gs_swizzle_data; - uint32_t gs_swizzle_data_size; - uint32_t gs_float_uniforms; - uint32_t gs_float_uniforms_size; - - // Other things we might want to store here: - // - Initial framebuffer data, maybe even a full copy of FCRAM/VRAM - // - Default vertex attributes - } initial_state_offsets; - - uint32_t stream_offset; - uint32_t stream_size; -}; - -enum CTStreamElementType : uint32_t { - FrameMarker = 0xE1, - MemoryLoad = 0xE2, - RegisterWrite = 0xE3, -}; - -struct CTMemoryLoad { - uint32_t file_offset; - uint32_t size; - uint32_t physical_address; - uint32_t pad; -}; - -struct CTRegisterWrite { - uint32_t physical_address; - - enum : uint32_t { - 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 - uint64_t value; -}; - -struct CTStreamElement { - CTStreamElementType type; - - union { - CTMemoryLoad memory_load; - CTRegisterWrite register_write; - }; -}; - -#pragma pack() - -} -- cgit v1.2.3