video_core: Refactor GPU interface (#7272)
* video_core: Refactor GPU interface * citra_qt: Better debug widget lifetime
This commit is contained in:
@@ -2,38 +2,22 @@
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <condition_variable>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <nihstro/bit_field.h>
|
||||
#include <nihstro/float24.h>
|
||||
#include <nihstro/shader_binary.h>
|
||||
#include "common/assert.h"
|
||||
#include "common/bit_field.h"
|
||||
#include "common/color.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/math_util.h"
|
||||
#include "common/vector_math.h"
|
||||
#include "core/core.h"
|
||||
#include "video_core/debug_utils/debug_utils.h"
|
||||
#include "video_core/pica_state.h"
|
||||
#include "video_core/pica_types.h"
|
||||
#include "video_core/rasterizer_interface.h"
|
||||
#include "video_core/regs_rasterizer.h"
|
||||
#include "video_core/regs_shader.h"
|
||||
#include "video_core/regs_texturing.h"
|
||||
#include "video_core/gpu.h"
|
||||
#include "video_core/pica/regs_shader.h"
|
||||
#include "video_core/pica/shader_setup.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "video_core/shader/shader.h"
|
||||
#include "video_core/texture/texture_decode.h"
|
||||
#include "video_core/utils.h"
|
||||
#include "video_core/video_core.h"
|
||||
|
||||
using nihstro::DVLBHeader;
|
||||
using nihstro::DVLEHeader;
|
||||
@@ -41,13 +25,13 @@ using nihstro::DVLPHeader;
|
||||
|
||||
namespace Pica {
|
||||
|
||||
void DebugContext::DoOnEvent(Event event, void* data) {
|
||||
void DebugContext::DoOnEvent(Event event, const void* data) {
|
||||
{
|
||||
std::unique_lock lock{breakpoint_mutex};
|
||||
|
||||
// Commit the rasterizer's caches so framebuffers, render targets, etc. will show on debug
|
||||
// widgets
|
||||
VideoCore::g_renderer->Rasterizer()->FlushAll();
|
||||
Core::System::GetInstance().GPU().Renderer().Rasterizer()->FlushAll();
|
||||
|
||||
// TODO: Should stop the CPU thread here once we multithread emulation.
|
||||
|
||||
@@ -84,8 +68,7 @@ std::shared_ptr<DebugContext> g_debug_context; // TODO: Get rid of this global
|
||||
|
||||
namespace DebugUtils {
|
||||
|
||||
void DumpShader(const std::string& filename, const ShaderRegs& config,
|
||||
const Shader::ShaderSetup& setup,
|
||||
void DumpShader(const std::string& filename, const ShaderRegs& config, const ShaderSetup& setup,
|
||||
const RasterizerRegs::VSOutputAttributes* output_attributes) {
|
||||
struct StuffToWrite {
|
||||
const u8* pointer;
|
||||
@@ -288,13 +271,13 @@ void StartPicaTracing() {
|
||||
g_is_pica_tracing = true;
|
||||
}
|
||||
|
||||
void OnPicaRegWrite(PicaTrace::Write write) {
|
||||
void OnPicaRegWrite(u16 cmd_id, u16 mask, u32 value) {
|
||||
std::lock_guard lock(pica_trace_mutex);
|
||||
|
||||
if (!g_is_pica_tracing)
|
||||
return;
|
||||
|
||||
pica_trace->writes.push_back(write);
|
||||
pica_trace->writes.push_back(PicaTrace::Write{cmd_id, mask, value});
|
||||
}
|
||||
|
||||
std::unique_ptr<PicaTrace> FinishPicaTracing() {
|
||||
@@ -313,153 +296,6 @@ std::unique_ptr<PicaTrace> FinishPicaTracing() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::string ReplacePattern(const std::string& input, const std::string& pattern,
|
||||
const std::string& replacement) {
|
||||
std::size_t start = input.find(pattern);
|
||||
if (start == std::string::npos)
|
||||
return input;
|
||||
|
||||
std::string ret = input;
|
||||
ret.replace(start, pattern.length(), replacement);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::string GetTevStageConfigSourceString(
|
||||
const TexturingRegs::TevStageConfig::Source& source) {
|
||||
|
||||
using Source = TexturingRegs::TevStageConfig::Source;
|
||||
static const std::map<Source, std::string> source_map = {
|
||||
{Source::PrimaryColor, "PrimaryColor"},
|
||||
{Source::PrimaryFragmentColor, "PrimaryFragmentColor"},
|
||||
{Source::SecondaryFragmentColor, "SecondaryFragmentColor"},
|
||||
{Source::Texture0, "Texture0"},
|
||||
{Source::Texture1, "Texture1"},
|
||||
{Source::Texture2, "Texture2"},
|
||||
{Source::Texture3, "Texture3"},
|
||||
{Source::PreviousBuffer, "PreviousBuffer"},
|
||||
{Source::Constant, "Constant"},
|
||||
{Source::Previous, "Previous"},
|
||||
};
|
||||
|
||||
const auto src_it = source_map.find(source);
|
||||
if (src_it == source_map.end())
|
||||
return "Unknown";
|
||||
|
||||
return src_it->second;
|
||||
}
|
||||
|
||||
static std::string GetTevStageConfigColorSourceString(
|
||||
const TexturingRegs::TevStageConfig::Source& source,
|
||||
const TexturingRegs::TevStageConfig::ColorModifier modifier) {
|
||||
|
||||
using ColorModifier = TexturingRegs::TevStageConfig::ColorModifier;
|
||||
static const std::map<ColorModifier, std::string> color_modifier_map = {
|
||||
{ColorModifier::SourceColor, "%source.rgb"},
|
||||
{ColorModifier::OneMinusSourceColor, "(1.0 - %source.rgb)"},
|
||||
{ColorModifier::SourceAlpha, "%source.aaa"},
|
||||
{ColorModifier::OneMinusSourceAlpha, "(1.0 - %source.aaa)"},
|
||||
{ColorModifier::SourceRed, "%source.rrr"},
|
||||
{ColorModifier::OneMinusSourceRed, "(1.0 - %source.rrr)"},
|
||||
{ColorModifier::SourceGreen, "%source.ggg"},
|
||||
{ColorModifier::OneMinusSourceGreen, "(1.0 - %source.ggg)"},
|
||||
{ColorModifier::SourceBlue, "%source.bbb"},
|
||||
{ColorModifier::OneMinusSourceBlue, "(1.0 - %source.bbb)"},
|
||||
};
|
||||
|
||||
auto src_str = GetTevStageConfigSourceString(source);
|
||||
auto modifier_it = color_modifier_map.find(modifier);
|
||||
std::string modifier_str = "%source.????";
|
||||
if (modifier_it != color_modifier_map.end())
|
||||
modifier_str = modifier_it->second;
|
||||
|
||||
return ReplacePattern(modifier_str, "%source", src_str);
|
||||
}
|
||||
|
||||
static std::string GetTevStageConfigAlphaSourceString(
|
||||
const TexturingRegs::TevStageConfig::Source& source,
|
||||
const TexturingRegs::TevStageConfig::AlphaModifier modifier) {
|
||||
|
||||
using AlphaModifier = TexturingRegs::TevStageConfig::AlphaModifier;
|
||||
static const std::map<AlphaModifier, std::string> alpha_modifier_map = {
|
||||
{AlphaModifier::SourceAlpha, "%source.a"},
|
||||
{AlphaModifier::OneMinusSourceAlpha, "(1.0 - %source.a)"},
|
||||
{AlphaModifier::SourceRed, "%source.r"},
|
||||
{AlphaModifier::OneMinusSourceRed, "(1.0 - %source.r)"},
|
||||
{AlphaModifier::SourceGreen, "%source.g"},
|
||||
{AlphaModifier::OneMinusSourceGreen, "(1.0 - %source.g)"},
|
||||
{AlphaModifier::SourceBlue, "%source.b"},
|
||||
{AlphaModifier::OneMinusSourceBlue, "(1.0 - %source.b)"},
|
||||
};
|
||||
|
||||
auto src_str = GetTevStageConfigSourceString(source);
|
||||
auto modifier_it = alpha_modifier_map.find(modifier);
|
||||
std::string modifier_str = "%source.????";
|
||||
if (modifier_it != alpha_modifier_map.end())
|
||||
modifier_str = modifier_it->second;
|
||||
|
||||
return ReplacePattern(modifier_str, "%source", src_str);
|
||||
}
|
||||
|
||||
static std::string GetTevStageConfigOperationString(
|
||||
const TexturingRegs::TevStageConfig::Operation& operation) {
|
||||
|
||||
using Operation = TexturingRegs::TevStageConfig::Operation;
|
||||
static const std::map<Operation, std::string> combiner_map = {
|
||||
{Operation::Replace, "%source1"},
|
||||
{Operation::Modulate, "(%source1 * %source2)"},
|
||||
{Operation::Add, "(%source1 + %source2)"},
|
||||
{Operation::AddSigned, "(%source1 + %source2) - 0.5"},
|
||||
{Operation::Lerp, "lerp(%source1, %source2, %source3)"},
|
||||
{Operation::Subtract, "(%source1 - %source2)"},
|
||||
{Operation::Dot3_RGB, "dot(%source1, %source2)"},
|
||||
{Operation::MultiplyThenAdd, "((%source1 * %source2) + %source3)"},
|
||||
{Operation::AddThenMultiply, "((%source1 + %source2) * %source3)"},
|
||||
};
|
||||
|
||||
const auto op_it = combiner_map.find(operation);
|
||||
if (op_it == combiner_map.end())
|
||||
return "Unknown op (%source1, %source2, %source3)";
|
||||
|
||||
return op_it->second;
|
||||
}
|
||||
|
||||
std::string GetTevStageConfigColorCombinerString(const TexturingRegs::TevStageConfig& tev_stage) {
|
||||
auto op_str = GetTevStageConfigOperationString(tev_stage.color_op);
|
||||
op_str = ReplacePattern(
|
||||
op_str, "%source1",
|
||||
GetTevStageConfigColorSourceString(tev_stage.color_source1, tev_stage.color_modifier1));
|
||||
op_str = ReplacePattern(
|
||||
op_str, "%source2",
|
||||
GetTevStageConfigColorSourceString(tev_stage.color_source2, tev_stage.color_modifier2));
|
||||
return ReplacePattern(
|
||||
op_str, "%source3",
|
||||
GetTevStageConfigColorSourceString(tev_stage.color_source3, tev_stage.color_modifier3));
|
||||
}
|
||||
|
||||
std::string GetTevStageConfigAlphaCombinerString(const TexturingRegs::TevStageConfig& tev_stage) {
|
||||
auto op_str = GetTevStageConfigOperationString(tev_stage.alpha_op);
|
||||
op_str = ReplacePattern(
|
||||
op_str, "%source1",
|
||||
GetTevStageConfigAlphaSourceString(tev_stage.alpha_source1, tev_stage.alpha_modifier1));
|
||||
op_str = ReplacePattern(
|
||||
op_str, "%source2",
|
||||
GetTevStageConfigAlphaSourceString(tev_stage.alpha_source2, tev_stage.alpha_modifier2));
|
||||
return ReplacePattern(
|
||||
op_str, "%source3",
|
||||
GetTevStageConfigAlphaSourceString(tev_stage.alpha_source3, tev_stage.alpha_modifier3));
|
||||
}
|
||||
|
||||
void DumpTevStageConfig(const std::array<TexturingRegs::TevStageConfig, 6>& stages) {
|
||||
std::string stage_info = "Tev setup:\n";
|
||||
for (std::size_t index = 0; index < stages.size(); ++index) {
|
||||
const auto& tev_stage = stages[index];
|
||||
stage_info += "Stage " + std::to_string(index) + ": " +
|
||||
GetTevStageConfigColorCombinerString(tev_stage) + " " +
|
||||
GetTevStageConfigAlphaCombinerString(tev_stage) + "\n";
|
||||
}
|
||||
LOG_TRACE(HW_GPU, "{}", stage_info);
|
||||
}
|
||||
|
||||
} // namespace DebugUtils
|
||||
|
||||
} // namespace Pica
|
||||
|
||||
@@ -4,22 +4,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <condition_variable>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
#include "common/vector_math.h"
|
||||
#include "video_core/regs_rasterizer.h"
|
||||
#include "video_core/regs_shader.h"
|
||||
#include "video_core/regs_texturing.h"
|
||||
#include "video_core/pica/regs_rasterizer.h"
|
||||
|
||||
namespace CiTrace {
|
||||
class Recorder;
|
||||
@@ -27,9 +21,8 @@ class Recorder;
|
||||
|
||||
namespace Pica {
|
||||
|
||||
namespace Shader {
|
||||
struct ShaderRegs;
|
||||
struct ShaderSetup;
|
||||
}
|
||||
|
||||
class DebugContext {
|
||||
public:
|
||||
@@ -87,7 +80,7 @@ public:
|
||||
* @param data Optional data pointer (if unused, this is a nullptr)
|
||||
* @note This function will perform nothing unless it is overridden in the child class.
|
||||
*/
|
||||
virtual void OnPicaBreakPointHit(Event event, void* data) {}
|
||||
virtual void OnPicaBreakPointHit(Event event, const void* data) {}
|
||||
|
||||
/**
|
||||
* Action to perform when emulation is resumed from a breakpoint.
|
||||
@@ -126,7 +119,7 @@ public:
|
||||
* @param data Optional data pointer (pass nullptr if unused). Needs to remain valid until
|
||||
* Resume() is called.
|
||||
*/
|
||||
void OnEvent(Event event, void* data) {
|
||||
void OnEvent(Event event, const void* data) {
|
||||
// This check is left in the header to allow the compiler to inline it.
|
||||
if (!breakpoints[(int)event].enabled)
|
||||
return;
|
||||
@@ -134,7 +127,7 @@ public:
|
||||
DoOnEvent(event, data);
|
||||
}
|
||||
|
||||
void DoOnEvent(Event event, void* data);
|
||||
void DoOnEvent(Event event, const void* data);
|
||||
|
||||
/**
|
||||
* Resume from the current breakpoint.
|
||||
@@ -181,10 +174,7 @@ extern std::shared_ptr<DebugContext> g_debug_context; // TODO: Get rid of this g
|
||||
|
||||
namespace DebugUtils {
|
||||
|
||||
#define PICA_LOG_TEV 0
|
||||
|
||||
void DumpShader(const std::string& filename, const ShaderRegs& config,
|
||||
const Shader::ShaderSetup& setup,
|
||||
void DumpShader(const std::string& filename, const ShaderRegs& config, const ShaderSetup& setup,
|
||||
const RasterizerRegs::VSOutputAttributes* output_attributes);
|
||||
|
||||
// Utility class to log Pica commands.
|
||||
@@ -203,46 +193,9 @@ void StartPicaTracing();
|
||||
inline bool IsPicaTracing() {
|
||||
return g_is_pica_tracing;
|
||||
}
|
||||
void OnPicaRegWrite(PicaTrace::Write write);
|
||||
void OnPicaRegWrite(u16 cmd_id, u16 mask, u32 value);
|
||||
std::unique_ptr<PicaTrace> FinishPicaTracing();
|
||||
|
||||
std::string GetTevStageConfigColorCombinerString(const TexturingRegs::TevStageConfig& tev_stage);
|
||||
std::string GetTevStageConfigAlphaCombinerString(const TexturingRegs::TevStageConfig& tev_stage);
|
||||
|
||||
/// Dumps the Tev stage config to log at trace level
|
||||
void DumpTevStageConfig(const std::array<TexturingRegs::TevStageConfig, 6>& stages);
|
||||
|
||||
/**
|
||||
* Used in the vertex loader to merge access records. TODO: Investigate if actually useful.
|
||||
*/
|
||||
class MemoryAccessTracker {
|
||||
/// Combine overlapping and close ranges
|
||||
void SimplifyRanges() {
|
||||
for (auto it = ranges.begin(); it != ranges.end(); ++it) {
|
||||
// NOTE: We add 32 to the range end address to make sure "close" ranges are combined,
|
||||
// too
|
||||
auto it2 = std::next(it);
|
||||
while (it2 != ranges.end() && it->first + it->second + 32 >= it2->first) {
|
||||
it->second = std::max(it->second, it2->first + it2->second - it->first);
|
||||
it2 = ranges.erase(it2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/// Record a particular memory access in the list
|
||||
void AddAccess(u32 paddr, u32 size) {
|
||||
// Create new range or extend existing one
|
||||
ranges[paddr] = std::max(ranges[paddr], size);
|
||||
|
||||
// Simplify ranges...
|
||||
SimplifyRanges();
|
||||
}
|
||||
|
||||
/// Map of accessed ranges (mapping start address to range size)
|
||||
std::map<u32, u32> ranges;
|
||||
};
|
||||
|
||||
} // namespace DebugUtils
|
||||
|
||||
} // namespace Pica
|
||||
|
||||
Reference in New Issue
Block a user