[D3D12] Switch from gflags to cvars

This commit is contained in:
Triang3l 2019-08-03 16:53:23 +03:00
commit 352f12f92e
127 changed files with 959 additions and 647 deletions

9
.gitmodules vendored
View File

@ -16,9 +16,6 @@
[submodule "third_party/catch"] [submodule "third_party/catch"]
path = third_party/catch path = third_party/catch
url = https://github.com/catchorg/Catch2.git url = https://github.com/catchorg/Catch2.git
[submodule "third_party/gflags"]
path = third_party/gflags
url = https://github.com/benvanik/gflags.git
[submodule "third_party/premake-core"] [submodule "third_party/premake-core"]
path = third_party/premake-core path = third_party/premake-core
url = https://github.com/xenia-project/premake-core.git url = https://github.com/xenia-project/premake-core.git
@ -49,3 +46,9 @@
[submodule "third_party/capstone"] [submodule "third_party/capstone"]
path = third_party/capstone path = third_party/capstone
url = https://github.com/xenia-project/capstone.git url = https://github.com/xenia-project/capstone.git
[submodule "third_party/cpptoml"]
path = third_party/cpptoml
url = https://github.com/skystrife/cpptoml
[submodule "third_party/cxxopts"]
path = third_party/cxxopts
url = https://github.com/jarro2783/cxxopts

View File

@ -193,30 +193,9 @@ filter("platforms:Windows")
"dxguid", "dxguid",
}) })
-- Create scratch/ path and dummy flags file if needed. -- Create scratch/ path
if not os.isdir("scratch") then if not os.isdir("scratch") then
os.mkdir("scratch") os.mkdir("scratch")
local flags_file = io.open("scratch/flags.txt", "w")
flags_file:write("# Put flags, one on each line.\n")
flags_file:write("# Launch executables with --flags_file=scratch/flags.txt\n")
flags_file:write("\n")
flags_file:write("--cpu=x64\n")
flags_file:write("#--enable_haswell_instructions=false\n")
flags_file:write("\n")
flags_file:write("--debug\n")
flags_file:write("#--protect_zero=false\n")
flags_file:write("\n")
flags_file:write("#--mute\n")
flags_file:write("\n")
flags_file:write("--fast_stdout\n")
flags_file:write("#--flush_stdout=false\n")
flags_file:write("\n")
flags_file:write("#--vsync=false\n")
flags_file:write("#--trace_gpu_prefix=scratch/gpu/gpu_trace_\n")
flags_file:write("#--trace_gpu_stream\n")
flags_file:write("#--disable_framebuffer_readback\n")
flags_file:write("\n")
flags_file:close()
end end
solution("xenia") solution("xenia")
@ -237,12 +216,12 @@ solution("xenia")
end end
configurations({"Checked", "Debug", "Release"}) configurations({"Checked", "Debug", "Release"})
-- Include third party files first so they don't have to deal with gflags.
include("third_party/aes_128.lua") include("third_party/aes_128.lua")
include("third_party/capstone.lua") include("third_party/capstone.lua")
include("third_party/dxbc.lua") include("third_party/dxbc.lua")
include("third_party/discord-rpc.lua") include("third_party/discord-rpc.lua")
include("third_party/gflags.lua") include("third_party/cxxopts.lua")
include("third_party/cpptoml.lua")
include("third_party/glew.lua") include("third_party/glew.lua")
include("third_party/glslang-spirv.lua") include("third_party/glslang-spirv.lua")
include("third_party/imgui.lua") include("third_party/imgui.lua")

View File

@ -7,8 +7,6 @@
****************************************************************************** ******************************************************************************
*/ */
#include <gflags/gflags.h>
#include "xenia/app/emulator_window.h" #include "xenia/app/emulator_window.h"
// Autogenerated by `xb premake`. // Autogenerated by `xb premake`.
@ -17,6 +15,7 @@
#include "third_party/imgui/imgui.h" #include "third_party/imgui/imgui.h"
#include "xenia/app/discord/discord_presence.h" #include "xenia/app/discord/discord_presence.h"
#include "xenia/base/clock.h" #include "xenia/base/clock.h"
#include "xenia/base/cvar.h"
#include "xenia/base/debugging.h" #include "xenia/base/debugging.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/platform.h" #include "xenia/base/platform.h"
@ -29,7 +28,8 @@
#include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_dialog.h"
#include "xenia/ui/imgui_drawer.h" #include "xenia/ui/imgui_drawer.h"
DEFINE_bool(discord, false, "Enable Discord rich presence"); DECLARE_bool(debug);
DEFINE_bool(discord, false, "Enable Discord rich presence", "General");
namespace xe { namespace xe {
namespace app { namespace app {
@ -85,7 +85,7 @@ bool EmulatorWindow::Initialize() {
return false; return false;
} }
if (FLAGS_discord) { if (cvars::discord) {
discord::DiscordPresence::InitializeDiscord(); discord::DiscordPresence::InitializeDiscord();
discord::DiscordPresence::NotPlaying(); discord::DiscordPresence::NotPlaying();
} }
@ -344,7 +344,7 @@ void EmulatorWindow::FileOpen() {
void EmulatorWindow::FileClose() { void EmulatorWindow::FileClose() {
if (emulator_->is_title_open()) { if (emulator_->is_title_open()) {
emulator_->TerminateTitle(); emulator_->TerminateTitle();
if (FLAGS_discord) { if (cvars::discord) {
discord::DiscordPresence::NotPlaying(); discord::DiscordPresence::NotPlaying();
} }
} }
@ -398,7 +398,7 @@ void EmulatorWindow::CpuTimeScalarSetDouble() {
} }
void EmulatorWindow::CpuBreakIntoDebugger() { void EmulatorWindow::CpuBreakIntoDebugger() {
if (!FLAGS_debug) { if (!cvars::debug) {
xe::ui::ImGuiDialog::ShowMessageBox(window_.get(), "Xenia Debugger", xe::ui::ImGuiDialog::ShowMessageBox(window_.get(), "Xenia Debugger",
"Xenia must be launched with the " "Xenia must be launched with the "
"--debug flag in order to enable " "--debug flag in order to enable "
@ -444,7 +444,7 @@ void EmulatorWindow::UpdateTitle() {
auto game_title = emulator()->game_title(); auto game_title = emulator()->game_title();
title += xe::format_string(L" | [%.8X] %s", emulator()->title_id(), title += xe::format_string(L" | [%.8X] %s", emulator()->title_id(),
game_title.c_str()); game_title.c_str());
if (FLAGS_discord) { if (cvars::discord) {
discord::DiscordPresence::PlayingTitle(game_title); discord::DiscordPresence::PlayingTitle(game_title);
} }
} }

View File

@ -12,7 +12,6 @@ project("xenia-app")
"capstone", "capstone",
"dxbc", "dxbc",
"discord-rpc", "discord-rpc",
"gflags",
"glew", "glew",
"glslang-spirv", "glslang-spirv",
"imgui", "imgui",
@ -46,9 +45,6 @@ project("xenia-app")
"XBYAK_NO_OP_NAMES", "XBYAK_NO_OP_NAMES",
"XBYAK_ENABLE_OMITTED_OPERAND", "XBYAK_ENABLE_OMITTED_OPERAND",
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
local_platform_files() local_platform_files()
files({ files({
"xenia_main.cc", "xenia_main.cc",
@ -92,6 +88,5 @@ project("xenia-app")
if not os.isfile(user_file) then if not os.isfile(user_file) then
debugdir(project_root) debugdir(project_root)
debugargs({ debugargs({
"--flagfile=scratch/flags.txt",
}) })
end end

View File

@ -7,14 +7,14 @@
****************************************************************************** ******************************************************************************
*/ */
#include <gflags/gflags.h>
#include "xenia/app/emulator_window.h" #include "xenia/app/emulator_window.h"
#include "xenia/base/cvar.h"
#include "xenia/base/debugging.h" #include "xenia/base/debugging.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/main.h" #include "xenia/base/main.h"
#include "xenia/base/profiling.h" #include "xenia/base/profiling.h"
#include "xenia/base/threading.h" #include "xenia/base/threading.h"
#include "xenia/config.h"
#include "xenia/debug/ui/debug_window.h" #include "xenia/debug/ui/debug_window.h"
#include "xenia/emulator.h" #include "xenia/emulator.h"
#include "xenia/ui/file_picker.h" #include "xenia/ui/file_picker.h"
@ -40,26 +40,33 @@
#include "xenia/hid/xinput/xinput_hid.h" #include "xenia/hid/xinput/xinput_hid.h"
#endif // XE_PLATFORM_WIN32 #endif // XE_PLATFORM_WIN32
DEFINE_string(apu, "any", "Audio system. Use: [any, nop, xaudio2]"); #include "third_party/xbyak/xbyak/xbyak_util.h"
DEFINE_string(gpu, "any", "Graphics system. Use: [any, vulkan, null]");
DEFINE_string(hid, "any", "Input system. Use: [any, nop, winkey, xinput]");
DEFINE_string(target, "", "Specifies the target .xex or .iso to execute."); DEFINE_string(apu, "any", "Audio system. Use: [any, nop, xaudio2]", "General");
DEFINE_bool(fullscreen, false, "Toggles fullscreen"); DEFINE_string(gpu, "any", "Graphics system. Use: [any, vulkan, null]",
"General");
DEFINE_string(hid, "any", "Input system. Use: [any, nop, winkey, xinput]",
"General");
DEFINE_string(content_root, "", "Root path for content (save/etc) storage."); DEFINE_bool(fullscreen, false, "Toggles fullscreen", "General");
DEFINE_bool(mount_scratch, false, "Enable scratch mount"); DEFINE_string(content_root, "", "Root path for content (save/etc) storage.",
DEFINE_bool(mount_cache, false, "Enable cache mount"); "General");
DEFINE_bool(mount_scratch, false, "Enable scratch mount", "General");
DEFINE_bool(mount_cache, false, "Enable cache mount", "General");
CmdVar(target, "", "Specifies the target .xex or .iso to execute.");
DECLARE_bool(debug);
namespace xe { namespace xe {
namespace app { namespace app {
std::unique_ptr<apu::AudioSystem> CreateAudioSystem(cpu::Processor* processor) { std::unique_ptr<apu::AudioSystem> CreateAudioSystem(cpu::Processor* processor) {
if (FLAGS_apu.compare("nop") == 0) { if (cvars::apu.compare("nop") == 0) {
return apu::nop::NopAudioSystem::Create(processor); return apu::nop::NopAudioSystem::Create(processor);
#if XE_PLATFORM_WIN32 #if XE_PLATFORM_WIN32
} else if (FLAGS_apu.compare("xaudio2") == 0) { } else if (cvars::apu.compare("xaudio2") == 0) {
return apu::xaudio2::XAudio2AudioSystem::Create(processor); return apu::xaudio2::XAudio2AudioSystem::Create(processor);
#endif // XE_PLATFORM_WIN32 #endif // XE_PLATFORM_WIN32
} else { } else {
@ -79,15 +86,15 @@ std::unique_ptr<apu::AudioSystem> CreateAudioSystem(cpu::Processor* processor) {
} }
std::unique_ptr<gpu::GraphicsSystem> CreateGraphicsSystem() { std::unique_ptr<gpu::GraphicsSystem> CreateGraphicsSystem() {
if (FLAGS_gpu.compare("vulkan") == 0) { if (cvars::gpu.compare("vulkan") == 0) {
return std::unique_ptr<gpu::GraphicsSystem>( return std::unique_ptr<gpu::GraphicsSystem>(
new xe::gpu::vulkan::VulkanGraphicsSystem()); new xe::gpu::vulkan::VulkanGraphicsSystem());
#if XE_PLATFORM_WIN32 #if XE_PLATFORM_WIN32
} else if (FLAGS_gpu.compare("d3d12") == 0) { } else if (cvars::gpu.compare("d3d12") == 0) {
return std::unique_ptr<gpu::GraphicsSystem>( return std::unique_ptr<gpu::GraphicsSystem>(
new xe::gpu::d3d12::D3D12GraphicsSystem()); new xe::gpu::d3d12::D3D12GraphicsSystem());
#endif // XE_PLATFORM_WIN32 #endif // XE_PLATFORM_WIN32
} else if (FLAGS_gpu.compare("null") == 0) { } else if (cvars::gpu.compare("null") == 0) {
return std::unique_ptr<gpu::GraphicsSystem>( return std::unique_ptr<gpu::GraphicsSystem>(
new xe::gpu::null::NullGraphicsSystem()); new xe::gpu::null::NullGraphicsSystem());
} else { } else {
@ -115,12 +122,12 @@ std::unique_ptr<gpu::GraphicsSystem> CreateGraphicsSystem() {
std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers( std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers(
ui::Window* window) { ui::Window* window) {
std::vector<std::unique_ptr<hid::InputDriver>> drivers; std::vector<std::unique_ptr<hid::InputDriver>> drivers;
if (FLAGS_hid.compare("nop") == 0) { if (cvars::hid.compare("nop") == 0) {
drivers.emplace_back(xe::hid::nop::Create(window)); drivers.emplace_back(xe::hid::nop::Create(window));
#if XE_PLATFORM_WIN32 #if XE_PLATFORM_WIN32
} else if (FLAGS_hid.compare("winkey") == 0) { } else if (cvars::hid.compare("winkey") == 0) {
drivers.emplace_back(xe::hid::winkey::Create(window)); drivers.emplace_back(xe::hid::winkey::Create(window));
} else if (FLAGS_hid.compare("xinput") == 0) { } else if (cvars::hid.compare("xinput") == 0) {
drivers.emplace_back(xe::hid::xinput::Create(window)); drivers.emplace_back(xe::hid::xinput::Create(window));
#endif // XE_PLATFORM_WIN32 #endif // XE_PLATFORM_WIN32
} else { } else {
@ -154,16 +161,17 @@ int xenia_main(const std::vector<std::wstring>& args) {
Profiler::ThreadEnter("main"); Profiler::ThreadEnter("main");
// Figure out where content should go. // Figure out where content should go.
std::wstring content_root; std::wstring content_root = xe::to_wstring(cvars::content_root);
if (!FLAGS_content_root.empty()) { std::wstring config_folder;
content_root = xe::to_wstring(FLAGS_content_root);
} else { if (content_root.empty()) {
auto base_path = xe::filesystem::GetExecutableFolder(); auto base_path = xe::filesystem::GetExecutableFolder();
base_path = xe::to_absolute_path(base_path); base_path = xe::to_absolute_path(base_path);
auto portable_path = xe::join_paths(base_path, L"portable.txt"); auto portable_path = xe::join_paths(base_path, L"portable.txt");
if (xe::filesystem::PathExists(portable_path)) { if (xe::filesystem::PathExists(portable_path)) {
content_root = xe::join_paths(base_path, L"content"); content_root = xe::join_paths(base_path, L"content");
config_folder = base_path;
} else { } else {
content_root = xe::filesystem::GetUserFolder(); content_root = xe::filesystem::GetUserFolder();
#if defined(XE_PLATFORM_WIN32) #if defined(XE_PLATFORM_WIN32)
@ -174,11 +182,14 @@ int xenia_main(const std::vector<std::wstring>& args) {
#warning Unhandled platform for content root. #warning Unhandled platform for content root.
content_root = xe::join_paths(content_root, L"Xenia"); content_root = xe::join_paths(content_root, L"Xenia");
#endif #endif
config_folder = content_root;
content_root = xe::join_paths(content_root, L"content"); content_root = xe::join_paths(content_root, L"content");
} }
} }
content_root = xe::to_absolute_path(content_root); content_root = xe::to_absolute_path(content_root);
XELOGI("Content root: %S", content_root.c_str()); XELOGI("Content root: %S", content_root.c_str());
config::SetupConfig(config_folder);
// Create the emulator but don't initialize so we can setup the window. // Create the emulator but don't initialize so we can setup the window.
auto emulator = std::make_unique<Emulator>(L"", content_root); auto emulator = std::make_unique<Emulator>(L"", content_root);
@ -196,7 +207,7 @@ int xenia_main(const std::vector<std::wstring>& args) {
return 1; return 1;
} }
if (FLAGS_mount_scratch) { if (cvars::mount_scratch) {
auto scratch_device = std::make_unique<xe::vfs::HostPathDevice>( auto scratch_device = std::make_unique<xe::vfs::HostPathDevice>(
"\\SCRATCH", L"scratch", false); "\\SCRATCH", L"scratch", false);
if (!scratch_device->Initialize()) { if (!scratch_device->Initialize()) {
@ -210,7 +221,7 @@ int xenia_main(const std::vector<std::wstring>& args) {
} }
} }
if (FLAGS_mount_cache) { if (cvars::mount_cache) {
auto cache0_device = auto cache0_device =
std::make_unique<xe::vfs::HostPathDevice>("\\CACHE0", L"cache0", false); std::make_unique<xe::vfs::HostPathDevice>("\\CACHE0", L"cache0", false);
if (!cache0_device->Initialize()) { if (!cache0_device->Initialize()) {
@ -239,7 +250,7 @@ int xenia_main(const std::vector<std::wstring>& args) {
// Set a debug handler. // Set a debug handler.
// This will respond to debugging requests so we can open the debug UI. // This will respond to debugging requests so we can open the debug UI.
std::unique_ptr<xe::debug::ui::DebugWindow> debug_window; std::unique_ptr<xe::debug::ui::DebugWindow> debug_window;
if (FLAGS_debug) { if (cvars::debug) {
emulator->processor()->set_debug_listener_request_handler( emulator->processor()->set_debug_listener_request_handler(
[&](xe::cpu::Processor* processor) { [&](xe::cpu::Processor* processor) {
if (debug_window) { if (debug_window) {
@ -285,20 +296,12 @@ int xenia_main(const std::vector<std::wstring>& args) {
// Grab path from the flag or unnamed argument. // Grab path from the flag or unnamed argument.
std::wstring path; std::wstring path;
if (!FLAGS_target.empty() || args.size() >= 2) { if (!cvars::target.empty()) {
if (!FLAGS_target.empty()) { path = xe::to_wstring(cvars::target);
// Passed as a named argument.
// TODO(benvanik): find something better than gflags that supports
// unicode.
path = xe::to_wstring(FLAGS_target);
} else {
// Passed as an unnamed argument.
path = args[1];
}
} }
// Toggles fullscreen // Toggles fullscreen
if (FLAGS_fullscreen) emulator_window->ToggleFullscreen(); if (cvars::fullscreen) emulator_window->ToggleFullscreen();
if (!path.empty()) { if (!path.empty()) {
// Normalize the path and make absolute. // Normalize the path and make absolute.

View File

@ -9,4 +9,4 @@
#include "xenia/apu/apu_flags.h" #include "xenia/apu/apu_flags.h"
DEFINE_bool(mute, false, "Mutes all audio output."); DEFINE_bool(mute, false, "Mutes all audio output.", "Audio")

View File

@ -10,8 +10,7 @@
#ifndef XENIA_APU_APU_FLAGS_H_ #ifndef XENIA_APU_APU_FLAGS_H_
#define XENIA_APU_APU_FLAGS_H_ #define XENIA_APU_APU_FLAGS_H_
#include <gflags/gflags.h> #include "xenia/base/cvar.h"
DECLARE_bool(mute)
DECLARE_bool(mute);
#endif // XENIA_APU_APU_FLAGS_H_ #endif // XENIA_APU_APU_FLAGS_H_

View File

@ -10,6 +10,4 @@
#ifndef XENIA_APU_NOP_NOP_APU_FLAGS_H_ #ifndef XENIA_APU_NOP_NOP_APU_FLAGS_H_
#define XENIA_APU_NOP_NOP_APU_FLAGS_H_ #define XENIA_APU_NOP_NOP_APU_FLAGS_H_
#include <gflags/gflags.h>
#endif // XENIA_APU_NOP_NOP_APU_FLAGS_H_ #endif // XENIA_APU_NOP_NOP_APU_FLAGS_H_

View File

@ -12,7 +12,4 @@ project("xenia-apu-nop")
}) })
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
local_platform_files() local_platform_files()

View File

@ -14,7 +14,6 @@ project("xenia-apu")
defines({ defines({
}) })
includedirs({ includedirs({
project_root.."/third_party/gflags/src",
project_root.."/third_party/libav/", project_root.."/third_party/libav/",
}) })
local_platform_files() local_platform_files()

View File

@ -12,7 +12,4 @@ project("xenia-apu-xaudio2")
}) })
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
local_platform_files() local_platform_files()

View File

@ -10,6 +10,4 @@
#ifndef XENIA_APU_XAUDIO2_XAUDIO2_APU_FLAGS_H_ #ifndef XENIA_APU_XAUDIO2_XAUDIO2_APU_FLAGS_H_
#define XENIA_APU_XAUDIO2_XAUDIO2_APU_FLAGS_H_ #define XENIA_APU_XAUDIO2_XAUDIO2_APU_FLAGS_H_
#include <gflags/gflags.h>
#endif // XENIA_APU_XAUDIO2_XAUDIO2_APU_FLAGS_H_ #endif // XENIA_APU_XAUDIO2_XAUDIO2_APU_FLAGS_H_

View File

@ -151,7 +151,7 @@ bool XAudio2AudioDriver::Initialize() {
return false; return false;
} }
if (FLAGS_mute) { if (cvars::mute) {
pcm_voice_->SetVolume(0.0f); pcm_voice_->SetVolume(0.0f);
} }

View File

@ -9,9 +9,8 @@
#include "xenia/apu/xma_decoder.h" #include "xenia/apu/xma_decoder.h"
#include <gflags/gflags.h>
#include "xenia/apu/xma_context.h" #include "xenia/apu/xma_context.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/base/profiling.h" #include "xenia/base/profiling.h"
@ -49,7 +48,8 @@ extern "C" {
// do this, it's likely they are either passing the context to XAudio or // do this, it's likely they are either passing the context to XAudio or
// using the XMA* functions. // using the XMA* functions.
DEFINE_bool(libav_verbose, false, "Verbose libav output (debug and above)"); DEFINE_bool(libav_verbose, false, "Verbose libav output (debug and above)",
"Audio");
namespace xe { namespace xe {
namespace apu { namespace apu {
@ -60,7 +60,7 @@ XmaDecoder::XmaDecoder(cpu::Processor* processor)
XmaDecoder::~XmaDecoder() = default; XmaDecoder::~XmaDecoder() = default;
void av_log_callback(void* avcl, int level, const char* fmt, va_list va) { void av_log_callback(void* avcl, int level, const char* fmt, va_list va) {
if (!FLAGS_libav_verbose && level > AV_LOG_WARNING) { if (!cvars::libav_verbose && level > AV_LOG_WARNING) {
return; return;
} }

56
src/xenia/base/cvar.cc Normal file
View File

@ -0,0 +1,56 @@
#include "cvar.h"
namespace cvar {
cxxopts::Options options("xenia", "Xbox 360 Emulator");
std::map<std::string, ICommandVar*>* CmdVars;
std::map<std::string, IConfigVar*>* ConfigVars;
void PrintHelpAndExit() {
std::cout << options.help({""}) << std::endl;
std::cout << "For the full list of command line arguments, see xenia.cfg."
<< std::endl;
exit(0);
}
void ParseLaunchArguments(int argc, char** argv) {
options.add_options()("help", "Prints help and exit.");
if (!CmdVars) CmdVars = new std::map<std::string, ICommandVar*>();
if (!ConfigVars) ConfigVars = new std::map<std::string, IConfigVar*>();
for (auto& it : *CmdVars) {
auto cmdVar = it.second;
cmdVar->AddToLaunchOptions(&options);
}
std::vector<IConfigVar*> vars;
for (const auto& s : *ConfigVars) vars.push_back(s.second);
for (auto& it : *ConfigVars) {
auto configVar = it.second;
configVar->AddToLaunchOptions(&options);
}
try {
options.positional_help("[Path to .iso/.xex]");
options.parse_positional({"target"});
auto result = options.parse(argc, argv);
if (result.count("help")) {
PrintHelpAndExit();
}
for (auto& it : *CmdVars) {
auto cmdVar = static_cast<ICommandVar*>(it.second);
if (result.count(cmdVar->GetName())) {
cmdVar->LoadFromLaunchOptions(&result);
}
}
for (auto& it : *ConfigVars) {
auto configVar = static_cast<IConfigVar*>(it.second);
if (result.count(configVar->GetName())) {
configVar->LoadFromLaunchOptions(&result);
}
}
} catch (const cxxopts::OptionException& e) {
std::cout << e.what() << std::endl;
PrintHelpAndExit();
}
}
} // namespace cvar

258
src/xenia/base/cvar.h Normal file
View File

@ -0,0 +1,258 @@
#ifndef XENIA_CVAR_H_
#define XENIA_CVAR_H_
#include <map>
#include <string>
#include "cpptoml/include/cpptoml.h"
#include "cxxopts/include/cxxopts.hpp"
#include "xenia/base/string_util.h"
namespace cvar {
class ICommandVar {
public:
virtual ~ICommandVar() = default;
virtual std::string GetName() = 0;
virtual std::string GetDescription() = 0;
virtual void UpdateValue() = 0;
virtual void AddToLaunchOptions(cxxopts::Options* options) = 0;
virtual void LoadFromLaunchOptions(cxxopts::ParseResult* result) = 0;
};
class IConfigVar : virtual public ICommandVar {
public:
virtual std::string GetCategory() = 0;
virtual std::string GetConfigValue() = 0;
virtual void LoadConfigValue(std::shared_ptr<cpptoml::base> result) = 0;
virtual void LoadGameConfigValue(std::shared_ptr<cpptoml::base> result) = 0;
};
template <class T>
class CommandVar : virtual public ICommandVar {
public:
CommandVar<T>(const char* name, T* defaultValue, const char* description);
std::string GetName() override;
std::string GetDescription() override;
void AddToLaunchOptions(cxxopts::Options* options) override;
void LoadFromLaunchOptions(cxxopts::ParseResult* result) override;
T* GetCurrentValue() { return currentValue_; }
protected:
std::string name_;
T defaultValue_;
T* currentValue_;
std::unique_ptr<T> commandLineValue_;
std::string description_;
T Convert(std::string val);
static std::string ToString(T val);
void SetValue(T val);
void SetCommandLineValue(T val);
void UpdateValue() override;
};
#pragma warning(push)
#pragma warning(disable : 4250)
template <class T>
class ConfigVar : public CommandVar<T>, virtual public IConfigVar {
public:
ConfigVar<T>(const char* name, T* defaultValue, const char* description,
const char* category);
std::string GetConfigValue() override;
std::string GetCategory() override;
void AddToLaunchOptions(cxxopts::Options* options) override;
void LoadConfigValue(std::shared_ptr<cpptoml::base> result) override;
void LoadGameConfigValue(std::shared_ptr<cpptoml::base> result) override;
void SetConfigValue(T val);
void SetGameConfigValue(T val);
private:
std::string category_;
std::unique_ptr<T> configValue_ = nullptr;
std::unique_ptr<T> gameConfigValue_ = nullptr;
void UpdateValue() override;
};
#pragma warning(pop)
template <class T>
std::string CommandVar<T>::GetName() {
return name_;
}
template <class T>
std::string CommandVar<T>::GetDescription() {
return description_;
}
template <class T>
void CommandVar<T>::AddToLaunchOptions(cxxopts::Options* options) {
options->add_options()(this->name_, this->description_, cxxopts::value<T>());
}
template <class T>
void ConfigVar<T>::AddToLaunchOptions(cxxopts::Options* options) {
options->add_options(category_)(this->name_, this->description_,
cxxopts::value<T>());
}
template <class T>
void CommandVar<T>::LoadFromLaunchOptions(cxxopts::ParseResult* result) {
T value = (*result)[this->name_].template as<T>();
SetCommandLineValue(value);
}
template <class T>
void ConfigVar<T>::LoadConfigValue(std::shared_ptr<cpptoml::base> result) {
SetConfigValue(*cpptoml::get_impl<T>(result));
}
template <class T>
void ConfigVar<T>::LoadGameConfigValue(std::shared_ptr<cpptoml::base> result) {
SetGameConfigValue(*cpptoml::get_impl<T>(result));
}
template <class T>
CommandVar<T>::CommandVar(const char* name, T* defaultValue,
const char* description)
: name_(name),
defaultValue_(*defaultValue),
description_(description),
currentValue_(defaultValue) {}
template <class T>
ConfigVar<T>::ConfigVar(const char* name, T* defaultValue,
const char* description, const char* category)
: CommandVar<T>(name, defaultValue, description), category_(category) {}
template <class T>
void CommandVar<T>::UpdateValue() {
if (this->commandLineValue_) return this->SetValue(*this->commandLineValue_);
return this->SetValue(defaultValue_);
}
template <class T>
void ConfigVar<T>::UpdateValue() {
if (this->commandLineValue_) return this->SetValue(*this->commandLineValue_);
if (this->gameConfigValue_) return this->SetValue(*this->gameConfigValue_);
if (this->configValue_) return this->SetValue(*this->configValue_);
return this->SetValue(this->defaultValue_);
}
template <class T>
T CommandVar<T>::Convert(std::string val) {
return xe::string_util::from_string<T>(val);
}
template <>
inline std::string CommandVar<std::string>::Convert(std::string val) {
return val;
}
template <>
inline std::string CommandVar<bool>::ToString(bool val) {
return val ? "true" : "false";
}
template <>
inline std::string CommandVar<std::string>::ToString(std::string val) {
return "\"" + val + "\"";
}
template <class T>
std::string CommandVar<T>::ToString(T val) {
return std::to_string(val);
}
template <class T>
void CommandVar<T>::SetValue(T val) {
*currentValue_ = val;
}
template <class T>
std::string ConfigVar<T>::GetCategory() {
return category_;
}
template <class T>
std::string ConfigVar<T>::GetConfigValue() {
if (this->configValue_) return this->ToString(*this->configValue_);
return this->ToString(this->defaultValue_);
}
template <class T>
void CommandVar<T>::SetCommandLineValue(const T val) {
this->commandLineValue_ = std::make_unique<T>(val);
this->UpdateValue();
}
template <class T>
void ConfigVar<T>::SetConfigValue(T val) {
this->configValue_ = std::make_unique<T>(val);
this->UpdateValue();
}
template <class T>
void ConfigVar<T>::SetGameConfigValue(T val) {
this->gameConfigValue_ = std::make_unique<T>(val);
this->UpdateValue();
}
extern std::map<std::string, ICommandVar*>* CmdVars;
extern std::map<std::string, IConfigVar*>* ConfigVars;
inline void AddConfigVar(IConfigVar* cv) {
if (!ConfigVars) ConfigVars = new std::map<std::string, IConfigVar*>();
ConfigVars->insert(std::pair<std::string, IConfigVar*>(cv->GetName(), cv));
}
inline void AddCommandVar(ICommandVar* cv) {
if (!CmdVars) CmdVars = new std::map<std::string, ICommandVar*>();
CmdVars->insert(std::pair<std::string, ICommandVar*>(cv->GetName(), cv));
}
void ParseLaunchArguments(int argc, char** argv);
template <typename T>
T* define_configvar(const char* name, T* defaultValue, const char* description,
const char* category) {
IConfigVar* cfgVar =
new ConfigVar<T>(name, defaultValue, description, category);
AddConfigVar(cfgVar);
return defaultValue;
}
template <typename T>
T* define_cmdvar(const char* name, T* defaultValue, const char* description) {
ICommandVar* cmdVar = new CommandVar<T>(name, defaultValue, description);
AddCommandVar(cmdVar);
return defaultValue;
}
#define DEFINE_double(name, defaultValue, description, category) \
DEFINE_CVar(name, defaultValue, description, category, double)
#define DEFINE_int32(name, defaultValue, description, category) \
DEFINE_CVar(name, defaultValue, description, category, int32_t)
#define DEFINE_uint64(name, defaultValue, description, category) \
DEFINE_CVar(name, defaultValue, description, category, uint64_t)
#define DEFINE_string(name, defaultValue, description, category) \
DEFINE_CVar(name, defaultValue, description, category, std::string)
#define DEFINE_bool(name, defaultValue, description, category) \
DEFINE_CVar(name, defaultValue, description, category, bool)
#define DEFINE_CVar(name, defaultValue, description, category, type) \
namespace cvars { \
type name = defaultValue; \
} \
namespace cv { \
static auto cv_##name = \
cvar::define_configvar(#name, &cvars::name, description, category); \
}
// CmdVars can only be strings for now, we don't need any others
#define CmdVar(name, defaultValue, description) \
namespace cvars { \
std::string name = defaultValue; \
} \
namespace cv { \
static auto cv_##name = \
cvar::define_cmdvar(#name, &cvars::name, description); \
}
#define DECLARE_double(name) DECLARE_CVar(name, double)
#define DECLARE_bool(name) DECLARE_CVar(name, bool)
#define DECLARE_string(name) DECLARE_CVar(name, std::string)
#define DECLARE_int32(name) DECLARE_CVar(name, int32_t)
#define DECLARE_uint64(name) DECLARE_CVar(name, uint64_t)
#define DECLARE_CVar(name, type) \
namespace cvars { \
extern type name; \
}
} // namespace cvar
#endif // XENIA_CVAR_H_

View File

@ -9,8 +9,6 @@
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include <gflags/gflags.h>
#include <atomic> #include <atomic>
#include <cinttypes> #include <cinttypes>
#include <cstdarg> #include <cstdarg>
@ -19,6 +17,7 @@
#include <vector> #include <vector>
#include "xenia/base/atomic.h" #include "xenia/base/atomic.h"
#include "xenia/base/cvar.h"
#include "xenia/base/debugging.h" #include "xenia/base/debugging.h"
#include "xenia/base/filesystem.h" #include "xenia/base/filesystem.h"
#include "xenia/base/main.h" #include "xenia/base/main.h"
@ -26,6 +25,7 @@
#include "xenia/base/memory.h" #include "xenia/base/memory.h"
#include "xenia/base/ring_buffer.h" #include "xenia/base/ring_buffer.h"
#include "xenia/base/threading.h" #include "xenia/base/threading.h"
//#include "xenia/base/cvar.h"
// For MessageBox: // For MessageBox:
// TODO(benvanik): generic API? logging_win.cc? // TODO(benvanik): generic API? logging_win.cc?
@ -35,12 +35,15 @@
DEFINE_string( DEFINE_string(
log_file, "", log_file, "",
"Logs are written to the given file (specify stdout for command line)"); "Logs are written to the given file (specify stdout for command line)",
DEFINE_bool(log_debugprint, false, "Dump the log to DebugPrint."); "Logging");
DEFINE_bool(flush_log, true, "Flush log file after each log line batch."); DEFINE_bool(log_debugprint, false, "Dump the log to DebugPrint.", "Logging");
DEFINE_bool(flush_log, true, "Flush log file after each log line batch.",
"Logging");
DEFINE_int32( DEFINE_int32(
log_level, 2, log_level, 2,
"Maximum level to be logged. (0=error, 1=warning, 2=info, 3=debug)"); "Maximum level to be logged. (0=error, 1=warning, 2=info, 3=debug)",
"Logging");
namespace xe { namespace xe {
@ -52,16 +55,16 @@ thread_local std::vector<char> log_format_buffer_(64 * 1024);
class Logger { class Logger {
public: public:
explicit Logger(const std::wstring& app_name) : running_(true) { explicit Logger(const std::wstring& app_name) : running_(true) {
if (FLAGS_log_file.empty()) { if (cvars::log_file.empty()) {
// Default to app name. // Default to app name.
auto file_path = app_name + L".log"; auto file_path = app_name + L".log";
xe::filesystem::CreateParentFolder(file_path); xe::filesystem::CreateParentFolder(file_path);
file_ = xe::filesystem::OpenFile(file_path, "wt"); file_ = xe::filesystem::OpenFile(file_path, "wt");
} else { } else {
if (FLAGS_log_file == "stdout") { if (cvars::log_file == "stdout") {
file_ = stdout; file_ = stdout;
} else { } else {
auto file_path = xe::to_wstring(FLAGS_log_file.c_str()); auto file_path = xe::to_wstring(cvars::log_file);
xe::filesystem::CreateParentFolder(file_path); xe::filesystem::CreateParentFolder(file_path);
file_ = xe::filesystem::OpenFile(file_path, "wt"); file_ = xe::filesystem::OpenFile(file_path, "wt");
} }
@ -81,7 +84,7 @@ class Logger {
void AppendLine(uint32_t thread_id, LogLevel level, const char prefix_char, void AppendLine(uint32_t thread_id, LogLevel level, const char prefix_char,
const char* buffer, size_t buffer_length) { const char* buffer, size_t buffer_length) {
if (static_cast<int32_t>(level) > FLAGS_log_level) { if (static_cast<int32_t>(level) > cvars::log_level) {
// Discard this line. // Discard this line.
return; return;
} }
@ -148,7 +151,7 @@ class Logger {
fwrite(buf, 1, size, file_); fwrite(buf, 1, size, file_);
} }
if (FLAGS_log_debugprint) { if (cvars::log_debugprint) {
debugging::DebugPrint("%.*s", size, buf); debugging::DebugPrint("%.*s", size, buf);
} }
} }
@ -214,7 +217,7 @@ class Logger {
read_head_ = rb.read_offset(); read_head_ = rb.read_offset();
} }
if (did_write) { if (did_write) {
if (FLAGS_flush_log) { if (cvars::flush_log) {
fflush(file_); fflush(file_);
} }

View File

@ -7,10 +7,9 @@
****************************************************************************** ******************************************************************************
*/ */
#include "xenia/base/cvar.h"
#include "xenia/base/main.h" #include "xenia/base/main.h"
#include <gflags/gflags.h>
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/string.h" #include "xenia/base/string.h"
@ -23,10 +22,7 @@ bool has_console_attached() { return true; }
extern "C" int main(int argc, char** argv) { extern "C" int main(int argc, char** argv) {
auto entry_info = xe::GetEntryInfo(); auto entry_info = xe::GetEntryInfo();
google::SetUsageMessage(std::string("usage: ") + cvar::ParseLaunchArguments(argc, argv);
xe::to_string(entry_info.usage));
google::SetVersionString("1.0");
google::ParseCommandLineFlags(&argc, &argv, true);
std::vector<std::wstring> args; std::vector<std::wstring> args;
for (int n = 0; n < argc; n++) { for (int n = 0; n < argc; n++) {
@ -39,6 +35,5 @@ extern "C" int main(int argc, char** argv) {
// Call app-provided entry point. // Call app-provided entry point.
int result = entry_info.entry_point(args); int result = entry_info.entry_point(args);
google::ShutDownCommandLineFlags();
return result; return result;
} }

View File

@ -10,7 +10,6 @@
#include "xenia/base/main.h" #include "xenia/base/main.h"
#include <fcntl.h> #include <fcntl.h>
#include <gflags/gflags.h>
#include <io.h> #include <io.h>
#include <cstdlib> #include <cstdlib>
@ -18,6 +17,7 @@
// Autogenerated by `xb premake`. // Autogenerated by `xb premake`.
#include "build/version.h" #include "build/version.h"
#include "xenia/base/filesystem.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/platform_win.h" #include "xenia/base/platform_win.h"
#include "xenia/base/string.h" #include "xenia/base/string.h"
@ -25,9 +25,10 @@
#include "third_party/xbyak/xbyak/xbyak_util.h" #include "third_party/xbyak/xbyak/xbyak_util.h"
#include <bcrypt.h> #include <bcrypt.h>
#include "xenia/base/cvar.h"
DEFINE_bool(win32_high_freq, true, DEFINE_bool(win32_high_freq, true,
"Requests high performance from the NT kernel"); "Requests high performance from the NT kernel", "Kernel");
namespace xe { namespace xe {
@ -88,7 +89,6 @@ int Main() {
auto entry_info = xe::GetEntryInfo(); auto entry_info = xe::GetEntryInfo();
// Convert command line to an argv-like format so we can share code/use // Convert command line to an argv-like format so we can share code/use
// gflags.
auto command_line = GetCommandLineW(); auto command_line = GetCommandLineW();
int argc; int argc;
wchar_t** argv = CommandLineToArgvW(command_line, &argc); wchar_t** argv = CommandLineToArgvW(command_line, &argc);
@ -96,11 +96,7 @@ int Main() {
return 1; return 1;
} }
google::SetUsageMessage(std::string("usage: ") + // Convert all args to narrow, as cxxopts doesn't support wchar.
xe::to_string(entry_info.usage));
google::SetVersionString("1.0");
// Convert all args to narrow, as gflags doesn't support wchar.
int argca = argc; int argca = argc;
char** argva = reinterpret_cast<char**>(alloca(sizeof(char*) * argca)); char** argva = reinterpret_cast<char**>(alloca(sizeof(char*) * argca));
for (int n = 0; n < argca; n++) { for (int n = 0; n < argca; n++) {
@ -109,8 +105,7 @@ int Main() {
std::wcstombs(argva[n], argv[n], len + 1); std::wcstombs(argva[n], argv[n], len + 1);
} }
// Parse flags; this may delete some of them. cvar::ParseLaunchArguments(argca, argva);
google::ParseCommandLineFlags(&argc, &argva, true);
// Widen all remaining flags and convert to usable strings. // Widen all remaining flags and convert to usable strings.
std::vector<std::wstring> args; std::vector<std::wstring> args;
@ -143,7 +138,7 @@ int Main() {
XE_BUILD_DATE); XE_BUILD_DATE);
// Request high performance timing. // Request high performance timing.
if (FLAGS_win32_high_freq) { if (cvars::win32_high_freq) {
RequestHighPerformance(); RequestHighPerformance();
} }
@ -151,7 +146,6 @@ int Main() {
int result = entry_info.entry_point(args); int result = entry_info.entry_point(args);
xe::ShutdownLogging(); xe::ShutdownLogging();
google::ShutDownCommandLineFlags();
LocalFree(argv); LocalFree(argv);
return result; return result;
} }

View File

@ -7,9 +7,6 @@ project("xenia-base")
language("C++") language("C++")
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
local_platform_files() local_platform_files()
removefiles({"main_*.cc"}) removefiles({"main_*.cc"})
files({ files({

View File

@ -7,8 +7,6 @@
****************************************************************************** ******************************************************************************
*/ */
#include <gflags/gflags.h>
#include <string> #include <string>
// NOTE: this must be included before microprofile as macro expansion needs // NOTE: this must be included before microprofile as macro expansion needs
@ -30,6 +28,7 @@
#include "third_party/microprofile/microprofile.h" #include "third_party/microprofile/microprofile.h"
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/profiling.h" #include "xenia/base/profiling.h"
#include "xenia/ui/window.h" #include "xenia/ui/window.h"
@ -42,7 +41,7 @@
#include "xenia/ui/microprofile_drawer.h" #include "xenia/ui/microprofile_drawer.h"
#endif // XE_OPTION_PROFILING_UI #endif // XE_OPTION_PROFILING_UI
DEFINE_bool(show_profiler, false, "Show profiling UI by default."); DEFINE_bool(show_profiler, false, "Show profiling UI by default.", "Other");
namespace xe { namespace xe {
@ -77,7 +76,7 @@ void Profiler::Initialize() {
g_MicroProfileUI.bShowSpikes = true; g_MicroProfileUI.bShowSpikes = true;
g_MicroProfileUI.nOpacityBackground = 0x40u << 24; g_MicroProfileUI.nOpacityBackground = 0x40u << 24;
g_MicroProfileUI.nOpacityForeground = 0xc0u << 24; g_MicroProfileUI.nOpacityForeground = 0xc0u << 24;
if (FLAGS_show_profiler) { if (cvars::show_profiler) {
MicroProfileSetDisplayMode(1); MicroProfileSetDisplayMode(1);
} }
#else #else

View File

@ -24,13 +24,13 @@ namespace string_util {
inline std::string to_hex_string(uint32_t value) { inline std::string to_hex_string(uint32_t value) {
char buffer[21]; char buffer[21];
std::snprintf(buffer, sizeof(buffer), "%08" PRIX32, value); snprintf(buffer, sizeof(buffer), "%08" PRIX32, value);
return std::string(buffer); return std::string(buffer);
} }
inline std::string to_hex_string(uint64_t value) { inline std::string to_hex_string(uint64_t value) {
char buffer[21]; char buffer[21];
std::snprintf(buffer, sizeof(buffer), "%016" PRIX64, value); snprintf(buffer, sizeof(buffer), "%016" PRIX64, value);
return std::string(buffer); return std::string(buffer);
} }
@ -54,8 +54,8 @@ inline std::string to_hex_string(double value) {
inline std::string to_hex_string(const vec128_t& value) { inline std::string to_hex_string(const vec128_t& value) {
char buffer[128]; char buffer[128];
std::snprintf(buffer, sizeof(buffer), "[%.8X, %.8X, %.8X, %.8X]", snprintf(buffer, sizeof(buffer), "[%.8X, %.8X, %.8X, %.8X]", value.u32[0],
value.u32[0], value.u32[1], value.u32[2], value.u32[3]); value.u32[1], value.u32[2], value.u32[3]);
return std::string(buffer); return std::string(buffer);
} }
@ -66,7 +66,7 @@ inline std::string to_hex_string(const __m128& value) {
char buffer[128]; char buffer[128];
float f[4]; float f[4];
_mm_storeu_ps(f, value); _mm_storeu_ps(f, value);
std::snprintf( snprintf(
buffer, sizeof(buffer), "[%.8X, %.8X, %.8X, %.8X]", buffer, sizeof(buffer), "[%.8X, %.8X, %.8X, %.8X]",
*reinterpret_cast<uint32_t*>(&f[0]), *reinterpret_cast<uint32_t*>(&f[1]), *reinterpret_cast<uint32_t*>(&f[0]), *reinterpret_cast<uint32_t*>(&f[1]),
*reinterpret_cast<uint32_t*>(&f[2]), *reinterpret_cast<uint32_t*>(&f[3])); *reinterpret_cast<uint32_t*>(&f[2]), *reinterpret_cast<uint32_t*>(&f[3]));
@ -77,15 +77,22 @@ inline std::string to_string(const __m128& value) {
char buffer[128]; char buffer[128];
float f[4]; float f[4];
_mm_storeu_ps(f, value); _mm_storeu_ps(f, value);
std::snprintf(buffer, sizeof(buffer), "(%F, %F, %F, %F)", f[0], f[1], f[2], snprintf(buffer, sizeof(buffer), "(%F, %F, %F, %F)", f[0], f[1], f[2], f[3]);
f[3]);
return std::string(buffer); return std::string(buffer);
} }
#endif #endif
template <typename T> template <typename T>
inline T from_string(const char* value, bool force_hex = false); inline T from_string(const char* value, bool force_hex = false) {
// Missing implementation for converting type T to string
throw;
}
template <>
inline bool from_string<bool>(const char* value, bool force_hex) {
return std::strcmp(value, "true") == 0 || value[0] == '1';
}
template <> template <>
inline int32_t from_string<int32_t>(const char* value, bool force_hex) { inline int32_t from_string<int32_t>(const char* value, bool force_hex) {

View File

@ -2,9 +2,6 @@ project_root = "../../../.."
include(project_root.."/tools/build") include(project_root.."/tools/build")
test_suite("xenia-base-tests", project_root, ".", { test_suite("xenia-base-tests", project_root, ".", {
includedirs = {
project_root.."/third_party/gflags/src",
},
links = { links = {
"xenia-base", "xenia-base",
}, },

View File

@ -266,8 +266,8 @@ static inline vec128_t vec128b(uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3,
inline std::string to_string(const vec128_t& value) { inline std::string to_string(const vec128_t& value) {
char buffer[128]; char buffer[128];
std::snprintf(buffer, sizeof(buffer), "(%g, %g, %g, %g)", value.x, value.y, snprintf(buffer, sizeof(buffer), "(%g, %g, %g, %g)", value.x, value.y,
value.z, value.w); value.z, value.w);
return std::string(buffer); return std::string(buffer);
} }

126
src/xenia/config.cc Normal file
View File

@ -0,0 +1,126 @@
#include "config.h"
#include "cpptoml/include/cpptoml.h"
#include "xenia/base/cvar.h"
#include "xenia/base/filesystem.h"
#include "xenia/base/logging.h"
#include "xenia/base/string.h"
CmdVar(config, "", "Specifies the target config to load.");
namespace config {
std::wstring config_name = L"xenia.config.toml";
std::wstring config_folder;
std::wstring config_path;
bool sortCvar(cvar::IConfigVar* a, cvar::IConfigVar* b) {
if (a->GetCategory() < b->GetCategory()) return true;
if (a->GetCategory() > b->GetCategory()) return false;
if (a->GetName() < b->GetName()) return true;
return false;
}
std::shared_ptr<cpptoml::table> ParseConfig(std::string config_path) {
try {
return cpptoml::parse_file(config_path);
} catch (cpptoml::parse_exception) {
xe::FatalError("Failed to parse config file: %s", config_path.c_str());
return nullptr;
}
}
void ReadConfig(const std::wstring& file_path) {
const auto config = ParseConfig(xe::to_string(file_path));
for (auto& it : *cvar::ConfigVars) {
auto configVar = static_cast<cvar::IConfigVar*>(it.second);
auto configKey = configVar->GetCategory() + "." + configVar->GetName();
if (config->contains_qualified(configKey)) {
configVar->LoadConfigValue(config->get_qualified(configKey));
}
}
XELOGI("Loaded config: %S", file_path.c_str());
}
void ReadGameConfig(std::wstring file_path) {
const auto config = ParseConfig(xe::to_string(file_path));
for (auto& it : *cvar::ConfigVars) {
auto configVar = static_cast<cvar::IConfigVar*>(it.second);
auto configKey = configVar->GetCategory() + "." + configVar->GetName();
if (config->contains_qualified(configKey)) {
configVar->LoadGameConfigValue(config->get_qualified(configKey));
}
}
XELOGI("Loaded game config: %S", file_path.c_str());
}
void SaveConfig() {
std::vector<cvar::IConfigVar*> vars;
for (const auto& s : *cvar::ConfigVars) vars.push_back(s.second);
std::sort(vars.begin(), vars.end(), sortCvar);
// we use our own write logic because cpptoml doesn't
// allow us to specify comments :(
std::ostringstream output;
std::string lastCategory;
for (auto configVar : vars) {
if (lastCategory != configVar->GetCategory()) {
if (!lastCategory.empty()) {
output << std::endl;
}
lastCategory = configVar->GetCategory();
output << xe::format_string("[%s]\n", lastCategory.c_str());
}
output << std::left << std::setw(40) << std::setfill(' ')
<< xe::format_string("%s = %s", configVar->GetName().c_str(),
configVar->GetConfigValue().c_str());
output << xe::format_string("\t# %s\n",
configVar->GetDescription().c_str());
}
if (xe::filesystem::PathExists(config_path)) {
std::ifstream existingConfigStream(xe::to_string(config_path).c_str());
const std::string existingConfig(
(std::istreambuf_iterator<char>(existingConfigStream)),
std::istreambuf_iterator<char>());
// if the config didn't change, no need to modify the file
if (existingConfig == output.str()) return;
}
// save the config file
xe::filesystem::CreateParentFolder(config_path);
std::ofstream file;
file.open(xe::to_string(config_path), std::ios::out | std::ios::trunc);
file << output.str();
file.close();
}
void SetupConfig(const std::wstring& config_folder) {
config::config_folder = config_folder;
// check if the user specified a specific config to load
if (!cvars::config.empty()) {
config_path = xe::to_wstring(cvars::config);
if (xe::filesystem::PathExists(config_path)) {
ReadConfig(config_path);
return;
}
}
// if the user specified a --config argument, but the file doesn't exist,
// let's also load the default config
if (!config_folder.empty()) {
config_path = xe::join_paths(config_folder, config_name);
if (xe::filesystem::PathExists(config_path)) {
ReadConfig(config_path);
}
// we only want to save the config if the user is using the default
// config, we don't want to override a user created specific config
SaveConfig();
}
}
void LoadGameConfig(const std::wstring& title_id) {
const auto content_folder = xe::join_paths(config_folder, L"content");
const auto game_folder = xe::join_paths(content_folder, title_id);
const auto game_config_path = xe::join_paths(game_folder, config_name);
if (xe::filesystem::PathExists(game_config_path)) {
ReadGameConfig(game_config_path);
}
}
} // namespace config

10
src/xenia/config.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef XENIA_CONFIG_H_
#define XENIA_CONFIG_H_
#include <string>
namespace config {
void SetupConfig(const std::wstring& config_folder);
void LoadGameConfig(const std::wstring& title_id);
} // namespace config
#endif // XENIA_CONFIG_H_

View File

@ -27,6 +27,5 @@ project("xenia-cpu-backend-x64")
includedirs({ includedirs({
project_root.."/third_party/capstone/include", project_root.."/third_party/capstone/include",
project_root.."/third_party/gflags/src",
}) })
local_platform_files() local_platform_files()

View File

@ -28,7 +28,8 @@
DEFINE_bool( DEFINE_bool(
enable_haswell_instructions, true, enable_haswell_instructions, true,
"Uses the AVX2/FMA/etc instructions on Haswell processors, if available."); "Uses the AVX2/FMA/etc instructions on Haswell processors, if available.",
"CPU");
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -83,7 +84,7 @@ bool X64Backend::Initialize(Processor* processor) {
} }
// Need movbe to do advanced LOAD/STORE tricks. // Need movbe to do advanced LOAD/STORE tricks.
if (FLAGS_enable_haswell_instructions) { if (cvars::enable_haswell_instructions) {
machine_info_.supports_extended_load_store = machine_info_.supports_extended_load_store =
cpu.has(Xbyak::util::Cpu::tMOVBE); cpu.has(Xbyak::util::Cpu::tMOVBE);
} else { } else {

View File

@ -10,10 +10,9 @@
#ifndef XENIA_CPU_BACKEND_X64_X64_BACKEND_H_ #ifndef XENIA_CPU_BACKEND_X64_X64_BACKEND_H_
#define XENIA_CPU_BACKEND_X64_X64_BACKEND_H_ #define XENIA_CPU_BACKEND_X64_X64_BACKEND_H_
#include <gflags/gflags.h>
#include <memory> #include <memory>
#include "xenia/base/cvar.h"
#include "xenia/cpu/backend/backend.h" #include "xenia/cpu/backend/backend.h"
DECLARE_bool(enable_haswell_instructions); DECLARE_bool(enable_haswell_instructions);

View File

@ -9,8 +9,6 @@
#include "xenia/cpu/backend/x64/x64_emitter.h" #include "xenia/cpu/backend/x64/x64_emitter.h"
#include <gflags/gflags.h>
#include <stddef.h> #include <stddef.h>
#include <climits> #include <climits>
#include <cstring> #include <cstring>
@ -36,11 +34,12 @@
#include "xenia/cpu/thread_state.h" #include "xenia/cpu/thread_state.h"
DEFINE_bool(enable_debugprint_log, false, DEFINE_bool(enable_debugprint_log, false,
"Log debugprint traps to the active debugger"); "Log debugprint traps to the active debugger", "CPU");
DEFINE_bool(ignore_undefined_externs, true, DEFINE_bool(ignore_undefined_externs, true,
"Don't exit when an undefined extern is called."); "Don't exit when an undefined extern is called.", "CPU");
DEFINE_bool(emit_source_annotations, false, DEFINE_bool(emit_source_annotations, false,
"Add extra movs and nops to make disassembly easier to read."); "Add extra movs and nops to make disassembly easier to read.",
"CPU");
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -71,7 +70,7 @@ X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator)
backend_(backend), backend_(backend),
code_cache_(backend->code_cache()), code_cache_(backend->code_cache()),
allocator_(allocator) { allocator_(allocator) {
if (FLAGS_enable_haswell_instructions) { if (cvars::enable_haswell_instructions) {
feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tAVX2) ? kX64EmitAVX2 : 0; feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tAVX2) ? kX64EmitAVX2 : 0;
feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tFMA) ? kX64EmitFMA : 0; feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tFMA) ? kX64EmitFMA : 0;
feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tLZCNT) ? kX64EmitLZCNT : 0; feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tLZCNT) ? kX64EmitLZCNT : 0;
@ -245,7 +244,7 @@ bool X64Emitter::Emit(HIRBuilder* builder, size_t* out_stack_size) {
add(rsp, (uint32_t)stack_size); add(rsp, (uint32_t)stack_size);
ret(); ret();
if (FLAGS_emit_source_annotations) { if (cvars::emit_source_annotations) {
nop(); nop();
nop(); nop();
nop(); nop();
@ -262,7 +261,7 @@ void X64Emitter::MarkSourceOffset(const Instr* i) {
entry->hir_offset = uint32_t(i->block->ordinal << 16) | i->ordinal; entry->hir_offset = uint32_t(i->block->ordinal << 16) | i->ordinal;
entry->code_offset = static_cast<uint32_t>(getSize()); entry->code_offset = static_cast<uint32_t>(getSize());
if (FLAGS_emit_source_annotations) { if (cvars::emit_source_annotations) {
nop(); nop();
nop(); nop();
mov(eax, entry->guest_address); mov(eax, entry->guest_address);
@ -299,7 +298,7 @@ uint64_t TrapDebugPrint(void* raw_context, uint64_t address) {
// TODO(benvanik): truncate to length? // TODO(benvanik): truncate to length?
XELOGD("(DebugPrint) %s", str); XELOGD("(DebugPrint) %s", str);
if (FLAGS_enable_debugprint_log) { if (cvars::enable_debugprint_log) {
debugging::DebugPrint("(DebugPrint) %s", str); debugging::DebugPrint("(DebugPrint) %s", str);
} }
@ -309,7 +308,7 @@ uint64_t TrapDebugPrint(void* raw_context, uint64_t address) {
uint64_t TrapDebugBreak(void* raw_context, uint64_t address) { uint64_t TrapDebugBreak(void* raw_context, uint64_t address) {
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context); auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
XELOGE("tw/td forced trap hit! This should be a crash!"); XELOGE("tw/td forced trap hit! This should be a crash!");
if (FLAGS_break_on_debugbreak) { if (cvars::break_on_debugbreak) {
xe::debugging::Break(); xe::debugging::Break();
} }
return 0; return 0;
@ -446,7 +445,7 @@ void X64Emitter::CallIndirect(const hir::Instr* instr,
uint64_t UndefinedCallExtern(void* raw_context, uint64_t function_ptr) { uint64_t UndefinedCallExtern(void* raw_context, uint64_t function_ptr) {
auto function = reinterpret_cast<Function*>(function_ptr); auto function = reinterpret_cast<Function*>(function_ptr);
if (!FLAGS_ignore_undefined_externs) { if (!cvars::ignore_undefined_externs) {
xe::FatalError("undefined extern call to %.8X %s", function->address(), xe::FatalError("undefined extern call to %.8X %s", function->address(),
function->name().c_str()); function->name().c_str());
} else { } else {

View File

@ -9,8 +9,6 @@
#include "xenia/cpu/compiler/passes/conditional_group_pass.h" #include "xenia/cpu/compiler/passes/conditional_group_pass.h"
#include <gflags/gflags.h>
#include "xenia/base/profiling.h" #include "xenia/base/profiling.h"
#include "xenia/cpu/compiler/compiler.h" #include "xenia/cpu/compiler/compiler.h"
#include "xenia/cpu/ppc/ppc_context.h" #include "xenia/cpu/ppc/ppc_context.h"

View File

@ -9,15 +9,16 @@
#include "xenia/cpu/compiler/passes/constant_propagation_pass.h" #include "xenia/cpu/compiler/passes/constant_propagation_pass.h"
#include <gflags/gflags.h>
#include <cmath> #include <cmath>
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/profiling.h" #include "xenia/base/profiling.h"
#include "xenia/cpu/function.h" #include "xenia/cpu/function.h"
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
DEFINE_bool(inline_mmio_access, true, "Inline constant MMIO loads and stores."); DEFINE_bool(inline_mmio_access, true, "Inline constant MMIO loads and stores.",
"CPU");
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -221,7 +222,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder, bool& result) {
auto mmio_range = auto mmio_range =
processor_->memory()->LookupVirtualMappedRange(address); processor_->memory()->LookupVirtualMappedRange(address);
if (FLAGS_inline_mmio_access && mmio_range) { if (cvars::inline_mmio_access && mmio_range) {
i->Replace(&OPCODE_LOAD_MMIO_info, 0); i->Replace(&OPCODE_LOAD_MMIO_info, 0);
i->src1.offset = reinterpret_cast<uint64_t>(mmio_range); i->src1.offset = reinterpret_cast<uint64_t>(mmio_range);
i->src2.offset = address; i->src2.offset = address;
@ -273,7 +274,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder, bool& result) {
break; break;
case OPCODE_STORE: case OPCODE_STORE:
case OPCODE_STORE_OFFSET: case OPCODE_STORE_OFFSET:
if (FLAGS_inline_mmio_access && i->src1.value->IsConstant()) { if (cvars::inline_mmio_access && i->src1.value->IsConstant()) {
auto address = i->src1.value->constant.i32; auto address = i->src1.value->constant.i32;
if (i->opcode->num == OPCODE_STORE_OFFSET) { if (i->opcode->num == OPCODE_STORE_OFFSET) {
address += i->src2.value->constant.i32; address += i->src2.value->constant.i32;

View File

@ -9,8 +9,8 @@
#include "xenia/cpu/compiler/passes/context_promotion_pass.h" #include "xenia/cpu/compiler/passes/context_promotion_pass.h"
#include <gflags/gflags.h> #include "xenia/apu/apu_flags.h"
#include "xenia/base/cvar.h"
#include "xenia/base/profiling.h" #include "xenia/base/profiling.h"
#include "xenia/cpu/compiler/compiler.h" #include "xenia/cpu/compiler/compiler.h"
#include "xenia/cpu/ppc/ppc_context.h" #include "xenia/cpu/ppc/ppc_context.h"
@ -19,7 +19,7 @@
DECLARE_bool(debug); DECLARE_bool(debug);
DEFINE_bool(store_all_context_values, false, DEFINE_bool(store_all_context_values, false,
"Don't strip dead context stores to aid in debugging."); "Don't strip dead context stores to aid in debugging.", "CPU");
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -77,7 +77,7 @@ bool ContextPromotionPass::Run(HIRBuilder* builder) {
// Remove all dead stores. // Remove all dead stores.
// This will break debugging as we can't recover this information when // This will break debugging as we can't recover this information when
// trying to extract stack traces/register values, so we don't do that. // trying to extract stack traces/register values, so we don't do that.
if (!FLAGS_debug && !FLAGS_store_all_context_values) { if (!cvars::debug && !cvars::store_all_context_values) {
block = builder->first_block(); block = builder->first_block();
while (block) { while (block) {
RemoveDeadStoresBlock(block); RemoveDeadStoresBlock(block);

View File

@ -9,38 +9,42 @@
#include "xenia/cpu/cpu_flags.h" #include "xenia/cpu/cpu_flags.h"
DEFINE_string(cpu, "any", "CPU backend [any, x64]."); DEFINE_string(cpu, "any", "CPU backend [any, x64].", "CPU");
DEFINE_string( DEFINE_string(
load_module_map, "", load_module_map, "",
"Loads a .map for symbol names and to diff with the generated symbol " "Loads a .map for symbol names and to diff with the generated symbol "
"database."); "database.",
"CPU");
DEFINE_bool(disassemble_functions, false, DEFINE_bool(disassemble_functions, false,
"Disassemble functions during generation."); "Disassemble functions during generation.", "CPU");
DEFINE_bool(trace_functions, false, DEFINE_bool(trace_functions, false, "Generate tracing for function statistics.",
"Generate tracing for function statistics."); "CPU");
DEFINE_bool(trace_function_coverage, false, DEFINE_bool(trace_function_coverage, false,
"Generate tracing for function instruction coverage statistics."); "Generate tracing for function instruction coverage statistics.",
"CPU");
DEFINE_bool(trace_function_references, false, DEFINE_bool(trace_function_references, false,
"Generate tracing for function address references."); "Generate tracing for function address references.", "CPU");
DEFINE_bool(trace_function_data, false, DEFINE_bool(trace_function_data, false,
"Generate tracing for function result data."); "Generate tracing for function result data.", "CPU");
DEFINE_bool( DEFINE_bool(
disable_global_lock, false, disable_global_lock, false,
"Disables global lock usage in guest code. Does not affect host code."); "Disables global lock usage in guest code. Does not affect host code.",
"CPU");
DEFINE_bool(validate_hir, false, DEFINE_bool(validate_hir, false,
"Perform validation checks on the HIR during compilation."); "Perform validation checks on the HIR during compilation.", "CPU");
// Breakpoints: // Breakpoints:
DEFINE_uint64(break_on_instruction, 0, DEFINE_uint64(break_on_instruction, 0,
"int3 before the given guest address is executed."); "int3 before the given guest address is executed.", "CPU");
DEFINE_int32(break_condition_gpr, -1, "GPR compared to"); DEFINE_int32(break_condition_gpr, -1, "GPR compared to", "CPU");
DEFINE_uint64(break_condition_value, 0, "value compared against"); DEFINE_uint64(break_condition_value, 0, "value compared against", "CPU");
DEFINE_string(break_condition_op, "eq", "comparison operator"); DEFINE_string(break_condition_op, "eq", "comparison operator", "CPU");
DEFINE_bool(break_condition_truncate, true, "truncate value to 32-bits"); DEFINE_bool(break_condition_truncate, true, "truncate value to 32-bits", "CPU");
DEFINE_bool(break_on_debugbreak, true, "int3 on JITed __debugbreak requests."); DEFINE_bool(break_on_debugbreak, true, "int3 on JITed __debugbreak requests.",
"CPU");

View File

@ -9,8 +9,7 @@
#ifndef XENIA_CPU_CPU_FLAGS_H_ #ifndef XENIA_CPU_CPU_FLAGS_H_
#define XENIA_CPU_CPU_FLAGS_H_ #define XENIA_CPU_CPU_FLAGS_H_
#include "xenia/base/cvar.h"
#include <gflags/gflags.h>
DECLARE_string(cpu); DECLARE_string(cpu);

View File

@ -728,12 +728,12 @@ int InstrEmit_mtmsr(PPCHIRBuilder& f, const InstrData& i) {
f.ZeroExtend(f.ZeroExtend(f.LoadGPR(i.X.RT), INT64_TYPE), INT64_TYPE)); f.ZeroExtend(f.ZeroExtend(f.LoadGPR(i.X.RT), INT64_TYPE), INT64_TYPE));
if (i.X.RT == 13) { if (i.X.RT == 13) {
// iff storing from r13 we are taking a lock (disable interrupts). // iff storing from r13 we are taking a lock (disable interrupts).
if (!FLAGS_disable_global_lock) { if (!cvars::disable_global_lock) {
f.CallExtern(f.builtins()->enter_global_lock); f.CallExtern(f.builtins()->enter_global_lock);
} }
} else { } else {
// Otherwise we are restoring interrupts (probably). // Otherwise we are restoring interrupts (probably).
if (!FLAGS_disable_global_lock) { if (!cvars::disable_global_lock) {
f.CallExtern(f.builtins()->leave_global_lock); f.CallExtern(f.builtins()->leave_global_lock);
} }
} }
@ -753,12 +753,12 @@ int InstrEmit_mtmsrd(PPCHIRBuilder& f, const InstrData& i) {
f.ZeroExtend(f.LoadGPR(i.X.RT), INT64_TYPE)); f.ZeroExtend(f.LoadGPR(i.X.RT), INT64_TYPE));
if (i.X.RT == 13) { if (i.X.RT == 13) {
// iff storing from r13 we are taking a lock (disable interrupts). // iff storing from r13 we are taking a lock (disable interrupts).
if (!FLAGS_disable_global_lock) { if (!cvars::disable_global_lock) {
f.CallExtern(f.builtins()->enter_global_lock); f.CallExtern(f.builtins()->enter_global_lock);
} }
} else { } else {
// Otherwise we are restoring interrupts (probably). // Otherwise we are restoring interrupts (probably).
if (!FLAGS_disable_global_lock) { if (!cvars::disable_global_lock) {
f.CallExtern(f.builtins()->leave_global_lock); f.CallExtern(f.builtins()->leave_global_lock);
} }
} }

View File

@ -182,25 +182,25 @@ bool PPCHIRBuilder::Emit(GuestFunction* function, uint32_t flags) {
} }
void PPCHIRBuilder::MaybeBreakOnInstruction(uint32_t address) { void PPCHIRBuilder::MaybeBreakOnInstruction(uint32_t address) {
if (address != FLAGS_break_on_instruction) { if (address != cvars::break_on_instruction) {
return; return;
} }
Comment("--break-on-instruction target"); Comment("--break-on-instruction target");
if (FLAGS_break_condition_gpr < 0) { if (cvars::break_condition_gpr < 0) {
DebugBreak(); DebugBreak();
return; return;
} }
auto left = LoadGPR(FLAGS_break_condition_gpr); auto left = LoadGPR(cvars::break_condition_gpr);
auto right = LoadConstantUint64(FLAGS_break_condition_value); auto right = LoadConstantUint64(cvars::break_condition_value);
if (FLAGS_break_condition_truncate) { if (cvars::break_condition_truncate) {
left = Truncate(left, INT32_TYPE); left = Truncate(left, INT32_TYPE);
right = Truncate(right, INT32_TYPE); right = Truncate(right, INT32_TYPE);
} }
auto op = FLAGS_break_condition_op.c_str(); auto op = cvars::break_condition_op.c_str();
// TODO(rick): table? // TODO(rick): table?
if (strcasecmp(op, "eq") == 0) { if (strcasecmp(op, "eq") == 0) {
TrapTrue(CompareEQ(left, right)); TrapTrue(CompareEQ(left, right));

View File

@ -9,8 +9,6 @@
#include "xenia/cpu/ppc/ppc_translator.h" #include "xenia/cpu/ppc/ppc_translator.h"
#include <gflags/gflags.h>
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/byte_order.h" #include "xenia/base/byte_order.h"
#include "xenia/base/memory.h" #include "xenia/base/memory.h"
@ -41,7 +39,7 @@ PPCTranslator::PPCTranslator(PPCFrontend* frontend) : frontend_(frontend) {
assembler_ = backend->CreateAssembler(); assembler_ = backend->CreateAssembler();
assembler_->Initialize(); assembler_->Initialize();
bool validate = FLAGS_validate_hir; bool validate = cvars::validate_hir;
// Merge blocks early. This will let us use more context in other passes. // Merge blocks early. This will let us use more context in other passes.
// The CFG is required for simplification and dirtied by it. // The CFG is required for simplification and dirtied by it.
@ -108,19 +106,19 @@ bool PPCTranslator::Translate(GuestFunction* function,
xe::make_reset_scope(&string_buffer_); xe::make_reset_scope(&string_buffer_);
// NOTE: we only want to do this when required, as it's expensive to build. // NOTE: we only want to do this when required, as it's expensive to build.
if (FLAGS_disassemble_functions) { if (cvars::disassemble_functions) {
debug_info_flags |= DebugInfoFlags::kDebugInfoAllDisasm; debug_info_flags |= DebugInfoFlags::kDebugInfoAllDisasm;
} }
if (FLAGS_trace_functions) { if (cvars::trace_functions) {
debug_info_flags |= DebugInfoFlags::kDebugInfoTraceFunctions; debug_info_flags |= DebugInfoFlags::kDebugInfoTraceFunctions;
} }
if (FLAGS_trace_function_coverage) { if (cvars::trace_function_coverage) {
debug_info_flags |= DebugInfoFlags::kDebugInfoTraceFunctionCoverage; debug_info_flags |= DebugInfoFlags::kDebugInfoTraceFunctionCoverage;
} }
if (FLAGS_trace_function_references) { if (cvars::trace_function_references) {
debug_info_flags |= DebugInfoFlags::kDebugInfoTraceFunctionReferences; debug_info_flags |= DebugInfoFlags::kDebugInfoTraceFunctionReferences;
} }
if (FLAGS_trace_function_data) { if (cvars::trace_function_data) {
debug_info_flags |= DebugInfoFlags::kDebugInfoTraceFunctionData; debug_info_flags |= DebugInfoFlags::kDebugInfoTraceFunctionData;
} }
std::unique_ptr<FunctionDebugInfo> debug_info; std::unique_ptr<FunctionDebugInfo> debug_info;

View File

@ -7,8 +7,6 @@
****************************************************************************** ******************************************************************************
*/ */
#include <gflags/gflags.h>
#include "xenia/base/filesystem.h" #include "xenia/base/filesystem.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/main.h" #include "xenia/base/main.h"
@ -26,9 +24,9 @@
#endif // XE_COMPILER_MSVC #endif // XE_COMPILER_MSVC
DEFINE_string(test_path, "src/xenia/cpu/ppc/testing/", DEFINE_string(test_path, "src/xenia/cpu/ppc/testing/",
"Directory scanned for test files."); "Directory scanned for test files.", "Other");
DEFINE_string(test_bin_path, "src/xenia/cpu/ppc/testing/bin/", DEFINE_string(test_bin_path, "src/xenia/cpu/ppc/testing/bin/",
"Directory with binary outputs of the test files."); "Directory with binary outputs of the test files.", "Other");
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -54,8 +52,8 @@ class TestSuite {
name = src_file_path.substr(src_file_path.find_last_of(xe::kPathSeparator) + name = src_file_path.substr(src_file_path.find_last_of(xe::kPathSeparator) +
1); 1);
name = ReplaceExtension(name, L""); name = ReplaceExtension(name, L"");
map_file_path = xe::to_wstring(FLAGS_test_bin_path) + name + L".map"; map_file_path = xe::to_wstring(cvars::test_bin_path) + name + L".map";
bin_file_path = xe::to_wstring(FLAGS_test_bin_path) + name + L".bin"; bin_file_path = xe::to_wstring(cvars::test_bin_path) + name + L".bin";
} }
bool Load() { bool Load() {
@ -192,11 +190,11 @@ class TestRunner {
std::unique_ptr<xe::cpu::backend::Backend> backend; std::unique_ptr<xe::cpu::backend::Backend> backend;
if (!backend) { if (!backend) {
#if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND #if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND
if (FLAGS_cpu == "x64") { if (cvars::cpu == "x64") {
backend.reset(new xe::cpu::backend::x64::X64Backend()); backend.reset(new xe::cpu::backend::x64::X64Backend());
} }
#endif // XENIA_HAS_X64_BACKEND #endif // XENIA_HAS_X64_BACKEND
if (FLAGS_cpu == "any") { if (cvars::cpu == "any") {
#if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND #if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND
if (!backend) { if (!backend) {
backend.reset(new xe::cpu::backend::x64::X64Backend()); backend.reset(new xe::cpu::backend::x64::X64Backend());
@ -408,7 +406,7 @@ bool RunTests(const std::wstring& test_name) {
int passed_count = 0; int passed_count = 0;
auto test_path_root = auto test_path_root =
xe::fix_path_separators(xe::to_wstring(FLAGS_test_path)); xe::fix_path_separators(xe::to_wstring(cvars::test_path));
std::vector<std::wstring> test_files; std::vector<std::wstring> test_files;
if (!DiscoverTests(test_path_root, test_files)) { if (!DiscoverTests(test_path_root, test_files)) {
return false; return false;

View File

@ -7,8 +7,6 @@
****************************************************************************** ******************************************************************************
*/ */
#include <gflags/gflags.h>
#include "xenia/base/filesystem.h" #include "xenia/base/filesystem.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/main.h" #include "xenia/base/main.h"
@ -58,8 +56,8 @@ class TestSuite {
name = src_file_path.substr(src_file_path.find_last_of(xe::kPathSeparator) + name = src_file_path.substr(src_file_path.find_last_of(xe::kPathSeparator) +
1); 1);
name = ReplaceExtension(name, L""); name = ReplaceExtension(name, L"");
map_file_path = xe::to_wstring(FLAGS_test_bin_path) + name + L".map"; map_file_path = xe::to_wstring(cvars::test_bin_path) + name + L".map";
bin_file_path = xe::to_wstring(FLAGS_test_bin_path) + name + L".bin"; bin_file_path = xe::to_wstring(cvars::test_bin_path) + name + L".bin";
} }
bool Load() { bool Load() {
@ -454,7 +452,7 @@ bool RunTests(const std::wstring& test_name) {
int passed_count = 0; int passed_count = 0;
auto test_path_root = auto test_path_root =
xe::fix_path_separators(xe::to_wstring(FLAGS_test_path)); xe::fix_path_separators(xe::to_wstring(cvars::test_path));
std::vector<std::wstring> test_files; std::vector<std::wstring> test_files;
if (!DiscoverTests(test_path_root, test_files)) { if (!DiscoverTests(test_path_root, test_files)) {
return false; return false;

View File

@ -11,7 +11,6 @@ project("xenia-cpu-ppc-tests")
"xenia-cpu-backend-x64", "xenia-cpu-backend-x64",
"xenia-cpu", "xenia-cpu",
"xenia-base", "xenia-base",
"gflags",
"capstone", -- cpu-backend-x64 "capstone", -- cpu-backend-x64
"mspack", "mspack",
}) })
@ -22,15 +21,11 @@ project("xenia-cpu-ppc-tests")
files({ files({
"*.s", "*.s",
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
filter("files:*.s") filter("files:*.s")
flags({"ExcludeFromBuild"}) flags({"ExcludeFromBuild"})
filter("platforms:Windows") filter("platforms:Windows")
debugdir(project_root) debugdir(project_root)
debugargs({ debugargs({
"--flagfile=scratch/flags.txt",
"2>&1", "2>&1",
"1>scratch/stdout-testing.txt", "1>scratch/stdout-testing.txt",
}) })
@ -46,7 +41,6 @@ project("xenia-cpu-ppc-nativetests")
language("C++") language("C++")
links({ links({
"xenia-base", "xenia-base",
"gflags",
}) })
files({ files({
"ppc_testing_native_main.cc", "ppc_testing_native_main.cc",
@ -59,9 +53,6 @@ project("xenia-cpu-ppc-nativetests")
filter("files:instr_*.s", "files:seq_*.s") filter("files:instr_*.s", "files:seq_*.s")
flags({"ExcludeFromBuild"}) flags({"ExcludeFromBuild"})
filter({}) filter({})
includedirs({
project_root.."/third_party/gflags/src",
})
buildoptions({ buildoptions({
"-Wa,-mregnames", -- Tell GAS to accept register names. "-Wa,-mregnames", -- Tell GAS to accept register names.
}) })

View File

@ -12,7 +12,6 @@ project("xenia-cpu")
}) })
includedirs({ includedirs({
project_root.."/third_party/llvm/include", project_root.."/third_party/llvm/include",
project_root.."/third_party/gflags/src",
}) })
local_platform_files() local_platform_files()
local_platform_files("backend") local_platform_files("backend")

View File

@ -9,12 +9,11 @@
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
#include <gflags/gflags.h>
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/atomic.h" #include "xenia/base/atomic.h"
#include "xenia/base/byte_order.h" #include "xenia/base/byte_order.h"
#include "xenia/base/byte_stream.h" #include "xenia/base/byte_stream.h"
#include "xenia/base/cvar.h"
#include "xenia/base/debugging.h" #include "xenia/base/debugging.h"
#include "xenia/base/exception_handler.h" #include "xenia/base/exception_handler.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
@ -42,9 +41,11 @@
#endif #endif
DEFINE_bool(debug, DEFAULT_DEBUG_FLAG, DEFINE_bool(debug, DEFAULT_DEBUG_FLAG,
"Allow debugging and retain debug information."); "Allow debugging and retain debug information.", "General");
DEFINE_string(trace_function_data_path, "", "File to write trace data to."); DEFINE_string(trace_function_data_path, "", "File to write trace data to.",
DEFINE_bool(break_on_start, false, "Break into the debugger on startup."); "CPU");
DEFINE_bool(break_on_start, false, "Break into the debugger on startup.",
"CPU");
namespace xe { namespace xe {
namespace kernel { namespace kernel {
@ -132,14 +133,14 @@ bool Processor::Setup(std::unique_ptr<backend::Backend> backend) {
stack_walker_ = StackWalker::Create(backend_->code_cache()); stack_walker_ = StackWalker::Create(backend_->code_cache());
if (!stack_walker_) { if (!stack_walker_) {
// TODO(benvanik): disable features. // TODO(benvanik): disable features.
if (FLAGS_debug) { if (cvars::debug) {
XELOGW("Disabling --debug due to lack of stack walker"); XELOGW("Disabling --debug due to lack of stack walker");
FLAGS_debug = false; cvars::debug = false;
} }
} }
// Open the trace data path, if requested. // Open the trace data path, if requested.
functions_trace_path_ = xe::to_wstring(FLAGS_trace_function_data_path); functions_trace_path_ = xe::to_wstring(cvars::trace_function_data_path);
if (!functions_trace_path_.empty()) { if (!functions_trace_path_.empty()) {
functions_trace_file_ = ChunkedMappedMemoryWriter::Open( functions_trace_file_ = ChunkedMappedMemoryWriter::Open(
functions_trace_path_, 32 * 1024 * 1024, true); functions_trace_path_, 32 * 1024 * 1024, true);
@ -149,7 +150,7 @@ bool Processor::Setup(std::unique_ptr<backend::Backend> backend) {
} }
void Processor::PreLaunch() { void Processor::PreLaunch() {
if (FLAGS_break_on_start) { if (cvars::break_on_start) {
// Start paused. // Start paused.
XELOGI("Breaking into debugger because of --break_on_start..."); XELOGI("Breaking into debugger because of --break_on_start...");
execution_state_ = ExecutionState::kRunning; execution_state_ = ExecutionState::kRunning;
@ -629,9 +630,9 @@ bool Processor::OnThreadBreakpointHit(Exception* ex) {
SuspendAllBreakpoints(); SuspendAllBreakpoints();
} }
// Update all thread states with their latest values, using the context we got // Update all thread states with their latest values, using the context we
// from the exception instead of a sampled value (as it would just show the // got from the exception instead of a sampled value (as it would just show
// exception handler). // the exception handler).
UpdateThreadExecutionStates(thread_info->thread_id, ex->thread_context()); UpdateThreadExecutionStates(thread_info->thread_id, ex->thread_context());
// Walk the captured thread stack and look for breakpoints at any address in // Walk the captured thread stack and look for breakpoints at any address in

View File

@ -10,13 +10,12 @@
#ifndef XENIA_CPU_PROCESSOR_H_ #ifndef XENIA_CPU_PROCESSOR_H_
#define XENIA_CPU_PROCESSOR_H_ #define XENIA_CPU_PROCESSOR_H_
#include <gflags/gflags.h>
#include <map> #include <map>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "xenia/base/cvar.h"
#include "xenia/base/mapped_memory.h" #include "xenia/base/mapped_memory.h"
#include "xenia/base/mutex.h" #include "xenia/base/mutex.h"
#include "xenia/cpu/backend/backend.h" #include "xenia/cpu/backend/backend.h"

View File

@ -9,8 +9,6 @@
#include "xenia/cpu/stack_walker.h" #include "xenia/cpu/stack_walker.h"
#include <gflags/gflags.h>
#include <mutex> #include <mutex>
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
@ -20,7 +18,7 @@
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
DEFINE_bool(debug_symbol_loader, false, DEFINE_bool(debug_symbol_loader, false,
"Enable dbghelp debug logging and validation."); "Enable dbghelp debug logging and validation.", "CPU");
// Must be included after platform_win.h: // Must be included after platform_win.h:
#pragma warning(push) #pragma warning(push)
@ -98,7 +96,7 @@ bool InitializeStackWalker() {
// Initialize the symbol lookup services. // Initialize the symbol lookup services.
DWORD options = sym_get_options_(); DWORD options = sym_get_options_();
if (FLAGS_debug_symbol_loader) { if (cvars::debug_symbol_loader) {
options |= SYMOPT_DEBUG; options |= SYMOPT_DEBUG;
} }
options |= SYMOPT_DEFERRED_LOADS; options |= SYMOPT_DEFERRED_LOADS;

View File

@ -2,9 +2,6 @@ project_root = "../../../.."
include(project_root.."/tools/build") include(project_root.."/tools/build")
test_suite("xenia-cpu-tests", project_root, ".", { test_suite("xenia-cpu-tests", project_root, ".", {
includedirs = {
project_root.."/third_party/gflags/src",
},
links = { links = {
"capstone", "capstone",
"xenia-base", "xenia-base",

View File

@ -14,8 +14,6 @@
#include "xenia/cpu/ppc/ppc_frontend.h" #include "xenia/cpu/ppc/ppc_frontend.h"
#include "xenia/cpu/raw_module.h" #include "xenia/cpu/raw_module.h"
#include <gflags/gflags.h>
namespace xe { namespace xe {
namespace cpu { namespace cpu {
namespace sandbox { namespace sandbox {

View File

@ -1008,8 +1008,8 @@ bool XexModule::LoadContinue() {
} }
// Load a specified module map and diff. // Load a specified module map and diff.
if (FLAGS_load_module_map.size()) { if (cvars::load_module_map.size()) {
if (!ReadMap(FLAGS_load_module_map.c_str())) { if (!ReadMap(cvars::load_module_map.c_str())) {
return false; return false;
} }
} }

View File

@ -9,8 +9,6 @@
#include "xenia/debug/ui/debug_window.h" #include "xenia/debug/ui/debug_window.h"
#include <gflags/gflags.h>
#include <algorithm> #include <algorithm>
#include <cinttypes> #include <cinttypes>
#include <utility> #include <utility>
@ -35,7 +33,7 @@
#include "xenia/ui/graphics_provider.h" #include "xenia/ui/graphics_provider.h"
#include "xenia/ui/imgui_drawer.h" #include "xenia/ui/imgui_drawer.h"
DEFINE_bool(imgui_debug, false, "Show ImGui debugging tools."); DEFINE_bool(imgui_debug, false, "Show ImGui debugging tools.", "Other");
namespace xe { namespace xe {
namespace debug { namespace debug {
@ -238,7 +236,7 @@ void DebugWindow::DrawFrame() {
ImGui::End(); ImGui::End();
ImGui::PopStyleVar(); ImGui::PopStyleVar();
if (FLAGS_imgui_debug) { if (cvars::imgui_debug) {
ImGui::ShowTestWindow(); ImGui::ShowTestWindow();
ImGui::ShowMetricsWindow(); ImGui::ShowMetricsWindow();
} }

View File

@ -16,7 +16,6 @@ project("xenia-debug-ui")
defines({ defines({
}) })
includedirs({ includedirs({
project_root.."/third_party/gflags/src",
project_root.."/third_party/yaml-cpp/include/", project_root.."/third_party/yaml-cpp/include/",
}) })
local_platform_files() local_platform_files()

View File

@ -9,13 +9,14 @@
#include "xenia/emulator.h" #include "xenia/emulator.h"
#include <gflags/gflags.h>
#include <cinttypes> #include <cinttypes>
#include "config.h"
#include "xenia/apu/audio_system.h" #include "xenia/apu/audio_system.h"
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/byte_stream.h" #include "xenia/base/byte_stream.h"
#include "xenia/base/clock.h" #include "xenia/base/clock.h"
#include "xenia/base/cvar.h"
#include "xenia/base/debugging.h" #include "xenia/base/debugging.h"
#include "xenia/base/exception_handler.h" #include "xenia/base/exception_handler.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
@ -44,7 +45,8 @@
#include "xenia/vfs/virtual_file_system.h" #include "xenia/vfs/virtual_file_system.h"
DEFINE_double(time_scalar, 1.0, DEFINE_double(time_scalar, 1.0,
"Scalar used to speed or slow time (1x, 2x, 1/2x, etc)."); "Scalar used to speed or slow time (1x, 2x, 1/2x, etc).",
"General");
namespace xe { namespace xe {
@ -112,7 +114,7 @@ X_STATUS Emulator::Setup(
// We could reset this with save state data/constant value to help replays. // We could reset this with save state data/constant value to help replays.
Clock::set_guest_system_time_base(Clock::QueryHostSystemTime()); Clock::set_guest_system_time_base(Clock::QueryHostSystemTime());
// This can be adjusted dynamically, as well. // This can be adjusted dynamically, as well.
Clock::set_guest_time_scalar(FLAGS_time_scalar); Clock::set_guest_time_scalar(cvars::time_scalar);
// Before we can set thread affinity we must enable the process to use all // Before we can set thread affinity we must enable the process to use all
// logical processors. // logical processors.
@ -130,11 +132,11 @@ X_STATUS Emulator::Setup(
std::unique_ptr<xe::cpu::backend::Backend> backend; std::unique_ptr<xe::cpu::backend::Backend> backend;
if (!backend) { if (!backend) {
#if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND #if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND
if (FLAGS_cpu == "x64") { if (cvars::cpu == "x64") {
backend.reset(new xe::cpu::backend::x64::X64Backend()); backend.reset(new xe::cpu::backend::x64::X64Backend());
} }
#endif // XENIA_HAS_X64_BACKEND #endif // XENIA_HAS_X64_BACKEND
if (FLAGS_cpu == "any") { if (cvars::cpu == "any") {
#if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND #if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND
if (!backend) { if (!backend) {
backend.reset(new xe::cpu::backend::x64::X64Backend()); backend.reset(new xe::cpu::backend::x64::X64Backend());
@ -646,6 +648,7 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring& path,
if (module->title_id()) { if (module->title_id()) {
char title_id[9] = {0}; char title_id[9] = {0};
std::snprintf(title_id, xe::countof(title_id), "%08X", module->title_id()); std::snprintf(title_id, xe::countof(title_id), "%08X", module->title_id());
config::LoadGameConfig(xe::to_wstring(title_id));
uint32_t resource_data = 0; uint32_t resource_data = 0;
uint32_t resource_size = 0; uint32_t resource_size = 0;
if (XSUCCEEDED( if (XSUCCEEDED(

View File

@ -393,7 +393,7 @@ void CommandProcessor::IssueSwap(uint32_t frontbuffer_ptr,
// This prevents the display from pulling the backbuffer out from under us. // This prevents the display from pulling the backbuffer out from under us.
// If we skip a lot then we may need to buffer more, but as the display // If we skip a lot then we may need to buffer more, but as the display
// thread should be fairly idle that shouldn't happen. // thread should be fairly idle that shouldn't happen.
if (!FLAGS_vsync) { if (!cvars::vsync) {
std::lock_guard<std::mutex> lock(swap_state_.mutex); std::lock_guard<std::mutex> lock(swap_state_.mutex);
if (swap_state_.pending) { if (swap_state_.pending) {
swap_state_.pending = false; swap_state_.pending = false;
@ -895,7 +895,7 @@ bool CommandProcessor::ExecutePacketType3_WAIT_REG_MEM(RingBuffer* reader,
// Wait. // Wait.
if (wait >= 0x100) { if (wait >= 0x100) {
PrepareForWait(); PrepareForWait();
if (!FLAGS_vsync) { if (!cvars::vsync) {
// User wants it fast and dangerous. // User wants it fast and dangerous.
xe::threading::MaybeYield(); xe::threading::MaybeYield();
} else { } else {

View File

@ -7,18 +7,17 @@
****************************************************************************** ******************************************************************************
*/ */
#include "xenia/gpu/d3d12/d3d12_command_processor.h"
#include <gflags/gflags.h>
#include "third_party/xxhash/xxhash.h" #include "third_party/xxhash/xxhash.h"
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/base/profiling.h" #include "xenia/base/profiling.h"
#include "xenia/gpu/d3d12/d3d12_command_processor.h"
#include "xenia/gpu/d3d12/d3d12_graphics_system.h" #include "xenia/gpu/d3d12/d3d12_graphics_system.h"
#include "xenia/gpu/d3d12/d3d12_shader.h" #include "xenia/gpu/d3d12/d3d12_shader.h"
#include "xenia/gpu/xenos.h" #include "xenia/gpu/xenos.h"
@ -26,27 +25,31 @@
DEFINE_bool(d3d12_edram_rov, true, DEFINE_bool(d3d12_edram_rov, true,
"Use rasterizer-ordered views for render target emulation where " "Use rasterizer-ordered views for render target emulation where "
"available."); "available.",
"D3D12");
// Some games (such as Banjo-Kazooie) are not aware of the half-pixel offset and // Some games (such as Banjo-Kazooie) are not aware of the half-pixel offset and
// may be blurry or have texture sampling artifacts, in this case the user may // may be blurry or have texture sampling artifacts, in this case the user may
// disable half-pixel offset by setting this to false. // disable half-pixel offset by setting this to false.
DEFINE_bool(d3d12_half_pixel_offset, true, DEFINE_bool(d3d12_half_pixel_offset, true,
"Enable half-pixel vertex and VPOS offset."); "Enable half-pixel vertex and VPOS offset.", "D3D12");
DEFINE_bool(d3d12_readback_memexport, false, DEFINE_bool(d3d12_readback_memexport, false,
"Read data written by memory export in shaders on the CPU. This " "Read data written by memory export in shaders on the CPU. This "
"may be needed in some games (but many only access exported data " "may be needed in some games (but many only access exported data "
"on the GPU, and this flag isn't needed to handle such behavior), " "on the GPU, and this flag isn't needed to handle such behavior), "
"but causes mid-frame synchronization, so it has a huge " "but causes mid-frame synchronization, so it has a huge "
"performance impact."); "performance impact.",
"D3D12");
DEFINE_bool(d3d12_readback_resolve, false, DEFINE_bool(d3d12_readback_resolve, false,
"Read render-to-texture results on the CPU. This may be needed in " "Read render-to-texture results on the CPU. This may be needed in "
"some games, for instance, for screenshots in saved games, but " "some games, for instance, for screenshots in saved games, but "
"causes mid-frame synchronization, so it has a huge performance " "causes mid-frame synchronization, so it has a huge performance "
"impact."); "impact.",
"D3D12");
DEFINE_bool(d3d12_ssaa_custom_sample_positions, false, DEFINE_bool(d3d12_ssaa_custom_sample_positions, false,
"Enable custom SSAA sample positions for the RTV/DSV rendering " "Enable custom SSAA sample positions for the RTV/DSV rendering "
"path where available instead of centers (experimental, not very " "path where available instead of centers (experimental, not very "
"high-quality)."); "high-quality).",
"D3D12");
namespace xe { namespace xe {
namespace gpu { namespace gpu {
@ -78,7 +81,7 @@ void D3D12CommandProcessor::RequestFrameTrace(const std::wstring& root_path) {
} }
bool D3D12CommandProcessor::IsROVUsedForEDRAM() const { bool D3D12CommandProcessor::IsROVUsedForEDRAM() const {
if (!FLAGS_d3d12_edram_rov) { if (!cvars::d3d12_edram_rov) {
return false; return false;
} }
auto provider = GetD3D12Context()->GetD3D12Provider(); auto provider = GetD3D12Context()->GetD3D12Provider();
@ -540,7 +543,7 @@ void D3D12CommandProcessor::SetSamplePositions(MsaaSamples sample_positions) {
// for ROV output. There's hardly any difference between 2,6 (of 0 and 3 with // for ROV output. There's hardly any difference between 2,6 (of 0 and 3 with
// 4x MSAA) and 4,4 anyway. // 4x MSAA) and 4,4 anyway.
// https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12graphicscommandlist1-setsamplepositions // https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12graphicscommandlist1-setsamplepositions
if (FLAGS_d3d12_ssaa_custom_sample_positions && !IsROVUsedForEDRAM()) { if (cvars::d3d12_ssaa_custom_sample_positions && !IsROVUsedForEDRAM()) {
auto provider = GetD3D12Context()->GetD3D12Provider(); auto provider = GetD3D12Context()->GetD3D12Provider();
auto tier = provider->GetProgrammableSamplePositionsTier(); auto tier = provider->GetProgrammableSamplePositionsTier();
if (tier >= 2 && if (tier >= 2 &&
@ -1611,7 +1614,7 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
memexport_range.base_address_dwords << 2, memexport_range.base_address_dwords << 2,
memexport_range.size_dwords << 2); memexport_range.size_dwords << 2);
} }
if (FLAGS_d3d12_readback_memexport) { if (cvars::d3d12_readback_memexport) {
// Read the exported data on the CPU. // Read the exported data on the CPU.
uint32_t memexport_total_size = 0; uint32_t memexport_total_size = 0;
for (uint32_t i = 0; i < memexport_range_count; ++i) { for (uint32_t i = 0; i < memexport_range_count; ++i) {
@ -1672,7 +1675,7 @@ bool D3D12CommandProcessor::IssueCopy() {
written_length)) { written_length)) {
return false; return false;
} }
if (FLAGS_d3d12_readback_resolve && !texture_cache_->IsResolutionScale2X() && if (cvars::d3d12_readback_resolve && !texture_cache_->IsResolutionScale2X() &&
written_length) { written_length) {
// Read the resolved data on the CPU. // Read the resolved data on the CPU.
ID3D12Resource* readback_buffer = RequestReadbackBuffer(written_length); ID3D12Resource* readback_buffer = RequestReadbackBuffer(written_length);
@ -2274,7 +2277,7 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
// TODO(Triang3l): Check if ps_param_gen should give center positions in // TODO(Triang3l): Check if ps_param_gen should give center positions in
// OpenGL mode on the Xbox 360. // OpenGL mode on the Xbox 360.
float pixel_half_pixel_offset = 0.5f; float pixel_half_pixel_offset = 0.5f;
if (FLAGS_d3d12_half_pixel_offset && !(pa_su_vtx_cntl & (1 << 0))) { if (cvars::d3d12_half_pixel_offset && !(pa_su_vtx_cntl & (1 << 0))) {
// Signs are hopefully correct here, tested in GTA IV on both clearing // Signs are hopefully correct here, tested in GTA IV on both clearing
// (without a viewport) and drawing things near the edges of the screen. // (without a viewport) and drawing things near the edges of the screen.
if (pa_cl_vte_cntl & (1 << 0)) { if (pa_cl_vte_cntl & (1 << 0)) {
@ -2406,7 +2409,7 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
// be incorrect in this case, but there's no other way without using ROV, // be incorrect in this case, but there's no other way without using ROV,
// though there's an option to limit the range to -1...1). // though there's an option to limit the range to -1...1).
// http://www.students.science.uu.nl/~3220516/advancedgraphics/papers/inferred_lighting.pdf // http://www.students.science.uu.nl/~3220516/advancedgraphics/papers/inferred_lighting.pdf
if (!IsROVUsedForEDRAM() && FLAGS_d3d12_16bit_rtv_full_range) { if (!IsROVUsedForEDRAM() && cvars::d3d12_16bit_rtv_full_range) {
color_exp_bias -= 5; color_exp_bias -= 5;
} }
} }

View File

@ -9,8 +9,6 @@
#include "xenia/gpu/d3d12/pipeline_cache.h" #include "xenia/gpu/d3d12/pipeline_cache.h"
#include <gflags/gflags.h>
#include <algorithm> #include <algorithm>
#include <cinttypes> #include <cinttypes>
#include <cmath> #include <cmath>
@ -20,6 +18,7 @@
#include "third_party/xxhash/xxhash.h" #include "third_party/xxhash/xxhash.h"
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/base/profiling.h" #include "xenia/base/profiling.h"
@ -28,21 +27,24 @@
#include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/gpu_flags.h"
DEFINE_bool(d3d12_dxbc_disasm, false, DEFINE_bool(d3d12_dxbc_disasm, false,
"Disassemble DXBC shaders after generation."); "Disassemble DXBC shaders after generation.", "D3D12");
DEFINE_int32( DEFINE_int32(
d3d12_pipeline_creation_threads, -1, d3d12_pipeline_creation_threads, -1,
"Number of threads used for graphics pipeline state creation. -1 to " "Number of threads used for graphics pipeline state creation. -1 to "
"calculate automatically (75% of logical CPU cores), 1-16 to specify the " "calculate automatically (75% of logical CPU cores), 1-16 to specify the "
"number of threads explicitly, 0 to disable multithreaded pipeline state " "number of threads explicitly, 0 to disable multithreaded pipeline state "
"creation."); "creation.",
"D3D12");
DEFINE_bool( DEFINE_bool(
d3d12_tessellation_adaptive, false, d3d12_tessellation_adaptive, false,
"Allow games to use adaptive tessellation - may be disabled if the game " "Allow games to use adaptive tessellation - may be disabled if the game "
"has issues with memexport, the maximum factor will be used in this case. " "has issues with memexport, the maximum factor will be used in this case. "
"Temporarily disabled by default since there are visible cracks currently " "Temporarily disabled by default since there are visible cracks currently "
"in Halo 3."); "in Halo 3.",
"D3D12");
DEFINE_bool(d3d12_tessellation_wireframe, false, DEFINE_bool(d3d12_tessellation_wireframe, false,
"Display tessellated surfaces as wireframe for debugging."); "Display tessellated surfaces as wireframe for debugging.",
"D3D12");
namespace xe { namespace xe {
namespace gpu { namespace gpu {
@ -81,18 +83,18 @@ PipelineCache::PipelineCache(D3D12CommandProcessor* command_processor,
PipelineCache::~PipelineCache() { Shutdown(); } PipelineCache::~PipelineCache() { Shutdown(); }
bool PipelineCache::Initialize() { bool PipelineCache::Initialize() {
if (FLAGS_d3d12_pipeline_creation_threads != 0) { if (cvars::d3d12_pipeline_creation_threads != 0) {
creation_threads_busy_ = 0; creation_threads_busy_ = 0;
creation_completion_event_ = creation_completion_event_ =
xe::threading::Event::CreateManualResetEvent(true); xe::threading::Event::CreateManualResetEvent(true);
creation_completion_set_event_ = false; creation_completion_set_event_ = false;
creation_threads_shutdown_ = false; creation_threads_shutdown_ = false;
uint32_t creation_thread_count; uint32_t creation_thread_count;
if (FLAGS_d3d12_pipeline_creation_threads < 0) { if (cvars::d3d12_pipeline_creation_threads < 0) {
creation_thread_count = std::max( creation_thread_count = std::max(
xe::threading::logical_processor_count() * 3 / 4, uint32_t(1)); xe::threading::logical_processor_count() * 3 / 4, uint32_t(1));
} else { } else {
creation_thread_count = uint32_t(FLAGS_d3d12_pipeline_creation_threads); creation_thread_count = uint32_t(cvars::d3d12_pipeline_creation_threads);
} }
creation_thread_count = std::min(creation_thread_count, uint32_t(16)); creation_thread_count = std::min(creation_thread_count, uint32_t(16));
for (uint32_t i = 0; i < creation_thread_count; ++i) { for (uint32_t i = 0; i < creation_thread_count; ++i) {
@ -331,7 +333,7 @@ bool PipelineCache::TranslateShader(D3D12Shader* shader,
} }
// Disassemble the shader for dumping. // Disassemble the shader for dumping.
if (FLAGS_d3d12_dxbc_disasm) { if (cvars::d3d12_dxbc_disasm) {
auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider(); auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider();
if (!shader->DisassembleDxbc(provider)) { if (!shader->DisassembleDxbc(provider)) {
XELOGE("Failed to disassemble DXBC shader %.16" PRIX64, XELOGE("Failed to disassemble DXBC shader %.16" PRIX64,
@ -340,8 +342,8 @@ bool PipelineCache::TranslateShader(D3D12Shader* shader,
} }
// Dump shader files if desired. // Dump shader files if desired.
if (!FLAGS_dump_shaders.empty()) { if (!cvars::dump_shaders.empty()) {
shader->Dump(FLAGS_dump_shaders, "d3d12"); shader->Dump(cvars::dump_shaders, "d3d12");
} }
return shader->is_valid(); return shader->is_valid();
@ -390,7 +392,7 @@ bool PipelineCache::GetCurrentStateDescription(
break; break;
case TessellationMode::kAdaptive: case TessellationMode::kAdaptive:
description_out.tessellation_mode = description_out.tessellation_mode =
FLAGS_d3d12_tessellation_adaptive cvars::d3d12_tessellation_adaptive
? PipelineTessellationMode::kAdaptive ? PipelineTessellationMode::kAdaptive
: PipelineTessellationMode::kContinuous; : PipelineTessellationMode::kContinuous;
break; break;
@ -549,7 +551,7 @@ bool PipelineCache::GetCurrentStateDescription(
description_out.depth_bias_slope_scaled = description_out.depth_bias_slope_scaled =
poly_offset_scale * (1.0f / 16.0f); poly_offset_scale * (1.0f / 16.0f);
} }
if (FLAGS_d3d12_tessellation_wireframe && tessellated && if (cvars::d3d12_tessellation_wireframe && tessellated &&
(primitive_type == PrimitiveType::kTrianglePatch || (primitive_type == PrimitiveType::kTrianglePatch ||
primitive_type == PrimitiveType::kQuadPatch)) { primitive_type == PrimitiveType::kQuadPatch)) {
description_out.fill_mode_wireframe = 1; description_out.fill_mode_wireframe = 1;

View File

@ -9,11 +9,10 @@
#include "xenia/gpu/d3d12/primitive_converter.h" #include "xenia/gpu/d3d12/primitive_converter.h"
#include <gflags/gflags.h>
#include <algorithm> #include <algorithm>
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/base/memory.h" #include "xenia/base/memory.h"
@ -26,7 +25,8 @@ DEFINE_bool(d3d12_convert_quads_to_triangles, false,
"Convert quad lists to triangle lists on the CPU instead of using " "Convert quad lists to triangle lists on the CPU instead of using "
"a geometry shader. Not recommended for playing, for debugging " "a geometry shader. Not recommended for playing, for debugging "
"primarily (because PIX fails to display vertices when a geometry " "primarily (because PIX fails to display vertices when a geometry "
"shader is used)."); "shader is used).",
"D3D12");
namespace xe { namespace xe {
namespace gpu { namespace gpu {
@ -176,7 +176,7 @@ PrimitiveType PrimitiveConverter::GetReplacementPrimitiveType(
case PrimitiveType::kLineLoop: case PrimitiveType::kLineLoop:
return PrimitiveType::kLineStrip; return PrimitiveType::kLineStrip;
case PrimitiveType::kQuadList: case PrimitiveType::kQuadList:
if (FLAGS_d3d12_convert_quads_to_triangles) { if (cvars::d3d12_convert_quads_to_triangles) {
return PrimitiveType::kTriangleList; return PrimitiveType::kTriangleList;
} }
break; break;
@ -213,7 +213,7 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
return ConversionResult::kConversionNotNeeded; return ConversionResult::kConversionNotNeeded;
} }
} else if (source_type == PrimitiveType::kQuadList) { } else if (source_type == PrimitiveType::kQuadList) {
if (!FLAGS_d3d12_convert_quads_to_triangles) { if (!cvars::d3d12_convert_quads_to_triangles) {
return ConversionResult::kConversionNotNeeded; return ConversionResult::kConversionNotNeeded;
} }
} else if (source_type != PrimitiveType::kTriangleFan && } else if (source_type != PrimitiveType::kTriangleFan &&
@ -731,7 +731,7 @@ D3D12_GPU_VIRTUAL_ADDRESS PrimitiveConverter::GetStaticIndexBuffer(
kStaticIBTriangleFanOffset * sizeof(uint16_t); kStaticIBTriangleFanOffset * sizeof(uint16_t);
} }
if (source_type == PrimitiveType::kQuadList && if (source_type == PrimitiveType::kQuadList &&
FLAGS_d3d12_convert_quads_to_triangles) { cvars::d3d12_convert_quads_to_triangles) {
index_count_out = (index_count >> 2) * 6; index_count_out = (index_count >> 2) * 6;
return static_ib_gpu_address_ + kStaticIBQuadOffset * sizeof(uint16_t); return static_ib_gpu_address_ + kStaticIBQuadOffset * sizeof(uint16_t);
} }

View File

@ -9,13 +9,12 @@
#include "xenia/gpu/d3d12/render_target_cache.h" #include "xenia/gpu/d3d12/render_target_cache.h"
#include <gflags/gflags.h>
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/base/memory.h" #include "xenia/base/memory.h"
@ -27,12 +26,14 @@
DEFINE_bool(d3d12_16bit_rtv_full_range, true, DEFINE_bool(d3d12_16bit_rtv_full_range, true,
"Use full -32...32 range for RG16 and RGBA16 render targets " "Use full -32...32 range for RG16 and RGBA16 render targets "
"(at the expense of blending correctness) without ROV."); "(at the expense of blending correctness) without ROV.",
"D3D12");
DEFINE_bool(d3d12_resolution_scale_resolve_edge_clamp, true, DEFINE_bool(d3d12_resolution_scale_resolve_edge_clamp, true,
"When using resolution scale, apply the hack that duplicates the " "When using resolution scale, apply the hack that duplicates the "
"right/lower subpixel in the left and top sides of render target " "right/lower subpixel in the left and top sides of render target "
"resolve areas to eliminate the gap caused by half-pixel offset " "resolve areas to eliminate the gap caused by half-pixel offset "
"(this is necessary for certain games like GTA IV to work)."); "(this is necessary for certain games like GTA IV to work).",
"D3D12");
DECLARE_bool(d3d12_half_pixel_offset); DECLARE_bool(d3d12_half_pixel_offset);
namespace xe { namespace xe {
@ -1303,7 +1304,7 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
// there on the guest side. // there on the guest side.
// http://www.students.science.uu.nl/~3220516/advancedgraphics/papers/inferred_lighting.pdf // http://www.students.science.uu.nl/~3220516/advancedgraphics/papers/inferred_lighting.pdf
if (command_processor_->IsROVUsedForEDRAM() || if (command_processor_->IsROVUsedForEDRAM() ||
FLAGS_d3d12_16bit_rtv_full_range) { cvars::d3d12_16bit_rtv_full_range) {
dest_exp_bias += 5; dest_exp_bias += 5;
} }
} }
@ -1340,8 +1341,9 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
// sides of the screen caused by half-pixel offset becoming whole pixel offset // sides of the screen caused by half-pixel offset becoming whole pixel offset
// with scaled rendering resolution. // with scaled rendering resolution.
bool resolution_scale_edge_clamp = bool resolution_scale_edge_clamp =
resolution_scale_2x_ && FLAGS_d3d12_resolution_scale_resolve_edge_clamp && resolution_scale_2x_ &&
FLAGS_d3d12_half_pixel_offset && cvars::d3d12_resolution_scale_resolve_edge_clamp &&
cvars::d3d12_half_pixel_offset &&
!(regs[XE_GPU_REG_PA_SU_VTX_CNTL].u32 & 0x1); !(regs[XE_GPU_REG_PA_SU_VTX_CNTL].u32 & 0x1);
if (sample_select <= xenos::CopySampleSelect::k3 && if (sample_select <= xenos::CopySampleSelect::k3 &&
src_texture_format == dest_format && dest_exp_bias == 0) { src_texture_format == dest_format && dest_exp_bias == 0) {

View File

@ -10,10 +10,9 @@
#ifndef XENIA_GPU_D3D12_RENDER_TARGET_CACHE_H_ #ifndef XENIA_GPU_D3D12_RENDER_TARGET_CACHE_H_
#define XENIA_GPU_D3D12_RENDER_TARGET_CACHE_H_ #define XENIA_GPU_D3D12_RENDER_TARGET_CACHE_H_
#include <gflags/gflags.h>
#include <unordered_map> #include <unordered_map>
#include "xenia/base/cvar.h"
#include "xenia/gpu/d3d12/d3d12_shader.h" #include "xenia/gpu/d3d12/d3d12_shader.h"
#include "xenia/gpu/d3d12/shared_memory.h" #include "xenia/gpu/d3d12/shared_memory.h"
#include "xenia/gpu/d3d12/texture_cache.h" #include "xenia/gpu/d3d12/texture_cache.h"

View File

@ -9,12 +9,11 @@
#include "xenia/gpu/d3d12/shared_memory.h" #include "xenia/gpu/d3d12/shared_memory.h"
#include <gflags/gflags.h>
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/base/memory.h" #include "xenia/base/memory.h"
@ -26,7 +25,8 @@ DEFINE_bool(d3d12_tiled_shared_memory, true,
"Enable tiled resources for shared memory emulation. Disabling " "Enable tiled resources for shared memory emulation. Disabling "
"them greatly increases video memory usage - a 512 MB buffer is " "them greatly increases video memory usage - a 512 MB buffer is "
"created - but allows graphics debuggers that don't support tiled " "created - but allows graphics debuggers that don't support tiled "
"resources to work."); "resources to work.",
"D3D12");
namespace xe { namespace xe {
namespace gpu { namespace gpu {
@ -453,7 +453,7 @@ void SharedMemory::RangeWrittenByGPU(uint32_t start, uint32_t length) {
} }
bool SharedMemory::AreTiledResourcesUsed() const { bool SharedMemory::AreTiledResourcesUsed() const {
if (!FLAGS_d3d12_tiled_shared_memory) { if (!cvars::d3d12_tiled_shared_memory) {
return false; return false;
} }
auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider(); auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider();

View File

@ -9,7 +9,6 @@
#include "xenia/gpu/d3d12/texture_cache.h" #include "xenia/gpu/d3d12/texture_cache.h"
#include <gflags/gflags.h>
#include "third_party/xxhash/xxhash.h" #include "third_party/xxhash/xxhash.h"
#include <algorithm> #include <algorithm>
@ -17,6 +16,7 @@
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/clock.h" #include "xenia/base/clock.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/base/profiling.h" #include "xenia/base/profiling.h"
@ -27,20 +27,24 @@
DEFINE_int32(d3d12_resolution_scale, 1, DEFINE_int32(d3d12_resolution_scale, 1,
"Scale of rendering width and height (currently only 1 and 2 " "Scale of rendering width and height (currently only 1 and 2 "
"are available)."); "are available).",
"D3D12");
DEFINE_int32(d3d12_texture_cache_limit_soft, 384, DEFINE_int32(d3d12_texture_cache_limit_soft, 384,
"Maximum host texture memory usage (in megabytes) above which old " "Maximum host texture memory usage (in megabytes) above which old "
"textures will be destroyed (lifetime configured with " "textures will be destroyed (lifetime configured with "
"d3d12_texture_cache_limit_soft_lifetime). If using 2x resolution " "d3d12_texture_cache_limit_soft_lifetime). If using 2x resolution "
"scale, 1.25x of this is used."); "scale, 1.25x of this is used.",
"D3D12");
DEFINE_int32(d3d12_texture_cache_limit_soft_lifetime, 30, DEFINE_int32(d3d12_texture_cache_limit_soft_lifetime, 30,
"Seconds a texture should be unused to be considered old enough " "Seconds a texture should be unused to be considered old enough "
"to be deleted if texture memory usage exceeds " "to be deleted if texture memory usage exceeds "
"d3d12_texture_cache_limit_soft."); "d3d12_texture_cache_limit_soft.",
"D3D12");
DEFINE_int32(d3d12_texture_cache_limit_hard, 768, DEFINE_int32(d3d12_texture_cache_limit_hard, 768,
"Maximum host texture memory usage (in megabytes) above which " "Maximum host texture memory usage (in megabytes) above which "
"textures will be destroyed as soon as possible. If using 2x " "textures will be destroyed as soon as possible. If using 2x "
"resolution scale, 1.25x of this is used."); "resolution scale, 1.25x of this is used.",
"D3D12");
namespace xe { namespace xe {
namespace gpu { namespace gpu {
@ -484,7 +488,7 @@ bool TextureCache::Initialize() {
// Try to create the tiled buffer 2x resolution scaling. // Try to create the tiled buffer 2x resolution scaling.
// Not currently supported with the RTV/DSV output path for various reasons. // Not currently supported with the RTV/DSV output path for various reasons.
// As of November 27th, 2018, PIX doesn't support tiled buffers. // As of November 27th, 2018, PIX doesn't support tiled buffers.
if (FLAGS_d3d12_resolution_scale >= 2 && if (cvars::d3d12_resolution_scale >= 2 &&
command_processor_->IsROVUsedForEDRAM() && command_processor_->IsROVUsedForEDRAM() &&
provider->GetTiledResourcesTier() >= 1 && provider->GetTiledResourcesTier() >= 1 &&
provider->GetGraphicsAnalysis() == nullptr && provider->GetGraphicsAnalysis() == nullptr &&
@ -738,14 +742,14 @@ void TextureCache::BeginFrame() {
// If memory usage is too high, destroy unused textures. // If memory usage is too high, destroy unused textures.
uint64_t last_completed_frame = uint64_t last_completed_frame =
command_processor_->GetD3D12Context()->GetLastCompletedFrame(); command_processor_->GetD3D12Context()->GetLastCompletedFrame();
uint32_t limit_soft_mb = FLAGS_d3d12_texture_cache_limit_soft; uint32_t limit_soft_mb = cvars::d3d12_texture_cache_limit_soft;
uint32_t limit_hard_mb = FLAGS_d3d12_texture_cache_limit_hard; uint32_t limit_hard_mb = cvars::d3d12_texture_cache_limit_hard;
if (IsResolutionScale2X()) { if (IsResolutionScale2X()) {
limit_soft_mb += limit_soft_mb >> 2; limit_soft_mb += limit_soft_mb >> 2;
limit_hard_mb += limit_hard_mb >> 2; limit_hard_mb += limit_hard_mb >> 2;
} }
uint32_t limit_soft_lifetime = uint32_t limit_soft_lifetime =
std::max(FLAGS_d3d12_texture_cache_limit_soft_lifetime, 0) * 1000; std::max(cvars::d3d12_texture_cache_limit_soft_lifetime, 0) * 1000;
bool destroyed_any = false; bool destroyed_any = false;
while (texture_used_first_ != nullptr) { while (texture_used_first_ != nullptr) {
uint64_t total_size_mb = textures_total_size_ >> 20; uint64_t total_size_mb = textures_total_size_ >> 20;

View File

@ -9,8 +9,6 @@
#include "xenia/gpu/dxbc_shader_translator.h" #include "xenia/gpu/dxbc_shader_translator.h"
#include <gflags/gflags.h>
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <memory> #include <memory>
@ -19,6 +17,7 @@
#include "third_party/dxbc/d3d12TokenizedProgramFormat.hpp" #include "third_party/dxbc/d3d12TokenizedProgramFormat.hpp"
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
DEFINE_bool(dxbc_switch, true, DEFINE_bool(dxbc_switch, true,
"Use switch rather than if for flow control. Turning this off or " "Use switch rather than if for flow control. Turning this off or "
@ -27,10 +26,12 @@ DEFINE_bool(dxbc_switch, true,
"Halo 3 appears to crash when if is used for flow control " "Halo 3 appears to crash when if is used for flow control "
"(possibly the shader compiler tries to flatten them). On Intel " "(possibly the shader compiler tries to flatten them). On Intel "
"HD Graphics, this is ignored because of a crash with the switch " "HD Graphics, this is ignored because of a crash with the switch "
"instruction."); "instruction.",
"D3D12");
DEFINE_bool(dxbc_source_map, false, DEFINE_bool(dxbc_source_map, false,
"Disassemble Xenos instructions as comments in the resulting DXBC " "Disassemble Xenos instructions as comments in the resulting DXBC "
"for debugging."); "for debugging.",
"D3D12");
namespace xe { namespace xe {
namespace gpu { namespace gpu {
@ -182,7 +183,7 @@ void DxbcShaderTranslator::Reset() {
bool DxbcShaderTranslator::UseSwitchForControlFlow() const { bool DxbcShaderTranslator::UseSwitchForControlFlow() const {
// Xenia crashes on Intel HD Graphics 4000 with switch. // Xenia crashes on Intel HD Graphics 4000 with switch.
return FLAGS_dxbc_switch && vendor_id_ != 0x8086; return cvars::dxbc_switch && vendor_id_ != 0x8086;
} }
uint32_t DxbcShaderTranslator::PushSystemTemp(uint32_t zero_mask, uint32_t DxbcShaderTranslator::PushSystemTemp(uint32_t zero_mask,
@ -1861,7 +1862,7 @@ std::vector<uint8_t> DxbcShaderTranslator::CompleteTranslation() {
} }
void DxbcShaderTranslator::EmitInstructionDisassembly() { void DxbcShaderTranslator::EmitInstructionDisassembly() {
if (!FLAGS_dxbc_source_map) { if (!cvars::dxbc_source_map) {
return; return;
} }
@ -3019,7 +3020,7 @@ void DxbcShaderTranslator::ProcessLabel(uint32_t cf_index) {
void DxbcShaderTranslator::ProcessExecInstructionBegin( void DxbcShaderTranslator::ProcessExecInstructionBegin(
const ParsedExecInstruction& instr) { const ParsedExecInstruction& instr) {
if (FLAGS_dxbc_source_map) { if (cvars::dxbc_source_map) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
// Will be emitted by UpdateExecConditionals. // Will be emitted by UpdateExecConditionals.
@ -3070,7 +3071,7 @@ void DxbcShaderTranslator::ProcessLoopStartInstruction(
// Loop control is outside execs - actually close the last exec. // Loop control is outside execs - actually close the last exec.
CloseExecConditionals(); CloseExecConditionals();
if (FLAGS_dxbc_source_map) { if (cvars::dxbc_source_map) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
EmitInstructionDisassembly(); EmitInstructionDisassembly();
@ -3182,7 +3183,7 @@ void DxbcShaderTranslator::ProcessLoopEndInstruction(
// Loop control is outside execs - actually close the last exec. // Loop control is outside execs - actually close the last exec.
CloseExecConditionals(); CloseExecConditionals();
if (FLAGS_dxbc_source_map) { if (cvars::dxbc_source_map) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
EmitInstructionDisassembly(); EmitInstructionDisassembly();
@ -3340,7 +3341,7 @@ void DxbcShaderTranslator::ProcessLoopEndInstruction(
void DxbcShaderTranslator::ProcessJumpInstruction( void DxbcShaderTranslator::ProcessJumpInstruction(
const ParsedJumpInstruction& instr) { const ParsedJumpInstruction& instr) {
if (FLAGS_dxbc_source_map) { if (cvars::dxbc_source_map) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
// Will be emitted by UpdateExecConditionals. // Will be emitted by UpdateExecConditionals.
@ -3369,7 +3370,7 @@ void DxbcShaderTranslator::ProcessJumpInstruction(
void DxbcShaderTranslator::ProcessAllocInstruction( void DxbcShaderTranslator::ProcessAllocInstruction(
const ParsedAllocInstruction& instr) { const ParsedAllocInstruction& instr) {
if (FLAGS_dxbc_source_map) { if (cvars::dxbc_source_map) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
EmitInstructionDisassembly(); EmitInstructionDisassembly();

View File

@ -10,12 +10,11 @@
#ifndef XENIA_GPU_DXBC_SHADER_TRANSLATOR_H_ #ifndef XENIA_GPU_DXBC_SHADER_TRANSLATOR_H_
#define XENIA_GPU_DXBC_SHADER_TRANSLATOR_H_ #define XENIA_GPU_DXBC_SHADER_TRANSLATOR_H_
#include <gflags/gflags.h>
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <vector> #include <vector>
#include "xenia/base/cvar.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/base/string_buffer.h" #include "xenia/base/string_buffer.h"
#include "xenia/gpu/shader_translator.h" #include "xenia/gpu/shader_translator.h"

View File

@ -2425,7 +2425,7 @@ void DxbcShaderTranslator::ProcessAluInstruction(
return; return;
} }
if (FLAGS_dxbc_source_map) { if (cvars::dxbc_source_map) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
// Will be emitted by UpdateInstructionPredication. // Will be emitted by UpdateInstructionPredication.

View File

@ -322,7 +322,7 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction(
} }
uint32_t result_write_mask = (1 << result_component_count) - 1; uint32_t result_write_mask = (1 << result_component_count) - 1;
if (FLAGS_dxbc_source_map) { if (cvars::dxbc_source_map) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
// Will be emitted by UpdateInstructionPredication. // Will be emitted by UpdateInstructionPredication.
@ -1162,7 +1162,7 @@ void DxbcShaderTranslator::ArrayCoordToCubeDirection(uint32_t reg) {
void DxbcShaderTranslator::ProcessTextureFetchInstruction( void DxbcShaderTranslator::ProcessTextureFetchInstruction(
const ParsedTextureFetchInstruction& instr) { const ParsedTextureFetchInstruction& instr) {
if (FLAGS_dxbc_source_map) { if (cvars::dxbc_source_map) {
instruction_disassembly_buffer_.Reset(); instruction_disassembly_buffer_.Reset();
instr.Disassemble(&instruction_disassembly_buffer_); instr.Disassemble(&instruction_disassembly_buffer_);
// Will be emitted later explicitly or by UpdateInstructionPredication. // Will be emitted later explicitly or by UpdateInstructionPredication.

View File

@ -10,10 +10,10 @@
#include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/gpu_flags.h"
DEFINE_string(trace_gpu_prefix, "scratch/gpu/", DEFINE_string(trace_gpu_prefix, "scratch/gpu/",
"Prefix path for GPU trace files."); "Prefix path for GPU trace files.", "GPU");
DEFINE_bool(trace_gpu_stream, false, "Trace all GPU packets."); DEFINE_bool(trace_gpu_stream, false, "Trace all GPU packets.", "GPU");
DEFINE_string(dump_shaders, "", DEFINE_string(dump_shaders, "",
"Path to write GPU shaders to as they are compiled."); "Path to write GPU shaders to as they are compiled.", "GPU");
DEFINE_bool(vsync, true, "Enable VSYNC."); DEFINE_bool(vsync, true, "Enable VSYNC.", "GPU");

View File

@ -9,8 +9,7 @@
#ifndef XENIA_GPU_GPU_FLAGS_H_ #ifndef XENIA_GPU_GPU_FLAGS_H_
#define XENIA_GPU_GPU_FLAGS_H_ #define XENIA_GPU_GPU_FLAGS_H_
#include "xenia/base/cvar.h"
#include <gflags/gflags.h>
DECLARE_string(trace_gpu_prefix); DECLARE_string(trace_gpu_prefix);
DECLARE_bool(trace_gpu_stream); DECLARE_bool(trace_gpu_stream);

View File

@ -113,7 +113,7 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor,
vsync_worker_running_ = true; vsync_worker_running_ = true;
vsync_worker_thread_ = kernel::object_ref<kernel::XHostThread>( vsync_worker_thread_ = kernel::object_ref<kernel::XHostThread>(
new kernel::XHostThread(kernel_state_, 128 * 1024, 0, [this]() { new kernel::XHostThread(kernel_state_, 128 * 1024, 0, [this]() {
uint64_t vsync_duration = FLAGS_vsync ? 16 : 1; uint64_t vsync_duration = cvars::vsync ? 16 : 1;
uint64_t last_frame_time = Clock::QueryGuestTickCount(); uint64_t last_frame_time = Clock::QueryGuestTickCount();
while (vsync_worker_running_) { while (vsync_worker_running_) {
uint64_t current_time = Clock::QueryGuestTickCount(); uint64_t current_time = Clock::QueryGuestTickCount();
@ -132,7 +132,7 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor,
vsync_worker_thread_->set_name("GraphicsSystem Vsync"); vsync_worker_thread_->set_name("GraphicsSystem Vsync");
vsync_worker_thread_->Create(); vsync_worker_thread_->Create();
if (FLAGS_trace_gpu_stream) { if (cvars::trace_gpu_stream) {
BeginTracing(); BeginTracing();
} }
@ -270,11 +270,12 @@ void GraphicsSystem::ClearCaches() {
} }
void GraphicsSystem::RequestFrameTrace() { void GraphicsSystem::RequestFrameTrace() {
command_processor_->RequestFrameTrace(xe::to_wstring(FLAGS_trace_gpu_prefix)); command_processor_->RequestFrameTrace(
xe::to_wstring(cvars::trace_gpu_prefix));
} }
void GraphicsSystem::BeginTracing() { void GraphicsSystem::BeginTracing() {
command_processor_->BeginTracing(xe::to_wstring(FLAGS_trace_gpu_prefix)); command_processor_->BeginTracing(xe::to_wstring(cvars::trace_gpu_prefix));
} }
void GraphicsSystem::EndTracing() { command_processor_->EndTracing(); } void GraphicsSystem::EndTracing() { command_processor_->EndTracing(); }

View File

@ -15,7 +15,4 @@ project("xenia-gpu-null")
}) })
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
local_platform_files() local_platform_files()

View File

@ -20,7 +20,6 @@ project("xenia-gpu")
}) })
includedirs({ includedirs({
project_root.."/third_party/spirv-tools/external/include", project_root.."/third_party/spirv-tools/external/include",
project_root.."/third_party/gflags/src",
}) })
local_platform_files() local_platform_files()
-- local_platform_files("spirv") -- local_platform_files("spirv")
@ -33,7 +32,6 @@ project("xenia-gpu-shader-compiler")
language("C++") language("C++")
links({ links({
"dxbc", "dxbc",
"gflags",
"glslang-spirv", "glslang-spirv",
"spirv-tools", "spirv-tools",
"xenia-base", "xenia-base",
@ -42,9 +40,6 @@ project("xenia-gpu-shader-compiler")
}) })
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
files({ files({
"shader_compiler_main.cc", "shader_compiler_main.cc",
"../base/main_"..platform_suffix..".cc", "../base/main_"..platform_suffix..".cc",
@ -56,7 +51,6 @@ project("xenia-gpu-shader-compiler")
if not os.isfile(user_file) then if not os.isfile(user_file) then
debugdir(project_root) debugdir(project_root)
debugargs({ debugargs({
"--flagfile=scratch/flags.txt",
"2>&1", "2>&1",
"1>scratch/stdout-shader-compiler.txt", "1>scratch/stdout-shader-compiler.txt",
}) })

View File

@ -7,13 +7,12 @@
****************************************************************************** ******************************************************************************
*/ */
#include <gflags/gflags.h>
#include <cinttypes> #include <cinttypes>
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <vector> #include <vector>
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/main.h" #include "xenia/base/main.h"
#include "xenia/base/platform.h" #include "xenia/base/platform.h"
@ -24,46 +23,51 @@
#include "xenia/gpu/spirv_shader_translator.h" #include "xenia/gpu/spirv_shader_translator.h"
#include "xenia/ui/spirv/spirv_disassembler.h" #include "xenia/ui/spirv/spirv_disassembler.h"
<<<<<<< HEAD
// For D3DDisassemble: // For D3DDisassemble:
#if XE_PLATFORM_WIN32 #if XE_PLATFORM_WIN32
#include "xenia/ui/d3d12/d3d12_api.h" #include "xenia/ui/d3d12/d3d12_api.h"
#endif // XE_PLATFORM_WIN32 #endif // XE_PLATFORM_WIN32
DEFINE_string(shader_input, "", "Input shader binary file path."); DEFINE_string(shader_input, "", "Input shader binary file path.", "GPU");
DEFINE_string(shader_input_type, "", DEFINE_string(shader_input_type, "",
"'vs', 'ps', or unspecified to infer from the given filename."); "'vs', 'ps', or unspecified to infer from the given filename.",
DEFINE_string(shader_output, "", "Output shader file path."); "GPU");
DEFINE_string(shader_output, "", "Output shader file path.", "GPU");
DEFINE_string(shader_output_type, "ucode", DEFINE_string(shader_output_type, "ucode",
"Translator to use: [ucode, glsl45, spirv, spirvtext, dxbc]."); "Translator to use: [ucode, glsl45, spirv, spirvtext, dxbc].",
"GPU");
DEFINE_string(shader_output_patch, "", DEFINE_string(shader_output_patch, "",
"Tessellation patch type in the generated tessellation " "Tessellation patch type in the generated tessellation "
"evaluation (domain) shader, or unspecified to produce a vertex " "evaluation (domain) shader, or unspecified to produce a vertex "
"shader: [line, triangle, quad]."); "shader: [line, triangle, quad].",
"GPU");
DEFINE_bool(shader_output_dxbc_rov, false, DEFINE_bool(shader_output_dxbc_rov, false,
"Output ROV-based output-merger code in DXBC pixel shaders."); "Output ROV-based output-merger code in DXBC pixel shaders.",
"GPU");
namespace xe { namespace xe {
namespace gpu { namespace gpu {
int shader_compiler_main(const std::vector<std::wstring>& args) { int shader_compiler_main(const std::vector<std::wstring>& args) {
ShaderType shader_type; ShaderType shader_type;
if (!FLAGS_shader_input_type.empty()) { if (!cvars::shader_input_type.empty()) {
if (FLAGS_shader_input_type == "vs") { if (cvars::shader_input_type == "vs") {
shader_type = ShaderType::kVertex; shader_type = ShaderType::kVertex;
} else if (FLAGS_shader_input_type == "ps") { } else if (cvars::shader_input_type == "ps") {
shader_type = ShaderType::kPixel; shader_type = ShaderType::kPixel;
} else { } else {
XELOGE("Invalid --shader_input_type; must be 'vs' or 'ps'."); XELOGE("Invalid --shader_input_type; must be 'vs' or 'ps'.");
return 1; return 1;
} }
} else { } else {
auto last_dot = FLAGS_shader_input.find_last_of('.'); auto last_dot = cvars::shader_input.find_last_of('.');
bool valid_type = false; bool valid_type = false;
if (last_dot != std::string::npos) { if (last_dot != std::string::npos) {
if (FLAGS_shader_input.substr(last_dot) == ".vs") { if (cvars::shader_input.substr(last_dot) == ".vs") {
shader_type = ShaderType::kVertex; shader_type = ShaderType::kVertex;
valid_type = true; valid_type = true;
} else if (FLAGS_shader_input.substr(last_dot) == ".ps") { } else if (cvars::shader_input.substr(last_dot) == ".ps") {
shader_type = ShaderType::kPixel; shader_type = ShaderType::kPixel;
valid_type = true; valid_type = true;
} }
@ -76,9 +80,9 @@ int shader_compiler_main(const std::vector<std::wstring>& args) {
} }
} }
auto input_file = fopen(FLAGS_shader_input.c_str(), "rb"); auto input_file = fopen(cvars::shader_input.c_str(), "rb");
if (!input_file) { if (!input_file) {
XELOGE("Unable to open input file: %s", FLAGS_shader_input.c_str()); XELOGE("Unable to open input file: %s", cvars::shader_input.c_str());
return 1; return 1;
} }
fseek(input_file, 0, SEEK_END); fseek(input_file, 0, SEEK_END);
@ -89,7 +93,7 @@ int shader_compiler_main(const std::vector<std::wstring>& args) {
fclose(input_file); fclose(input_file);
XELOGI("Opened %s as a %s shader, %" PRId64 " words (%" PRId64 " bytes).", XELOGI("Opened %s as a %s shader, %" PRId64 " words (%" PRId64 " bytes).",
FLAGS_shader_input.c_str(), cvars::shader_input.c_str(),
shader_type == ShaderType::kVertex ? "vertex" : "pixel", shader_type == ShaderType::kVertex ? "vertex" : "pixel",
ucode_dwords.size(), ucode_dwords.size() * 4); ucode_dwords.size(), ucode_dwords.size() * 4);
@ -99,26 +103,26 @@ int shader_compiler_main(const std::vector<std::wstring>& args) {
shader_type, ucode_data_hash, ucode_dwords.data(), ucode_dwords.size()); shader_type, ucode_data_hash, ucode_dwords.data(), ucode_dwords.size());
std::unique_ptr<ShaderTranslator> translator; std::unique_ptr<ShaderTranslator> translator;
if (FLAGS_shader_output_type == "spirv" || if (cvars::shader_output_type == "spirv" ||
FLAGS_shader_output_type == "spirvtext") { cvars::shader_output_type == "spirvtext") {
translator = std::make_unique<SpirvShaderTranslator>(); translator = std::make_unique<SpirvShaderTranslator>();
} else if (FLAGS_shader_output_type == "glsl45") { } else if (cvars::shader_output_type == "glsl45") {
translator = std::make_unique<GlslShaderTranslator>( translator = std::make_unique<GlslShaderTranslator>(
GlslShaderTranslator::Dialect::kGL45); GlslShaderTranslator::Dialect::kGL45);
} else if (FLAGS_shader_output_type == "dxbc") { } else if (cvars::shader_output_type == "dxbc") {
translator = translator = std::make_unique<DxbcShaderTranslator>(
std::make_unique<DxbcShaderTranslator>(0, FLAGS_shader_output_dxbc_rov); 0, cvars::shader_output_dxbc_rov);
} else { } else {
translator = std::make_unique<UcodeShaderTranslator>(); translator = std::make_unique<UcodeShaderTranslator>();
} }
PrimitiveType patch_primitive_type = PrimitiveType::kNone; PrimitiveType patch_primitive_type = PrimitiveType::kNone;
if (shader_type == ShaderType::kVertex) { if (shader_type == ShaderType::kVertex) {
if (FLAGS_shader_output_patch == "line") { if (cvars::shader_output_patch == "line") {
patch_primitive_type = PrimitiveType::kLinePatch; patch_primitive_type = PrimitiveType::kLinePatch;
} else if (FLAGS_shader_output_patch == "triangle") { } else if (cvars::shader_output_patch == "triangle") {
patch_primitive_type = PrimitiveType::kTrianglePatch; patch_primitive_type = PrimitiveType::kTrianglePatch;
} else if (FLAGS_shader_output_patch == "quad") { } else if (cvars::shader_output_patch == "quad") {
patch_primitive_type = PrimitiveType::kQuadPatch; patch_primitive_type = PrimitiveType::kQuadPatch;
} }
} }
@ -129,7 +133,7 @@ int shader_compiler_main(const std::vector<std::wstring>& args) {
size_t source_data_size = shader->translated_binary().size(); size_t source_data_size = shader->translated_binary().size();
std::unique_ptr<xe::ui::spirv::SpirvDisassembler::Result> spirv_disasm_result; std::unique_ptr<xe::ui::spirv::SpirvDisassembler::Result> spirv_disasm_result;
if (FLAGS_shader_output_type == "spirvtext") { if (cvars::shader_output_type == "spirvtext") {
// Disassemble SPIRV. // Disassemble SPIRV.
spirv_disasm_result = xe::ui::spirv::SpirvDisassembler().Disassemble( spirv_disasm_result = xe::ui::spirv::SpirvDisassembler().Disassemble(
reinterpret_cast<const uint32_t*>(source_data), source_data_size / 4); reinterpret_cast<const uint32_t*>(source_data), source_data_size / 4);
@ -138,7 +142,7 @@ int shader_compiler_main(const std::vector<std::wstring>& args) {
} }
#if XE_PLATFORM_WIN32 #if XE_PLATFORM_WIN32
ID3DBlob* dxbc_disasm_blob = nullptr; ID3DBlob* dxbc_disasm_blob = nullptr;
if (FLAGS_shader_output_type == "dxbc") { if (cvars::shader_output_type == "dxbc") {
HMODULE d3d_compiler = LoadLibrary(L"D3DCompiler_47.dll"); HMODULE d3d_compiler = LoadLibrary(L"D3DCompiler_47.dll");
if (d3d_compiler != nullptr) { if (d3d_compiler != nullptr) {
pD3DDisassemble d3d_disassemble = pD3DDisassemble d3d_disassemble =
@ -158,8 +162,8 @@ int shader_compiler_main(const std::vector<std::wstring>& args) {
} }
#endif // XE_PLATFORM_WIN32 #endif // XE_PLATFORM_WIN32
if (!FLAGS_shader_output.empty()) { if (!cvars::shader_output.empty()) {
auto output_file = fopen(FLAGS_shader_output.c_str(), "wb"); auto output_file = fopen(cvars::shader_output.c_str(), "wb");
fwrite(source_data, 1, source_data_size, output_file); fwrite(source_data, 1, source_data_size, output_file);
fclose(output_file); fclose(output_file);
} }

View File

@ -9,19 +9,20 @@
#include "xenia/gpu/spirv_shader_translator.h" #include "xenia/gpu/spirv_shader_translator.h"
#include <gflags/gflags.h>
#include <algorithm> #include <algorithm>
#include <cfloat> #include <cfloat>
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
#include <vector> #include <vector>
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
DEFINE_bool(spv_validate, false, "Validate SPIR-V shaders after generation"); DEFINE_bool(spv_validate, false, "Validate SPIR-V shaders after generation",
DEFINE_bool(spv_disasm, false, "Disassemble SPIR-V shaders after generation"); "GPU");
DEFINE_bool(spv_disasm, false, "Disassemble SPIR-V shaders after generation",
"GPU");
namespace xe { namespace xe {
namespace gpu { namespace gpu {
@ -666,7 +667,7 @@ std::vector<uint8_t> SpirvShaderTranslator::CompleteTranslation() {
void SpirvShaderTranslator::PostTranslation(Shader* shader) { void SpirvShaderTranslator::PostTranslation(Shader* shader) {
// Validation. // Validation.
if (FLAGS_spv_validate) { if (cvars::spv_validate) {
auto validation = validator_.Validate( auto validation = validator_.Validate(
reinterpret_cast<const uint32_t*>(shader->translated_binary().data()), reinterpret_cast<const uint32_t*>(shader->translated_binary().data()),
shader->translated_binary().size() / sizeof(uint32_t)); shader->translated_binary().size() / sizeof(uint32_t));
@ -676,7 +677,7 @@ void SpirvShaderTranslator::PostTranslation(Shader* shader) {
} }
} }
if (FLAGS_spv_disasm) { if (cvars::spv_disasm) {
// TODO(benvanik): only if needed? could be slowish. // TODO(benvanik): only if needed? could be slowish.
auto disasm = disassembler_.Disassemble( auto disasm = disassembler_.Disassemble(
reinterpret_cast<const uint32_t*>(shader->translated_binary().data()), reinterpret_cast<const uint32_t*>(shader->translated_binary().data()),

View File

@ -7,13 +7,12 @@
****************************************************************************** ******************************************************************************
*/ */
#include <gflags/gflags.h> #include "xenia/base/cvar.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/gpu/texture_info.h" #include "xenia/gpu/texture_info.h"
DEFINE_bool(texture_dump, false, "Dump textures to DDS"); DEFINE_bool(texture_dump, false, "Dump textures to DDS", "GPU");
namespace xe { namespace xe {
namespace gpu { namespace gpu {

View File

@ -9,8 +9,6 @@
#include "xenia/gpu/trace_dump.h" #include "xenia/gpu/trace_dump.h"
#include <gflags/gflags.h>
#include "third_party/stb/stb_image_write.h" #include "third_party/stb/stb_image_write.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/profiling.h" #include "xenia/base/profiling.h"
@ -28,8 +26,9 @@
#undef _CRT_NONSTDC_NO_DEPRECATE #undef _CRT_NONSTDC_NO_DEPRECATE
#include "third_party/stb/stb_image_write.h" #include "third_party/stb/stb_image_write.h"
DEFINE_string(target_trace_file, "", "Specifies the trace file to load."); DEFINE_string(target_trace_file, "", "Specifies the trace file to load.",
DEFINE_string(trace_dump_path, "", "Output path for dumped files."); "GPU");
DEFINE_string(trace_dump_path, "", "Output path for dumped files.", "GPU");
namespace xe { namespace xe {
namespace gpu { namespace gpu {
@ -44,11 +43,11 @@ int TraceDump::Main(const std::vector<std::wstring>& args) {
// Grab path from the flag or unnamed argument. // Grab path from the flag or unnamed argument.
std::wstring path; std::wstring path;
std::wstring output_path; std::wstring output_path;
if (!FLAGS_target_trace_file.empty()) { if (!cvars::target_trace_file.empty()) {
// Passed as a named argument. // Passed as a named argument.
// TODO(benvanik): find something better than gflags that supports // TODO(benvanik): find something better than gflags that supports
// unicode. // unicode.
path = xe::to_wstring(FLAGS_target_trace_file); path = xe::to_wstring(cvars::target_trace_file);
} else if (args.size() >= 2) { } else if (args.size() >= 2) {
// Passed as an unnamed argument. // Passed as an unnamed argument.
path = args[1]; path = args[1];
@ -79,7 +78,7 @@ int TraceDump::Main(const std::vector<std::wstring>& args) {
// Root file name for outputs. // Root file name for outputs.
if (output_path.empty()) { if (output_path.empty()) {
base_output_path_ = base_output_path_ =
xe::fix_path_separators(xe::to_wstring(FLAGS_trace_dump_path)); xe::fix_path_separators(xe::to_wstring(cvars::trace_dump_path));
std::wstring output_name = std::wstring output_name =
xe::find_name_from_path(xe::fix_path_separators(path)); xe::find_name_from_path(xe::fix_path_separators(path));

View File

@ -9,8 +9,6 @@
#include "xenia/gpu/trace_viewer.h" #include "xenia/gpu/trace_viewer.h"
#include <gflags/gflags.h>
#include <cinttypes> #include <cinttypes>
#include "third_party/half/include/half.hpp" #include "third_party/half/include/half.hpp"
@ -32,7 +30,8 @@
#include "xenia/ui/window.h" #include "xenia/ui/window.h"
#include "xenia/xbox.h" #include "xenia/xbox.h"
DEFINE_string(target_trace_file, "", "Specifies the trace file to load."); DEFINE_string(target_trace_file, "", "Specifies the trace file to load.",
"GPU");
namespace xe { namespace xe {
namespace gpu { namespace gpu {
@ -53,11 +52,11 @@ TraceViewer::~TraceViewer() = default;
int TraceViewer::Main(const std::vector<std::wstring>& args) { int TraceViewer::Main(const std::vector<std::wstring>& args) {
// Grab path from the flag or unnamed argument. // Grab path from the flag or unnamed argument.
std::wstring path; std::wstring path;
if (!FLAGS_target_trace_file.empty()) { if (!cvars::target_trace_file.empty()) {
// Passed as a named argument. // Passed as a named argument.
// TODO(benvanik): find something better than gflags that supports // TODO(benvanik): find something better than gflags that supports
// unicode. // unicode.
path = xe::to_wstring(FLAGS_target_trace_file); path = xe::to_wstring(cvars::target_trace_file);
} else if (args.size() >= 2) { } else if (args.size() >= 2) {
// Passed as an unnamed argument. // Passed as an unnamed argument.
path = args[1]; path = args[1];

View File

@ -347,7 +347,7 @@ VkPipeline PipelineCache::GetPipeline(const RenderState* render_state,
} }
// Dump shader disassembly. // Dump shader disassembly.
if (FLAGS_vulkan_dump_disasm) { if (cvars::vulkan_dump_disasm) {
if (device_->HasEnabledExtension(VK_AMD_SHADER_INFO_EXTENSION_NAME)) { if (device_->HasEnabledExtension(VK_AMD_SHADER_INFO_EXTENSION_NAME)) {
DumpShaderDisasmAMD(pipeline); DumpShaderDisasmAMD(pipeline);
} else if (device_->device_info().properties.vendorID == 0x10DE) { } else if (device_->device_info().properties.vendorID == 0x10DE) {
@ -387,8 +387,8 @@ bool PipelineCache::TranslateShader(VulkanShader* shader,
} }
// Dump shader files if desired. // Dump shader files if desired.
if (!FLAGS_dump_shaders.empty()) { if (!cvars::dump_shaders.empty()) {
shader->Dump(FLAGS_dump_shaders, "vk"); shader->Dump(cvars::dump_shaders, "vk");
} }
return shader->is_valid(); return shader->is_valid();
@ -1396,7 +1396,7 @@ PipelineCache::UpdateStatus PipelineCache::UpdateMultisampleState() {
// PA_SU_SC_MODE_CNTL MSAA_ENABLE (0x10000) // PA_SU_SC_MODE_CNTL MSAA_ENABLE (0x10000)
// If set, all samples will be sampled at set locations. Otherwise, they're // If set, all samples will be sampled at set locations. Otherwise, they're
// all sampled from the pixel center. // all sampled from the pixel center.
if (FLAGS_vulkan_native_msaa) { if (cvars::vulkan_native_msaa) {
auto msaa_num_samples = auto msaa_num_samples =
static_cast<MsaaSamples>((regs.rb_surface_info >> 16) & 0x3); static_cast<MsaaSamples>((regs.rb_surface_info >> 16) & 0x3);
switch (msaa_num_samples) { switch (msaa_num_samples) {

View File

@ -17,9 +17,6 @@ project("xenia-gpu-vulkan")
}) })
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
local_platform_files() local_platform_files()
files({ files({
"shaders/bin/*.h", "shaders/bin/*.h",
@ -34,7 +31,6 @@ project("xenia-gpu-vulkan-trace-viewer")
links({ links({
"aes_128", "aes_128",
"capstone", "capstone",
"gflags",
"glslang-spirv", "glslang-spirv",
"imgui", "imgui",
"libavcodec", "libavcodec",
@ -62,9 +58,6 @@ project("xenia-gpu-vulkan-trace-viewer")
}) })
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
files({ files({
"vulkan_trace_viewer_main.cc", "vulkan_trace_viewer_main.cc",
"../../base/main_"..platform_suffix..".cc", "../../base/main_"..platform_suffix..".cc",
@ -91,7 +84,6 @@ project("xenia-gpu-vulkan-trace-viewer")
if not os.isfile(user_file) then if not os.isfile(user_file) then
debugdir(project_root) debugdir(project_root)
debugargs({ debugargs({
"--flagfile=scratch/flags.txt",
"2>&1", "2>&1",
"1>scratch/stdout-trace-viewer.txt", "1>scratch/stdout-trace-viewer.txt",
}) })
@ -105,7 +97,6 @@ project("xenia-gpu-vulkan-trace-dump")
links({ links({
"aes_128", "aes_128",
"capstone", "capstone",
"gflags",
"glslang-spirv", "glslang-spirv",
"imgui", "imgui",
"libavcodec", "libavcodec",
@ -133,9 +124,6 @@ project("xenia-gpu-vulkan-trace-dump")
}) })
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
files({ files({
"vulkan_trace_dump_main.cc", "vulkan_trace_dump_main.cc",
"../../base/main_"..platform_suffix..".cc", "../../base/main_"..platform_suffix..".cc",
@ -156,7 +144,6 @@ project("xenia-gpu-vulkan-trace-dump")
if not os.isfile(user_file) then if not os.isfile(user_file) then
debugdir(project_root) debugdir(project_root)
debugargs({ debugargs({
"--flagfile=scratch/flags.txt",
"2>&1", "2>&1",
"1>scratch/stdout-trace-dump.txt", "1>scratch/stdout-trace-dump.txt",
}) })

View File

@ -194,7 +194,7 @@ VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) {
image_info.extent.depth = 1; image_info.extent.depth = 1;
image_info.mipLevels = 1; image_info.mipLevels = 1;
image_info.arrayLayers = 1; image_info.arrayLayers = 1;
if (FLAGS_vulkan_native_msaa) { if (cvars::vulkan_native_msaa) {
auto msaa_samples = static_cast<MsaaSamples>(key.msaa_samples); auto msaa_samples = static_cast<MsaaSamples>(key.msaa_samples);
switch (msaa_samples) { switch (msaa_samples) {
case MsaaSamples::k1X: case MsaaSamples::k1X:
@ -422,7 +422,7 @@ CachedRenderPass::~CachedRenderPass() {
VkResult CachedRenderPass::Initialize() { VkResult CachedRenderPass::Initialize() {
VkSampleCountFlagBits sample_count; VkSampleCountFlagBits sample_count;
if (FLAGS_vulkan_native_msaa) { if (cvars::vulkan_native_msaa) {
switch (config.surface_msaa) { switch (config.surface_msaa) {
case MsaaSamples::k1X: case MsaaSamples::k1X:
sample_count = VK_SAMPLE_COUNT_1_BIT; sample_count = VK_SAMPLE_COUNT_1_BIT;
@ -534,7 +534,7 @@ VkResult CachedRenderPass::Initialize() {
bool CachedRenderPass::IsCompatible( bool CachedRenderPass::IsCompatible(
const RenderConfiguration& desired_config) const { const RenderConfiguration& desired_config) const {
if (config.surface_msaa != desired_config.surface_msaa && if (config.surface_msaa != desired_config.surface_msaa &&
FLAGS_vulkan_native_msaa) { cvars::vulkan_native_msaa) {
return false; return false;
} }

View File

@ -1040,7 +1040,7 @@ bool TextureCache::UploadTexture(VkCommandBuffer command_buffer,
unpack_offset += ComputeMipStorage(src, mip); unpack_offset += ComputeMipStorage(src, mip);
} }
if (FLAGS_texture_dump) { if (cvars::texture_dump) {
TextureDump(src, unpack_buffer, unpack_length); TextureDump(src, unpack_buffer, unpack_length);
} }

View File

@ -356,7 +356,7 @@ void VulkanCommandProcessor::BeginFrame() {
// The capture will end when these commands are submitted to the queue. // The capture will end when these commands are submitted to the queue.
static uint32_t frame = 0; static uint32_t frame = 0;
if (device_->is_renderdoc_attached() && !capturing_ && if (device_->is_renderdoc_attached() && !capturing_ &&
(FLAGS_vulkan_renderdoc_capture_all || trace_requested_)) { (cvars::vulkan_renderdoc_capture_all || trace_requested_)) {
if (queue_mutex_) { if (queue_mutex_) {
queue_mutex_->lock(); queue_mutex_->lock();
} }

View File

@ -10,7 +10,7 @@
#include "xenia/gpu/vulkan/vulkan_gpu_flags.h" #include "xenia/gpu/vulkan/vulkan_gpu_flags.h"
DEFINE_bool(vulkan_renderdoc_capture_all, false, DEFINE_bool(vulkan_renderdoc_capture_all, false,
"Capture everything with RenderDoc."); "Capture everything with RenderDoc.", "Vulkan");
DEFINE_bool(vulkan_native_msaa, false, "Use native MSAA"); DEFINE_bool(vulkan_native_msaa, false, "Use native MSAA", "Vulkan");
DEFINE_bool(vulkan_dump_disasm, false, DEFINE_bool(vulkan_dump_disasm, false,
"Dump shader disassembly. NVIDIA only supported."); "Dump shader disassembly. NVIDIA only supported.", "Vulkan");

View File

@ -10,9 +10,8 @@
#ifndef XENIA_GPU_VULKAN_VULKAN_GPU_FLAGS_H_ #ifndef XENIA_GPU_VULKAN_VULKAN_GPU_FLAGS_H_
#define XENIA_GPU_VULKAN_VULKAN_GPU_FLAGS_H_ #define XENIA_GPU_VULKAN_VULKAN_GPU_FLAGS_H_
#include <gflags/gflags.h>
#define FINE_GRAINED_DRAW_SCOPES 1 #define FINE_GRAINED_DRAW_SCOPES 1
#include "xenia/base/cvar.h"
DECLARE_bool(vulkan_renderdoc_capture_all); DECLARE_bool(vulkan_renderdoc_capture_all);
DECLARE_bool(vulkan_native_msaa); DECLARE_bool(vulkan_native_msaa);

View File

@ -7,12 +7,11 @@
****************************************************************************** ******************************************************************************
*/ */
#include <gflags/gflags.h>
#include <cstring> #include <cstring>
#include "third_party/imgui/imgui.h" #include "third_party/imgui/imgui.h"
#include "xenia/base/clock.h" #include "xenia/base/clock.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/main.h" #include "xenia/base/main.h"
#include "xenia/base/threading.h" #include "xenia/base/threading.h"
@ -28,7 +27,8 @@
#include "xenia/hid/xinput/xinput_hid.h" #include "xenia/hid/xinput/xinput_hid.h"
#endif // XE_PLATFORM_WIN32 #endif // XE_PLATFORM_WIN32
DEFINE_string(hid, "any", "Input system. Use: [any, nop, winkey, xinput]"); DEFINE_string(hid, "any", "Input system. Use: [any, nop, winkey, xinput]",
"General");
namespace xe { namespace xe {
namespace hid { namespace hid {
@ -38,12 +38,12 @@ std::unique_ptr<xe::hid::InputSystem> input_system_;
std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers( std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers(
ui::Window* window) { ui::Window* window) {
std::vector<std::unique_ptr<hid::InputDriver>> drivers; std::vector<std::unique_ptr<hid::InputDriver>> drivers;
if (FLAGS_hid.compare("nop") == 0) { if (cvars::hid.compare("nop") == 0) {
drivers.emplace_back(xe::hid::nop::Create(window)); drivers.emplace_back(xe::hid::nop::Create(window));
#if XE_PLATFORM_WIN32 #if XE_PLATFORM_WIN32
} else if (FLAGS_hid.compare("winkey") == 0) { } else if (cvars::hid.compare("winkey") == 0) {
drivers.emplace_back(xe::hid::winkey::Create(window)); drivers.emplace_back(xe::hid::winkey::Create(window));
} else if (FLAGS_hid.compare("xinput") == 0) { } else if (cvars::hid.compare("xinput") == 0) {
drivers.emplace_back(xe::hid::xinput::Create(window)); drivers.emplace_back(xe::hid::xinput::Create(window));
#endif // XE_PLATFORM_WIN32 #endif // XE_PLATFORM_WIN32
} else { } else {

View File

@ -10,6 +10,4 @@
#ifndef XENIA_HID_HID_FLAGS_H_ #ifndef XENIA_HID_HID_FLAGS_H_
#define XENIA_HID_HID_FLAGS_H_ #define XENIA_HID_HID_FLAGS_H_
#include <gflags/gflags.h>
#endif // XENIA_HID_HID_FLAGS_H_ #endif // XENIA_HID_HID_FLAGS_H_

View File

@ -12,7 +12,4 @@ project("xenia-hid-nop")
}) })
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
local_platform_files() local_platform_files()

View File

@ -11,9 +11,6 @@ project("xenia-hid")
}) })
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
local_platform_files() local_platform_files()
removefiles({"*_demo.cc"}) removefiles({"*_demo.cc"})
@ -23,7 +20,6 @@ project("xenia-hid-demo")
kind("WindowedApp") kind("WindowedApp")
language("C++") language("C++")
links({ links({
"gflags",
"glew", "glew",
"imgui", "imgui",
"volk", "volk",
@ -37,9 +33,6 @@ project("xenia-hid-demo")
"GLEW_STATIC=1", "GLEW_STATIC=1",
"GLEW_MX=1", "GLEW_MX=1",
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
files({ files({
"hid_demo.cc", "hid_demo.cc",
"../base/main_"..platform_suffix..".cc", "../base/main_"..platform_suffix..".cc",

View File

@ -13,7 +13,4 @@ project("xenia-hid-winkey")
}) })
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
local_platform_files() local_platform_files()

View File

@ -12,7 +12,4 @@ project("xenia-hid-xinput")
}) })
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
local_platform_files() local_platform_files()

View File

@ -0,0 +1,16 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/kernel/kernel_flags.h"
DEFINE_bool(headless, false,
"Don't display any UI, using defaults for prompts as needed.",
"Other");
DEFINE_bool(log_high_frequency_kernel_calls, false,
"Log kernel calls with the kHighFrequency tag.", "Kernel");

View File

@ -0,0 +1,17 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_KERNEL_KERNEL_FLAGS_H_
#define XENIA_KERNEL_KERNEL_FLAGS_H_
#include "xenia/base/cvar.h"
DECLARE_bool(headless);
DECLARE_bool(log_high_frequency_kernel_calls);
#endif // XENIA_KERNEL_KERNEL_FLAGS_H_

View File

@ -9,8 +9,6 @@
#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/kernel_state.h"
#include <gflags/gflags.h>
#include <string> #include <string>
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
@ -29,9 +27,6 @@
#include "xenia/kernel/xobject.h" #include "xenia/kernel/xobject.h"
#include "xenia/kernel/xthread.h" #include "xenia/kernel/xthread.h"
DEFINE_bool(headless, false,
"Don't display any UI, using defaults for prompts as needed.");
namespace xe { namespace xe {
namespace kernel { namespace kernel {

View File

@ -10,8 +10,6 @@
#ifndef XENIA_KERNEL_KERNEL_STATE_H_ #ifndef XENIA_KERNEL_KERNEL_STATE_H_
#define XENIA_KERNEL_KERNEL_STATE_H_ #define XENIA_KERNEL_KERNEL_STATE_H_
#include <gflags/gflags.h>
#include <atomic> #include <atomic>
#include <condition_variable> #include <condition_variable>
#include <functional> #include <functional>
@ -20,6 +18,7 @@
#include <vector> #include <vector>
#include "xenia/base/bit_map.h" #include "xenia/base/bit_map.h"
#include "xenia/base/cvar.h"
#include "xenia/base/mutex.h" #include "xenia/base/mutex.h"
#include "xenia/cpu/export_resolver.h" #include "xenia/cpu/export_resolver.h"
#include "xenia/kernel/util/native_list.h" #include "xenia/kernel/util/native_list.h"
@ -39,8 +38,6 @@ class Processor;
} // namespace cpu } // namespace cpu
} // namespace xe } // namespace xe
DECLARE_bool(headless);
namespace xe { namespace xe {
namespace kernel { namespace kernel {

View File

@ -16,9 +16,6 @@ project("xenia-kernel")
}) })
defines({ defines({
}) })
includedirs({
project_root.."/third_party/gflags/src",
})
recursive_platform_files() recursive_platform_files()
files({ files({
"debug_visualizers.natvis", "debug_visualizers.natvis",

View File

@ -20,7 +20,7 @@
#include "xenia/kernel/xfile.h" #include "xenia/kernel/xfile.h"
#include "xenia/kernel/xthread.h" #include "xenia/kernel/xthread.h"
DEFINE_bool(xex_apply_patches, true, "Apply XEX patches."); DEFINE_bool(xex_apply_patches, true, "Apply XEX patches.", "Kernel");
namespace xe { namespace xe {
namespace kernel { namespace kernel {
@ -102,7 +102,7 @@ X_STATUS UserModule::LoadFromFile(std::string path) {
return result; return result;
} }
if (FLAGS_xex_apply_patches) { if (cvars::xex_apply_patches) {
// Search for xexp patch file // Search for xexp patch file
auto patch_entry = kernel_state()->file_system()->ResolvePath(path_ + "p"); auto patch_entry = kernel_state()->file_system()->ResolvePath(path_ + "p");

View File

@ -9,9 +9,6 @@
#include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/util/shim_utils.h"
DEFINE_bool(log_high_frequency_kernel_calls, false,
"Log kernel calls with the kHighFrequency tag.");
namespace xe { namespace xe {
namespace kernel { namespace kernel {
namespace shim { namespace shim {

View File

@ -10,8 +10,6 @@
#ifndef XENIA_KERNEL_UTIL_SHIM_UTILS_H_ #ifndef XENIA_KERNEL_UTIL_SHIM_UTILS_H_
#define XENIA_KERNEL_UTIL_SHIM_UTILS_H_ #define XENIA_KERNEL_UTIL_SHIM_UTILS_H_
#include <gflags/gflags.h>
#include <cstring> #include <cstring>
#include <string> #include <string>
@ -21,10 +19,9 @@
#include "xenia/base/string_buffer.h" #include "xenia/base/string_buffer.h"
#include "xenia/cpu/export_resolver.h" #include "xenia/cpu/export_resolver.h"
#include "xenia/cpu/ppc/ppc_context.h" #include "xenia/cpu/ppc/ppc_context.h"
#include "xenia/kernel/kernel_flags.h"
#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/kernel_state.h"
DECLARE_bool(log_high_frequency_kernel_calls);
namespace xe { namespace xe {
namespace kernel { namespace kernel {
@ -482,7 +479,7 @@ xe::cpu::Export* RegisterExport(R (*fn)(Ps&...), const char* name,
auto params = std::make_tuple<Ps...>(Ps(init)...); auto params = std::make_tuple<Ps...>(Ps(init)...);
if (export_entry->tags & xe::cpu::ExportTag::kLog && if (export_entry->tags & xe::cpu::ExportTag::kLog &&
(!(export_entry->tags & xe::cpu::ExportTag::kHighFrequency) || (!(export_entry->tags & xe::cpu::ExportTag::kHighFrequency) ||
FLAGS_log_high_frequency_kernel_calls)) { cvars::log_high_frequency_kernel_calls)) {
PrintKernelCall(export_entry, params); PrintKernelCall(export_entry, params);
} }
auto result = auto result =
@ -516,7 +513,7 @@ xe::cpu::Export* RegisterExport(void (*fn)(Ps&...), const char* name,
auto params = std::make_tuple<Ps...>(Ps(init)...); auto params = std::make_tuple<Ps...>(Ps(init)...);
if (export_entry->tags & xe::cpu::ExportTag::kLog && if (export_entry->tags & xe::cpu::ExportTag::kLog &&
(!(export_entry->tags & xe::cpu::ExportTag::kHighFrequency) || (!(export_entry->tags & xe::cpu::ExportTag::kHighFrequency) ||
FLAGS_log_high_frequency_kernel_calls)) { cvars::log_high_frequency_kernel_calls)) {
PrintKernelCall(export_entry, params); PrintKernelCall(export_entry, params);
} }
KernelTrampoline(FN, std::forward<std::tuple<Ps...>>(params), KernelTrampoline(FN, std::forward<std::tuple<Ps...>>(params),

View File

@ -9,6 +9,7 @@
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/emulator.h" #include "xenia/emulator.h"
#include "xenia/kernel/kernel_flags.h"
#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/xam/xam_private.h" #include "xenia/kernel/xam/xam_private.h"
@ -43,7 +44,7 @@ dword_result_t XamShowNuiTroubleshooterUI(unknown_t unk1, unknown_t unk2,
// unk1 is 0xFF - possibly user index? // unk1 is 0xFF - possibly user index?
// unk2, unk3 appear to always be zero. // unk2, unk3 appear to always be zero.
if (FLAGS_headless) { if (cvars::headless) {
return 0; return 0;
} }

View File

@ -10,6 +10,7 @@
#include "third_party/imgui/imgui.h" #include "third_party/imgui/imgui.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/emulator.h" #include "xenia/emulator.h"
#include "xenia/kernel/kernel_flags.h"
#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/xam/xam_private.h" #include "xenia/kernel/xam/xam_private.h"
@ -111,7 +112,7 @@ dword_result_t XamShowMessageBoxUI(dword_t user_index, lpwstring_t title_ptr,
} }
uint32_t chosen_button; uint32_t chosen_button;
if (FLAGS_headless) { if (cvars::headless) {
// Auto-pick the focused button. // Auto-pick the focused button.
chosen_button = active_button; chosen_button = active_button;
} else { } else {
@ -231,7 +232,7 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags,
return X_ERROR_INVALID_PARAMETER; return X_ERROR_INVALID_PARAMETER;
} }
if (FLAGS_headless) { if (cvars::headless) {
// Redirect default_text back into the buffer. // Redirect default_text back into the buffer.
std::memset(buffer, 0, buffer_length * 2); std::memset(buffer, 0, buffer_length * 2);
if (default_text) { if (default_text) {
@ -309,7 +310,7 @@ dword_result_t XamShowDeviceSelectorUI(dword_t user_index, dword_t content_type,
DECLARE_XAM_EXPORT1(XamShowDeviceSelectorUI, kUI, kImplemented); DECLARE_XAM_EXPORT1(XamShowDeviceSelectorUI, kUI, kImplemented);
void XamShowDirtyDiscErrorUI(dword_t user_index) { void XamShowDirtyDiscErrorUI(dword_t user_index) {
if (FLAGS_headless) { if (cvars::headless) {
assert_always(); assert_always();
exit(1); exit(1);
return; return;

View File

@ -9,8 +9,6 @@
#include "xenia/kernel/xboxkrnl/xboxkrnl_module.h" #include "xenia/kernel/xboxkrnl/xboxkrnl_module.h"
#include <gflags/gflags.h>
#include <vector> #include <vector>
#include "xenia/base/clock.h" #include "xenia/base/clock.h"

View File

@ -9,8 +9,6 @@
#include "xenia/kernel/xboxkrnl/xboxkrnl_module.h" #include "xenia/kernel/xboxkrnl/xboxkrnl_module.h"
#include <gflags/gflags.h>
#include <vector> #include <vector>
#include "xenia/base/clock.h" #include "xenia/base/clock.h"
@ -47,7 +45,7 @@ void KeDebugMonitorCallback(cpu::ppc::PPCContext* ppc_context,
XELOGI("KeDebugMonitorCallback(%u, %08x)", static_cast<uint32_t>(id), arg); XELOGI("KeDebugMonitorCallback(%u, %08x)", static_cast<uint32_t>(id), arg);
if (!FLAGS_kernel_pix) { if (!cvars::kernel_pix) {
SHIM_SET_RETURN_32(-1); SHIM_SET_RETURN_32(-1);
return; return;
} }

View File

@ -9,8 +9,6 @@
#include "xenia/kernel/xboxkrnl/xboxkrnl_module.h" #include "xenia/kernel/xboxkrnl/xboxkrnl_module.h"
#include <gflags/gflags.h>
#include <vector> #include <vector>
#include "xenia/base/clock.h" #include "xenia/base/clock.h"
@ -27,18 +25,19 @@
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h" #include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
#include "xenia/kernel/xthread.h" #include "xenia/kernel/xthread.h"
DEFINE_string(cl, "", "Specify additional command-line provided to guest."); DEFINE_string(cl, "", "Specify additional command-line provided to guest.",
"Kernel");
DEFINE_bool(kernel_debug_monitor, false, "Enable debug monitor."); DEFINE_bool(kernel_debug_monitor, false, "Enable debug monitor.", "Kernel");
DEFINE_bool(kernel_cert_monitor, false, "Enable cert monitor."); DEFINE_bool(kernel_cert_monitor, false, "Enable cert monitor.", "Kernel");
DEFINE_bool(kernel_pix, false, "Enable PIX."); DEFINE_bool(kernel_pix, false, "Enable PIX.", "Kernel");
namespace xe { namespace xe {
namespace kernel { namespace kernel {
namespace xboxkrnl { namespace xboxkrnl {
bool XboxkrnlModule::SendPIXCommand(const char* cmd) { bool XboxkrnlModule::SendPIXCommand(const char* cmd) {
if (!FLAGS_kernel_pix) { if (!cvars::kernel_pix) {
return false; return false;
} }
@ -103,7 +102,7 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
// Offset 0x18 is a 4b pointer to a handler function that seems to take two // Offset 0x18 is a 4b pointer to a handler function that seems to take two
// arguments. If we wanted to see what would happen we could fake that. // arguments. If we wanted to see what would happen we could fake that.
uint32_t pKeDebugMonitorData; uint32_t pKeDebugMonitorData;
if (!FLAGS_kernel_debug_monitor) { if (!cvars::kernel_debug_monitor) {
pKeDebugMonitorData = memory_->SystemHeapAlloc(4); pKeDebugMonitorData = memory_->SystemHeapAlloc(4);
auto lpKeDebugMonitorData = memory_->TranslateVirtual(pKeDebugMonitorData); auto lpKeDebugMonitorData = memory_->TranslateVirtual(pKeDebugMonitorData);
xe::store_and_swap<uint32_t>(lpKeDebugMonitorData, 0); xe::store_and_swap<uint32_t>(lpKeDebugMonitorData, 0);
@ -125,7 +124,7 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
// KeCertMonitorData (?*) // KeCertMonitorData (?*)
// Always set to zero, ignored. // Always set to zero, ignored.
uint32_t pKeCertMonitorData; uint32_t pKeCertMonitorData;
if (!FLAGS_kernel_cert_monitor) { if (!cvars::kernel_cert_monitor) {
pKeCertMonitorData = memory_->SystemHeapAlloc(4); pKeCertMonitorData = memory_->SystemHeapAlloc(4);
auto lpKeCertMonitorData = memory_->TranslateVirtual(pKeCertMonitorData); auto lpKeCertMonitorData = memory_->TranslateVirtual(pKeCertMonitorData);
xe::store_and_swap<uint32_t>(lpKeCertMonitorData, 0); xe::store_and_swap<uint32_t>(lpKeCertMonitorData, 0);
@ -187,8 +186,8 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
// Always set to "default.xex" (with quotes) for now. // Always set to "default.xex" (with quotes) for now.
// TODO(gibbed): set this to the actual module name. // TODO(gibbed): set this to the actual module name.
std::string command_line("\"default.xex\""); std::string command_line("\"default.xex\"");
if (FLAGS_cl.length()) { if (cvars::cl.length()) {
command_line += " " + FLAGS_cl; command_line += " " + cvars::cl;
} }
uint32_t command_line_length = uint32_t command_line_length =
xe::align(static_cast<uint32_t>(command_line.length()) + 1, 1024u); xe::align(static_cast<uint32_t>(command_line.length()) + 1, 1024u);

View File

@ -9,8 +9,6 @@
#include "xenia/kernel/xboxkrnl/xboxkrnl_video.h" #include "xenia/kernel/xboxkrnl/xboxkrnl_video.h"
#include <gflags/gflags.h>
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/emulator.h" #include "xenia/emulator.h"
#include "xenia/gpu/graphics_system.h" #include "xenia/gpu/graphics_system.h"
@ -24,9 +22,11 @@
DEFINE_int32(kernel_display_gamma_type, 1, DEFINE_int32(kernel_display_gamma_type, 1,
"Display gamma type: 0 - linear, 1 - sRGB, 2 - TV (BT.709), " "Display gamma type: 0 - linear, 1 - sRGB, 2 - TV (BT.709), "
"3 - power specified via kernel_display_gamma_power."); "3 - power specified via kernel_display_gamma_power.",
"Kernel");
DEFINE_double(kernel_display_gamma_power, 2.22222233, DEFINE_double(kernel_display_gamma_power, 2.22222233,
"Display gamma to use with kernel_display_gamma_type 3."); "Display gamma to use with kernel_display_gamma_type 3.",
"Kernel");
namespace xe { namespace xe {
namespace kernel { namespace kernel {
@ -51,8 +51,8 @@ void VdGetCurrentDisplayGamma(lpdword_t type_ptr, lpfloat_t power_ptr) {
// 3 - use the power written to *power_ptr. // 3 - use the power written to *power_ptr.
// Anything else - linear. // Anything else - linear.
// Used in D3D SetGammaRamp/SetPWLGamma to adjust the ramp for the display. // Used in D3D SetGammaRamp/SetPWLGamma to adjust the ramp for the display.
*type_ptr = uint32_t(FLAGS_kernel_display_gamma_type); *type_ptr = uint32_t(cvars::kernel_display_gamma_type);
*power_ptr = float(FLAGS_kernel_display_gamma_power); *power_ptr = float(cvars::kernel_display_gamma_power);
} }
DECLARE_XBOXKRNL_EXPORT1(VdGetCurrentDisplayGamma, kVideo, kStub); DECLARE_XBOXKRNL_EXPORT1(VdGetCurrentDisplayGamma, kVideo, kStub);

Some files were not shown because too many files have changed in this diff Show More