commit
18c20687d4
@ -0,0 +1,3 @@
|
||||
[submodule "modules/minhook"]
|
||||
path = modules/minhook
|
||||
url = https://github.com/flightlessmango/minhook
|
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
set -u
|
||||
|
||||
if [ $# -eq 2 ]; then
|
||||
echo Specify runtime version too
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SRCDIR=$PWD
|
||||
BRANCH="${1:-master}"
|
||||
# soldier 0.20201022.1 or newer
|
||||
# scout 0.20201104.0 or newer
|
||||
RUNTIME="${2:-soldier}"
|
||||
VERSION="${3:-0.20201022.1}"
|
||||
IMAGE="steamrt_${RUNTIME}_amd64:mango-${VERSION}"
|
||||
BASEURL="https://repo.steampowered.com/steamrt-images-${RUNTIME}/snapshots/${VERSION}"
|
||||
|
||||
echo -e "\e[1mBuilding branch \e[92m${BRANCH}\e[39m using \e[92m${RUNTIME}:${VERSION}\e[39m runtime\e[0m"
|
||||
|
||||
if ! docker inspect --type=image ${IMAGE} 2>&1 >/dev/null ; then
|
||||
rm -fr ./cache/empty
|
||||
set -e
|
||||
mkdir -p ./cache/empty
|
||||
sed "s/%RUNTIME%/${RUNTIME}/g" steamrt.Dockerfile.in > ./cache/steamrt.Dockerfile
|
||||
|
||||
wget -P ./cache -c ${BASEURL}/com.valvesoftware.SteamRuntime.Sdk-amd64,i386-${RUNTIME}-sysroot.tar.gz
|
||||
cp --reflink=always "./cache/com.valvesoftware.SteamRuntime.Sdk-amd64,i386-${RUNTIME}-sysroot.tar.gz" ./cache/empty/
|
||||
docker build -f ./cache/steamrt.Dockerfile -t ${IMAGE} ./cache/empty
|
||||
fi
|
||||
|
||||
docker run --entrypoint=/bin/sh --rm -i -v "${SRCDIR}/srt-output:/output" ${IMAGE} << EOF
|
||||
export RUNTIME=${RUNTIME}
|
||||
export SRT_VERSION=${VERSION}
|
||||
git clone git://github.com/flightlessmango/MangoHud.git . --branch ${BRANCH} --recurse-submodules --progress
|
||||
./build-srt.sh clean build package release
|
||||
cp -v build-srt/MangoHud*tar.gz /output/
|
||||
EOF
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,18 @@
|
||||
[binaries]
|
||||
c = 'x86_64-w64-mingw32-gcc'
|
||||
cpp = 'x86_64-w64-mingw32-g++'
|
||||
ar = 'x86_64-w64-mingw32-ar'
|
||||
strip = 'x86_64-w64-mingw32-strip'
|
||||
pkgconfig = 'x86_64-w64-mingw32-pkg-config'
|
||||
sh = '/usr/bin/sh'
|
||||
|
||||
[properties]
|
||||
c_link_args = ['-static', '-static-libgcc']
|
||||
cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++']
|
||||
needs_exe_wrapper = true
|
||||
|
||||
[host_machine]
|
||||
system = 'windows'
|
||||
cpu_family = 'x86_64'
|
||||
cpu = 'x86_64'
|
||||
endian = 'little'
|
@ -0,0 +1 @@
|
||||
Subproject commit df6622659e366c63dfc9591245fa6a9a10ec4759
|
@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
#ifndef MANGOHUD_BLACKLIST_H
|
||||
#define MANGOHUD_BLACKLIST_H
|
||||
|
||||
#include<string>
|
||||
bool is_blacklisted(bool force_recheck = false);
|
||||
void add_blacklist(std::string);
|
||||
|
||||
|
||||
#endif //MANGOHUD_BLACKLIST_H
|
||||
|
@ -0,0 +1,65 @@
|
||||
#include <windows.h>
|
||||
#include <thread>
|
||||
#include <string.h>
|
||||
#include "cpu.h"
|
||||
#include <iostream>
|
||||
#define SystemProcessorPerformanceInformation 0x8
|
||||
#define SystemBasicInformation 0x0
|
||||
FILETIME last_userTime, last_kernelTime, last_idleTime;
|
||||
|
||||
uint64_t FileTimeToInt64( const FILETIME& ft ) {
|
||||
ULARGE_INTEGER uli = { 0 };
|
||||
uli.LowPart = ft.dwLowDateTime;
|
||||
uli.HighPart = ft.dwHighDateTime;
|
||||
return uli.QuadPart;
|
||||
}
|
||||
|
||||
bool CPUStats::UpdateCPUData()
|
||||
{
|
||||
#define NUMBER_OF_PROCESSORS (8)
|
||||
#define PROCESSOR_BUFFER_SIZE (NUMBER_OF_PROCESSORS * 8)
|
||||
static ULONG64 ProcessorIdleTimeBuffer [ PROCESSOR_BUFFER_SIZE ];
|
||||
|
||||
FILETIME IdleTime, KernelTime, UserTime;
|
||||
static unsigned long long PrevTotal = 0;
|
||||
static unsigned long long PrevIdle = 0;
|
||||
static unsigned long long PrevUser = 0;
|
||||
unsigned long long ThisTotal;
|
||||
unsigned long long ThisIdle, ThisKernel, ThisUser;
|
||||
unsigned long long TotalSinceLast, IdleSinceLast, UserSinceLast;
|
||||
|
||||
|
||||
// GET THE KERNEL / USER / IDLE times.
|
||||
// And oh, BTW, kernel time includes idle time
|
||||
GetSystemTimes( & IdleTime, & KernelTime, & UserTime);
|
||||
|
||||
ThisIdle = FileTimeToInt64(IdleTime);
|
||||
ThisKernel = FileTimeToInt64 (KernelTime);
|
||||
ThisUser = FileTimeToInt64 (UserTime);
|
||||
|
||||
ThisTotal = ThisKernel + ThisUser;
|
||||
TotalSinceLast = ThisTotal - PrevTotal;
|
||||
IdleSinceLast = ThisIdle - PrevIdle;
|
||||
UserSinceLast = ThisUser - PrevUser;
|
||||
double Headroom;
|
||||
Headroom = (double)IdleSinceLast / (double)TotalSinceLast ;
|
||||
double Load;
|
||||
Load = 1.0 - Headroom;
|
||||
Headroom *= 100.0; // to make it percent
|
||||
Load *= 100.0; // percent
|
||||
|
||||
PrevTotal = ThisTotal;
|
||||
PrevIdle = ThisIdle;
|
||||
PrevUser = ThisUser;
|
||||
|
||||
// print results to output window of VS when run in Debug
|
||||
m_cpuDataTotal.percent = Load;
|
||||
return true;
|
||||
}
|
||||
CPUStats::CPUStats()
|
||||
{
|
||||
}
|
||||
CPUStats::~CPUStats()
|
||||
{
|
||||
}
|
||||
CPUStats cpuStats;
|
@ -0,0 +1,67 @@
|
||||
#include "file_utils.h"
|
||||
#include "string_utils.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
|
||||
std::string read_line(const std::string& filename)
|
||||
{
|
||||
std::string line;
|
||||
std::ifstream file(filename);
|
||||
std::getline(file, line);
|
||||
return line;
|
||||
}
|
||||
|
||||
bool find_folder(const char* root, const char* prefix, std::string& dest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool find_folder(const std::string& root, const std::string& prefix, std::string& dest)
|
||||
{
|
||||
return find_folder(root.c_str(), prefix.c_str(), dest);
|
||||
}
|
||||
|
||||
std::vector<std::string> ls(const char* root, const char* prefix, LS_FLAGS flags)
|
||||
{
|
||||
std::vector<std::string> list;
|
||||
return list;
|
||||
}
|
||||
|
||||
bool file_exists(const std::string& path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dir_exists(const std::string& path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string get_exe_path()
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
bool get_wine_exe_name(std::string& name, bool keep_ext)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string get_home_dir()
|
||||
{
|
||||
std::string path;
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string get_data_dir()
|
||||
{
|
||||
std::string path;
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string get_config_dir()
|
||||
{
|
||||
std::string path;
|
||||
return path;
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
#include "overlay.h"
|
||||
#include "file_utils.h"
|
||||
#include "font_default.h"
|
||||
|
||||
void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& text_font)
|
||||
{
|
||||
auto& io = ImGui::GetIO();
|
||||
io.Fonts->Clear();
|
||||
ImGui::GetIO().FontGlobalScale = params.font_scale; // set here too so ImGui::CalcTextSize is correct
|
||||
float font_size = params.font_size;
|
||||
if (font_size < FLT_EPSILON)
|
||||
font_size = 24;
|
||||
|
||||
float font_size_text = params.font_size_text;
|
||||
if (font_size_text < FLT_EPSILON)
|
||||
font_size_text = font_size;
|
||||
static const ImWchar default_range[] =
|
||||
{
|
||||
0x0020, 0x00FF, // Basic Latin + Latin Supplement
|
||||
//0x0100, 0x017F, // Latin Extended-A
|
||||
//0x2103, 0x2103, // Degree Celsius
|
||||
//0x2109, 0x2109, // Degree Fahrenheit
|
||||
0,
|
||||
};
|
||||
|
||||
ImVector<ImWchar> glyph_ranges;
|
||||
ImFontGlyphRangesBuilder builder;
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesDefault());
|
||||
if (params.font_glyph_ranges & FG_KOREAN)
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesKorean());
|
||||
if (params.font_glyph_ranges & FG_CHINESE_FULL)
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesChineseFull());
|
||||
if (params.font_glyph_ranges & FG_CHINESE_SIMPLIFIED)
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
|
||||
if (params.font_glyph_ranges & FG_JAPANESE)
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Not exactly Shift JIS compatible?
|
||||
if (params.font_glyph_ranges & FG_CYRILLIC)
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesCyrillic());
|
||||
if (params.font_glyph_ranges & FG_THAI)
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesThai());
|
||||
if (params.font_glyph_ranges & FG_VIETNAMESE)
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesVietnamese());
|
||||
if (params.font_glyph_ranges & FG_LATIN_EXT_A) {
|
||||
constexpr ImWchar latin_ext_a[] { 0x0100, 0x017F, 0 };
|
||||
builder.AddRanges(latin_ext_a);
|
||||
}
|
||||
if (params.font_glyph_ranges & FG_LATIN_EXT_B) {
|
||||
constexpr ImWchar latin_ext_b[] { 0x0180, 0x024F, 0 };
|
||||
builder.AddRanges(latin_ext_b);
|
||||
}
|
||||
builder.BuildRanges(&glyph_ranges);
|
||||
|
||||
bool same_font = (params.font_file == params.font_file_text || params.font_file_text.empty());
|
||||
bool same_size = (font_size == font_size_text);
|
||||
|
||||
// ImGui takes ownership of the data, no need to free it
|
||||
if (!params.font_file.empty() && file_exists(params.font_file)) {
|
||||
io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size, nullptr, same_font && same_size ? glyph_ranges.Data : default_range);
|
||||
if (params.no_small_font)
|
||||
small_font = io.Fonts->Fonts[0];
|
||||
else
|
||||
small_font = io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size * 0.55f, nullptr, default_range);
|
||||
} else {
|
||||
const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85();
|
||||
io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size, nullptr, default_range);
|
||||
if (params.no_small_font)
|
||||
small_font = io.Fonts->Fonts[0];
|
||||
else
|
||||
small_font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size * 0.55f, nullptr, default_range);
|
||||
}
|
||||
|
||||
auto font_file_text = params.font_file_text;
|
||||
if (font_file_text.empty())
|
||||
font_file_text = params.font_file;
|
||||
|
||||
if ((!same_font || !same_size) && file_exists(font_file_text))
|
||||
text_font = io.Fonts->AddFontFromFileTTF(font_file_text.c_str(), font_size_text, nullptr, glyph_ranges.Data);
|
||||
else
|
||||
text_font = io.Fonts->Fonts[0];
|
||||
|
||||
io.Fonts->Build();
|
||||
}
|
@ -0,0 +1,630 @@
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include "hud_elements.h"
|
||||
#include "cpu.h"
|
||||
#include "memory.h"
|
||||
#include "mesa/util/macros.h"
|
||||
#include "string_utils.h"
|
||||
|
||||
// Cut from https://github.com/ocornut/imgui/pull/2943
|
||||
// Probably move to ImGui
|
||||
float SRGBToLinear(float in)
|
||||
{
|
||||
if (in <= 0.04045f)
|
||||
return in / 12.92f;
|
||||
else
|
||||
return powf((in + 0.055f) / 1.055f, 2.4f);
|
||||
}
|
||||
|
||||
float LinearToSRGB(float in)
|
||||
{
|
||||
if (in <= 0.0031308f)
|
||||
return in * 12.92f;
|
||||
else
|
||||
return 1.055f * powf(in, 1.0f / 2.4f) - 0.055f;
|
||||
}
|
||||
|
||||
ImVec4 SRGBToLinear(ImVec4 col)
|
||||
{
|
||||
col.x = SRGBToLinear(col.x);
|
||||
col.y = SRGBToLinear(col.y);
|
||||
col.z = SRGBToLinear(col.z);
|
||||
// Alpha component is already linear
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
ImVec4 LinearToSRGB(ImVec4 col)
|
||||
{
|
||||
col.x = LinearToSRGB(col.x);
|
||||
col.y = LinearToSRGB(col.y);
|
||||
col.z = LinearToSRGB(col.z);
|
||||
// Alpha component is already linear
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
void HudElements::convert_colors(struct overlay_params& params)
|
||||
{
|
||||
HUDElements.colors.update = false;
|
||||
auto convert = [](unsigned color) -> ImVec4 {
|
||||
ImVec4 fc = ImGui::ColorConvertU32ToFloat4(color);
|
||||
if (HUDElements.colors.convert)
|
||||
return SRGBToLinear(fc);
|
||||
return fc;
|
||||
};
|
||||
|
||||
HUDElements.colors.cpu = convert(params.cpu_color);
|
||||
HUDElements.colors.gpu = convert(params.gpu_color);
|
||||
HUDElements.colors.vram = convert(params.vram_color);
|
||||
HUDElements.colors.ram = convert(params.ram_color);
|
||||
HUDElements.colors.engine = convert(params.engine_color);
|
||||
HUDElements.colors.io = convert(params.io_color);
|
||||
HUDElements.colors.frametime = convert(params.frametime_color);
|
||||
HUDElements.colors.background = convert(params.background_color);
|
||||
HUDElements.colors.text = convert(params.text_color);
|
||||
HUDElements.colors.media_player = convert(params.media_player_color);
|
||||
HUDElements.colors.wine = convert(params.wine_color);
|
||||
HUDElements.colors.gpu_load_low = convert(params.gpu_load_color[0]);
|
||||
HUDElements.colors.gpu_load_med = convert(params.gpu_load_color[1]);
|
||||
HUDElements.colors.gpu_load_high = convert(params.gpu_load_color[2]);
|
||||
HUDElements.colors.cpu_load_low = convert(params.cpu_load_color[0]);
|
||||
HUDElements.colors.cpu_load_med = convert(params.cpu_load_color[1]);
|
||||
HUDElements.colors.cpu_load_high = convert(params.cpu_load_color[2]);
|
||||
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.Colors[ImGuiCol_PlotLines] = convert(params.frametime_color);
|
||||
style.Colors[ImGuiCol_PlotHistogram] = convert(params.frametime_color);
|
||||
style.Colors[ImGuiCol_WindowBg] = convert(params.background_color);
|
||||
style.Colors[ImGuiCol_Text] = convert(params.text_color);
|
||||
style.CellPadding.y = params.cellpadding_y * real_font_size.y;
|
||||
}
|
||||
|
||||
void HudElements::convert_colors(bool do_conv, struct overlay_params& params)
|
||||
{
|
||||
HUDElements.colors.convert = do_conv;
|
||||
convert_colors(params);
|
||||
}
|
||||
|
||||
void HudElements::time(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_time]){
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.00f), "%s", HUDElements.sw_stats->time.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void HudElements::version(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_version]){
|
||||
ImGui::TableNextRow();
|
||||
ImGui::Text("%s", MANGOHUD_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
void HudElements::gpu_stats(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_stats]){
|
||||
ImGui::TableNextRow();
|
||||
const char* gpu_text;
|
||||
if (HUDElements.params->gpu_text.empty())
|
||||
gpu_text = "GPU";
|
||||
else
|
||||
gpu_text = HUDElements.params->gpu_text.c_str();
|
||||
ImGui::TextColored(HUDElements.colors.gpu, "%s", gpu_text);
|
||||
ImGui::TableNextCell();
|
||||
auto text_color = HUDElements.colors.text;
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){
|
||||
struct LOAD_DATA gpu_data = {
|
||||
HUDElements.colors.gpu_load_low,
|
||||
HUDElements.colors.gpu_load_med,
|
||||
HUDElements.colors.gpu_load_high,
|
||||
HUDElements.params->gpu_load_value[0],
|
||||
HUDElements.params->gpu_load_value[1]
|
||||
};
|
||||
|
||||
auto load_color = change_on_load_temp(gpu_data, gpu_info.load);
|
||||
right_aligned_text(load_color, HUDElements.ralign_width, "%i", gpu_info.load);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::TextColored(load_color,"%%");
|
||||
}
|
||||
else {
|
||||
right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.load);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::TextColored(text_color,"%%");
|
||||
// ImGui::SameLine(150);
|
||||
// ImGui::Text("%s", "%");
|
||||
}
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_temp]){
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.temp);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::Text("°C");
|
||||
}
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock] || HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_power])
|
||||
ImGui::TableNextRow();
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock]){
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.CoreClock);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::Text("MHz");
|
||||
ImGui::PopFont();
|
||||
}
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_power]) {
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.powerUsage);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::Text("W");
|
||||
ImGui::PopFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HudElements::cpu_stats(){
|
||||
if(HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_stats]){
|
||||
ImGui::TableNextRow();
|
||||
const char* cpu_text;
|
||||
if (HUDElements.params->cpu_text.empty())
|
||||
cpu_text = "CPU";
|
||||
else
|
||||
cpu_text = HUDElements.params->cpu_text.c_str();
|
||||
|
||||
ImGui::TextColored(HUDElements.colors.cpu, "%s", cpu_text);
|
||||
ImGui::TableNextCell();
|
||||
auto text_color = HUDElements.colors.text;
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_load_change]){
|
||||
int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent);
|
||||
struct LOAD_DATA cpu_data = {
|
||||
HUDElements.colors.cpu_load_low,
|
||||
HUDElements.colors.cpu_load_med,
|
||||
HUDElements.colors.cpu_load_high,
|
||||
HUDElements.params->cpu_load_value[0],
|
||||
HUDElements.params->cpu_load_value[1]
|
||||
};
|
||||
|
||||
auto load_color = change_on_load_temp(cpu_data, cpu_load_percent);
|
||||
right_aligned_text(load_color, HUDElements.ralign_width, "%d", cpu_load_percent);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::TextColored(load_color, "%%");
|
||||
}
|
||||
else {
|
||||
right_aligned_text(text_color, HUDElements.ralign_width, "%d", int(cpuStats.GetCPUDataTotal().percent));
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::Text("%%");
|
||||
}
|
||||
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_temp]){
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().temp);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::Text("°C");
|
||||
}
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_mhz] || HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_power])
|
||||
ImGui::TableNextRow();
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_mhz]){
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().cpu_mhz);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::Text("MHz");
|
||||
ImGui::PopFont();
|
||||
}
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_power]){
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().power);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::Text("W");
|
||||
ImGui::PopFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HudElements::core_load(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_core_load]){
|
||||
int i = 0;
|
||||
for (const CPUData &cpuData : cpuStats.GetCPUData())
|
||||
{
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TextColored(HUDElements.colors.cpu, "CPU");
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::TextColored(HUDElements.colors.cpu,"%i", i);
|
||||
ImGui::PopFont();
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", int(cpuData.percent));
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::Text("%%");
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", cpuData.mhz);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::Text("MHz");
|
||||
ImGui::PopFont();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
void HudElements::io_stats(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read] || HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]){
|
||||
auto sampling = HUDElements.params->fps_sampling_period;
|
||||
ImGui::TableNextRow();
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read] && !HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write])
|
||||
ImGui::TextColored(HUDElements.colors.io, "IO RD");
|
||||
else if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read] && HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write])
|
||||
ImGui::TextColored(HUDElements.colors.io, "IO RW");
|
||||
else if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write] && !HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read])
|
||||
ImGui::TextColored(HUDElements.colors.io, "IO WR");
|
||||
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read]){
|
||||
ImGui::TableNextCell();
|
||||
float val = HUDElements.sw_stats->io.diff.read * 1000000 / sampling;
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, val < 100 ? "%.1f" : "%.f", val);
|
||||
ImGui::SameLine(0,1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::Text("MiB/s");
|
||||
ImGui::PopFont();
|
||||
}
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]){
|
||||
ImGui::TableNextCell();
|
||||
float val = HUDElements.sw_stats->io.diff.write * 1000000 / sampling;
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, val < 100 ? "%.1f" : "%.f", val);
|
||||
ImGui::SameLine(0,1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::Text("MiB/s");
|
||||
ImGui::PopFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HudElements::vram(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_vram]){
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TextColored(HUDElements.colors.vram, "VRAM");
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", gpu_info.memoryUsed);
|
||||
ImGui::SameLine(0,1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::Text("GiB");
|
||||
ImGui::PopFont();
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_mem_clock]){
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", gpu_info.MemClock);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::Text("MHz");
|
||||
ImGui::PopFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
void HudElements::ram(){
|
||||
#ifdef __gnu_linux__
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_ram]){
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TextColored(HUDElements.colors.ram, "RAM");
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", memused);
|
||||
ImGui::SameLine(0,1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::Text("GiB");
|
||||
ImGui::PopFont();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void HudElements::fps(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_fps]){
|
||||
ImGui::TableNextRow();
|
||||
if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_fps] && HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_engine_version]){
|
||||
ImGui::TextColored(HUDElements.colors.engine, "%s", HUDElements.is_vulkan ? HUDElements.sw_stats->engineName.c_str() : "OpenGL");
|
||||
}
|
||||
ImGui::TextColored(HUDElements.colors.engine, "%s", HUDElements.is_vulkan ? HUDElements.sw_stats->engineName.c_str() : "OpenGL");
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.0f", HUDElements.sw_stats->fps);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::Text("FPS");
|
||||
ImGui::PopFont();
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_frametime]){
|
||||
ImGui::TableNextCell();
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", 1000 / HUDElements.sw_stats->fps);
|
||||
ImGui::SameLine(0, 1.0f);
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::Text("ms");
|
||||
ImGui::PopFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HudElements::gpu_name(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_name] && !HUDElements.sw_stats->gpuName.empty()){
|
||||
ImGui::TableNextRow();
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::TextColored(HUDElements.colors.engine,
|
||||
"%s", HUDElements.sw_stats->gpuName.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
}
|
||||
|
||||
void HudElements::engine_version(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_engine_version]){
|
||||
ImGui::TableNextRow();
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
if (HUDElements.is_vulkan) {
|
||||
if ((HUDElements.sw_stats->engineName == "DXVK" || HUDElements.sw_stats->engineName == "VKD3D")){
|
||||
ImGui::TextColored(HUDElements.colors.engine,
|
||||
"%s/%d.%d.%d", HUDElements.sw_stats->engineVersion.c_str(),
|
||||
HUDElements.sw_stats->version_vk.major,
|
||||
HUDElements.sw_stats->version_vk.minor,
|
||||
HUDElements.sw_stats->version_vk.patch);
|
||||
} else {
|
||||
ImGui::TextColored(HUDElements.colors.engine,
|
||||
"%d.%d.%d",
|
||||
HUDElements.sw_stats->version_vk.major,
|
||||
HUDElements.sw_stats->version_vk.minor,
|
||||
HUDElements.sw_stats->version_vk.patch);
|
||||
}
|
||||
} else {
|
||||
ImGui::TextColored(HUDElements.colors.engine,
|
||||
"%d.%d%s", HUDElements.sw_stats->version_gl.major, HUDElements.sw_stats->version_gl.minor,
|
||||
HUDElements.sw_stats->version_gl.is_gles ? " ES" : "");
|
||||
}
|
||||
ImGui::PopFont();
|
||||
}
|
||||
}
|
||||
|
||||
void HudElements::vulkan_driver(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_vulkan_driver] && !HUDElements.sw_stats->driverName.empty()){
|
||||
ImGui::TableNextRow();
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::TextColored(HUDElements.colors.engine,
|
||||
"%s", HUDElements.sw_stats->driverName.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
}
|
||||
|
||||
void HudElements::arch(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_arch]){
|
||||
ImGui::TableNextRow();
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::TextColored(HUDElements.colors.engine, "%s", "" MANGOHUD_ARCH);
|
||||
ImGui::PopFont();
|
||||
}
|
||||
}
|
||||
|
||||
void HudElements::wine(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_wine]){
|
||||
ImGui::TableNextRow();
|
||||
if (!wineVersion.empty()){
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::TextColored(HUDElements.colors.wine, "%s", wineVersion.c_str());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HudElements::frame_timing(){
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_frame_timing]){
|
||||
ImGui::TableNextRow();
|
||||
ImGui::Dummy(ImVec2(0.0f, real_font_size.y));
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
ImGui::TextColored(HUDElements.colors.engine, "%s", "Frametime");
|
||||
for (size_t i = 0; i < HUDElements.params->table_columns - 1; i++)
|
||||
ImGui::TableNextCell();
|
||||
ImGui::Dummy(ImVec2(0.0f, real_font_size.y));
|
||||
right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width * 1.3, "%.1f ms", 1000 / HUDElements.sw_stats->fps);
|
||||
ImGui::PopFont();
|
||||
ImGui::TableNextRow();
|
||||
char hash[40];
|
||||
snprintf(hash, sizeof(hash), "##%s", overlay_param_names[OVERLAY_PARAM_ENABLED_frame_timing]);
|
||||
HUDElements.sw_stats->stat_selector = OVERLAY_PLOTS_frame_timing;
|
||||
HUDElements.sw_stats->time_dividor = 1000.0f;
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
double min_time = 0.0f;
|
||||
double max_time = 50.0f;
|
||||
if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_histogram]){
|
||||
ImGui::PlotHistogram(hash, get_time_stat, HUDElements.sw_stats,
|
||||
ARRAY_SIZE(HUDElements.sw_stats->frames_stats), 0,
|
||||
NULL, min_time, max_time,
|
||||
ImVec2(ImGui::GetContentRegionAvailWidth() * HUDElements.params->table_columns, 50));
|
||||
} else {
|
||||
ImGui::PlotLines(hash, get_time_stat, HUDElements.sw_stats,
|
||||
ARRAY_SIZE(HUDElements.sw_stats->frames_stats), 0,
|
||||
NULL, min_time, max_time,
|
||||
ImVec2(ImGui::GetContentRegionAvailWidth() * HUDElements.params->table_columns, 50));
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void HudElements::media_player(){
|
||||
#ifdef HAVE_DBUS
|
||||
ImGui::TableNextRow();
|
||||
uint32_t f_idx = (HUDElements.sw_stats->n_frames - 1) % ARRAY_SIZE(HUDElements.sw_stats->frames_stats);
|
||||
uint64_t frame_timing = HUDElements.sw_stats->frames_stats[f_idx].stats[OVERLAY_PLOTS_frame_timing];
|
||||
ImFont scaled_font = *HUDElements.sw_stats->font_text;
|
||||
scaled_font.Scale = HUDElements.params->font_scale_media_player;
|
||||
ImGui::PushFont(&scaled_font);
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(main_metadata.mtx);
|
||||
render_mpris_metadata(*HUDElements.params, main_metadata, frame_timing, true);
|
||||
}
|
||||
ImGui::PopFont();
|
||||
#endif
|
||||
}
|
||||
|
||||
void HudElements::graphs(){
|
||||
ImGui::TableNextRow();
|
||||
ImGui::Dummy(ImVec2(0.0f, real_font_size.y));
|
||||
std::string value = HUDElements.ordered_functions[HUDElements.place].second;
|
||||
std::vector<float> arr(50, 0);
|
||||
|
||||
ImGui::PushFont(HUDElements.sw_stats->font1);
|
||||
if (value == "cpu_load"){
|
||||
for (auto& it : graph_data){
|
||||
arr.push_back(float(it.cpu_load));
|
||||
arr.erase(arr.begin());
|
||||
}
|
||||
HUDElements.max = 100; HUDElements.min = 0;
|
||||
ImGui::TextColored(HUDElements.colors.engine, "%s", "CPU Load");
|
||||
}
|
||||
|
||||
if (value == "gpu_load"){
|
||||
for (auto& it : graph_data){
|
||||
arr.push_back(float(it.gpu_load));
|
||||
arr.erase(arr.begin());
|
||||
}
|
||||
HUDElements.max = 100; HUDElements.min = 0;
|
||||
ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Load");
|
||||
}
|
||||
|
||||
if (value == "cpu_temp"){
|
||||
for (auto& it : graph_data){
|
||||
arr.push_back(float(it.cpu_temp));
|
||||
arr.erase(arr.begin());
|
||||
}
|
||||
if (int(arr.back()) > HUDElements.cpu_temp_max)
|
||||
HUDElements.cpu_temp_max = arr.back();
|
||||
|
||||
HUDElements.max = HUDElements.cpu_temp_max;
|
||||
HUDElements.min = 0;
|
||||
ImGui::TextColored(HUDElements.colors.engine, "%s", "CPU Temp");
|
||||
}
|
||||
|
||||
if (value == "gpu_temp"){
|
||||
for (auto& it : graph_data){
|
||||
arr.push_back(float(it.gpu_temp));
|
||||
arr.erase(arr.begin());
|
||||
}
|
||||
if (int(arr.back()) > HUDElements.gpu_temp_max)
|
||||
HUDElements.gpu_temp_max = arr.back();
|
||||
|
||||
HUDElements.max = HUDElements.gpu_temp_max;
|
||||
HUDElements.min = 0;
|
||||
ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Temp");
|
||||
}
|
||||
|
||||
if (value == "gpu_core_clock"){
|
||||
for (auto& it : graph_data){
|
||||
arr.push_back(float(it.gpu_core_clock));
|
||||
arr.erase(arr.begin());
|
||||
}
|
||||
if (int(arr.back()) > HUDElements.gpu_core_max)
|
||||
HUDElements.gpu_core_max = arr.back();
|
||||
|
||||
HUDElements.max = HUDElements.gpu_core_max;
|
||||
HUDElements.min = 0;
|
||||
ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Core Clock");
|
||||
}
|
||||
|
||||
if (value == "gpu_mem_clock"){
|
||||
for (auto& it : graph_data){
|
||||
arr.push_back(float(it.gpu_mem_clock));
|
||||
arr.erase(arr.begin());
|
||||
}
|
||||
if (int(arr.back()) > HUDElements.gpu_mem_max)
|
||||
HUDElements.gpu_mem_max = arr.back();
|
||||
|
||||
HUDElements.max = HUDElements.gpu_mem_max;
|
||||
HUDElements.min = 0;
|
||||
ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Mem Clock");
|
||||
}
|
||||
|
||||
if (value == "vram"){
|
||||
for (auto& it : graph_data){
|
||||
arr.push_back(float(it.gpu_vram_used));
|
||||
arr.erase(arr.begin());
|
||||
}
|
||||
|
||||
HUDElements.max = gpu_info.memoryTotal;
|
||||
HUDElements.min = 0;
|
||||
ImGui::TextColored(HUDElements.colors.engine, "%s", "VRAM");
|
||||
}
|
||||
|
||||
if (value == "ram"){
|
||||
if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_ram])
|
||||
HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_ram] = true;
|
||||
for (auto& it : graph_data){
|
||||
arr.push_back(float(it.ram_used));
|
||||
arr.erase(arr.begin());
|
||||
}
|
||||
|
||||
HUDElements.max = memmax;
|
||||
HUDElements.min = 0;
|
||||
ImGui::TextColored(HUDElements.colors.engine, "%s", "RAM");
|
||||
}
|
||||
ImGui::PopFont();
|
||||
ImGui::Dummy(ImVec2(0.0f,5.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
ImGui::TableNextRow();
|
||||
if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_histogram]){
|
||||
ImGui::PlotLines("", arr.data(),
|
||||
arr.size(), 0,
|
||||
NULL, HUDElements.min, HUDElements.max,
|
||||
ImVec2(ImGui::GetContentRegionAvailWidth() * HUDElements.params->table_columns, 50));
|
||||
} else {
|
||||
ImGui::PlotHistogram("", arr.data(),
|
||||
arr.size(), 0,
|
||||
NULL, HUDElements.min, HUDElements.max,
|
||||
ImVec2(ImGui::GetContentRegionAvailWidth() * HUDElements.params->table_columns, 50));
|
||||
}
|
||||
ImGui::Dummy(ImVec2(0.0f,5.0f));
|
||||
ImGui::PopStyleColor(1);
|
||||
}
|
||||
|
||||
void HudElements::sort_elements(std::pair<std::string, std::string> option){
|
||||
auto param = option.first;
|
||||
auto value = option.second;
|
||||
|
||||
if (param == "version") { ordered_functions.push_back({version, value}); }
|
||||
if (param == "time") { ordered_functions.push_back({time, value}); }
|
||||
if (param == "gpu_stats") { ordered_functions.push_back({gpu_stats, value}); }
|
||||
if (param == "cpu_stats") { ordered_functions.push_back({cpu_stats, value}); }
|
||||
if (param == "core_load") { ordered_functions.push_back({core_load, value}); }
|
||||
if (param == "io_stats") { ordered_functions.push_back({io_stats, value}); }
|
||||
if (param == "vram") { ordered_functions.push_back({vram, value}); }
|
||||
if (param == "ram") { ordered_functions.push_back({ram, value}); }
|
||||
if (param == "fps") { ordered_functions.push_back({fps, value}); }
|
||||
if (param == "engine_version") { ordered_functions.push_back({engine_version, value}); }
|
||||
if (param == "gpu_name") { ordered_functions.push_back({gpu_name, value}); }
|
||||
if (param == "vulkan_driver") { ordered_functions.push_back({vulkan_driver, value}); }
|
||||
if (param == "arch") { ordered_functions.push_back({arch, value}); }
|
||||
if (param == "wine") { ordered_functions.push_back({wine, value}); }
|
||||
if (param == "frame_timing") { ordered_functions.push_back({frame_timing, value}); }
|
||||
if (param == "media_player") { ordered_functions.push_back({media_player, value}); }
|
||||
if (param == "graphs"){
|
||||
if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_graphs])
|
||||
HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_graphs] = true;
|
||||
auto values = str_tokenize(value);
|
||||
for (auto& value : values) {
|
||||
if (find(permitted_params.begin(), permitted_params.end(), value) != permitted_params.end())
|
||||
ordered_functions.push_back({graphs, value});
|
||||
else
|
||||
printf("MANGOHUD: Unrecognized graph type: %s\n", value.c_str());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void HudElements::legacy_elements(){
|
||||
string value = "NULL";
|
||||
ordered_functions.clear();
|
||||
ordered_functions.push_back({time, value});
|
||||
ordered_functions.push_back({version, value});
|
||||
ordered_functions.push_back({gpu_stats, value});
|
||||
ordered_functions.push_back({cpu_stats, value});
|
||||
ordered_functions.push_back({core_load, value});
|
||||
ordered_functions.push_back({io_stats, value});
|
||||
ordered_functions.push_back({vram, value});
|
||||
ordered_functions.push_back({ram, value});
|
||||
ordered_functions.push_back({fps, value});
|
||||
ordered_functions.push_back({engine_version, value});
|
||||
ordered_functions.push_back({gpu_name, value});
|
||||
ordered_functions.push_back({vulkan_driver, value});
|
||||
ordered_functions.push_back({arch, value});
|
||||
ordered_functions.push_back({wine, value});
|
||||
ordered_functions.push_back({frame_timing, value});
|
||||
ordered_functions.push_back({media_player, value});
|
||||
}
|
||||
|
||||
HudElements HUDElements;
|
@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
#include "overlay.h"
|
||||
#include "overlay_params.h"
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
class HudElements{
|
||||
public:
|
||||
struct swapchain_stats *sw_stats;
|
||||
struct overlay_params *params;
|
||||
float ralign_width;
|
||||
float old_scale;
|
||||
bool is_vulkan;
|
||||
int place;
|
||||
std::vector<std::pair<std::string, std::string>> options;
|
||||
std::vector<std::pair<void(*)(), std::string >> ordered_functions;
|
||||
int min, max, gpu_core_max, gpu_mem_max, cpu_temp_max, gpu_temp_max;
|
||||
std::vector<std::string> permitted_params = {
|
||||
"gpu_load", "cpu_load", "gpu_core_clock", "gpu_mem_clock",
|
||||
"vram", "ram", "cpu_temp", "gpu_temp"
|
||||
};
|
||||
void sort_elements(std::pair<std::string, std::string> option);
|
||||
void legacy_elements();
|
||||
static void version();
|
||||
static void time();
|
||||
static void gpu_stats();
|
||||
static void cpu_stats();
|
||||
static void core_load();
|
||||
static void io_stats();
|
||||
static void vram();
|
||||
static void ram();
|
||||
static void fps();
|
||||
static void engine_version();
|
||||
static void gpu_name();
|
||||
static void vulkan_driver();
|
||||
static void arch();
|
||||
static void wine();
|
||||
static void frame_timing();
|
||||
static void media_player();
|
||||
static void graphs();
|
||||
|
||||
void convert_colors(struct overlay_params& params);
|
||||
void convert_colors(bool do_conv, struct overlay_params& params);
|
||||
struct hud_colors {
|
||||
bool convert, update;
|
||||
ImVec4 cpu,
|
||||
gpu,
|
||||
vram,
|
||||
ram,
|
||||
engine,
|
||||
io,
|
||||
frametime,
|
||||
background,
|
||||
text,
|
||||
media_player,
|
||||
wine,
|
||||
gpu_load_low,
|
||||
gpu_load_med,
|
||||
gpu_load_high,
|
||||
cpu_load_low,
|
||||
cpu_load_med,
|
||||
cpu_load_high;
|
||||
} colors {};
|
||||
};
|
||||
|
||||
extern HudElements HUDElements;
|
@ -0,0 +1,109 @@
|
||||
#include "overlay.h"
|
||||
#include "timing.hpp"
|
||||
#include "logging.h"
|
||||
#include "keybinds.h"
|
||||
|
||||
void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& params, uint32_t vendorID){
|
||||
using namespace std::chrono_literals;
|
||||
bool pressed = false; // FIXME just a placeholder until wayland support
|
||||
auto now = Clock::now(); /* us */
|
||||
auto elapsedF2 = now - last_f2_press;
|
||||
auto elapsedFpsLimitToggle = now - toggle_fps_limit_press;
|
||||
auto elapsedF12 = now - last_f12_press;
|
||||
auto elapsedReloadCfg = now - reload_cfg_press;
|
||||
auto elapsedUpload = now - last_upload_press;
|
||||
|
||||
auto keyPressDelay = 500ms;
|
||||
|
||||
if (elapsedF2 >= keyPressDelay){
|
||||
#if defined(HAVE_X11) || defined(_WIN32)
|
||||
pressed = keys_are_pressed(params.toggle_logging);
|
||||
#else
|
||||
pressed = false;
|
||||
#endif
|
||||
if (pressed && (now - logger->last_log_end() > 11s)) {
|
||||
last_f2_press = now;
|
||||
if (logger->is_active()) {
|
||||
logger->stop_logging();
|
||||
} else {
|
||||
logger->start_logging();
|
||||
std::thread(update_hw_info, std::ref(sw_stats), std::ref(params),
|
||||
vendorID)
|
||||
.detach();
|
||||
benchmark.fps_data.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (elapsedFpsLimitToggle >= keyPressDelay){
|
||||
#if defined(HAVE_X11) || defined(_WIN32)
|
||||
pressed = keys_are_pressed(params.toggle_fps_limit);
|
||||
#else
|
||||
pressed = false;
|
||||
#endif
|
||||
if (pressed){
|
||||
toggle_fps_limit_press = now;
|
||||
for (size_t i = 0; i < params.fps_limit.size(); i++){
|
||||
uint32_t fps_limit = params.fps_limit[i];
|
||||
// current fps limit equals vector entry, use next / first
|
||||
if((fps_limit > 0 && fps_limit_stats.targetFrameTime == std::chrono::duration_cast<Clock::duration>(std::chrono::duration<double>(1) / params.fps_limit[i]))
|
||||
|| (fps_limit == 0 && fps_limit_stats.targetFrameTime == fps_limit_stats.targetFrameTime.zero())) {
|
||||
uint32_t newFpsLimit = i+1 == params.fps_limit.size() ? params.fps_limit[0] : params.fps_limit[i+1];
|
||||
if(newFpsLimit > 0) {
|
||||
fps_limit_stats.targetFrameTime = std::chrono::duration_cast<Clock::duration>(std::chrono::duration<double>(1) / newFpsLimit);
|
||||
} else {
|
||||
fps_limit_stats.targetFrameTime = {};
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (elapsedF12 >= keyPressDelay){
|
||||
#if defined(HAVE_X11) || defined(_WIN32)
|
||||
pressed = keys_are_pressed(params.toggle_hud);
|
||||
#else
|
||||
pressed = false;
|
||||
#endif
|
||||
if (pressed){
|
||||
last_f12_press = now;
|
||||
params.no_display = !params.no_display;
|
||||
}
|
||||
}
|
||||
|
||||
if (elapsedReloadCfg >= keyPressDelay){
|
||||
#if defined(HAVE_X11) || defined(_WIN32)
|
||||
pressed = keys_are_pressed(params.reload_cfg);
|
||||
#else
|
||||
pressed = false;
|
||||
#endif
|
||||
if (pressed){
|
||||
parse_overlay_config(¶ms, getenv("MANGOHUD_CONFIG"));
|
||||
reload_cfg_press = now;
|
||||
}
|
||||
}
|
||||
|
||||
if (params.permit_upload && elapsedUpload >= keyPressDelay){
|
||||
#if defined(HAVE_X11) || defined(_WIN32)
|
||||
pressed = keys_are_pressed(params.upload_log);
|
||||
#else
|
||||
pressed = false;
|
||||
#endif
|
||||
if (pressed){
|
||||
last_upload_press = now;
|
||||
logger->upload_last_log();
|
||||
}
|
||||
}
|
||||
if (params.permit_upload && elapsedUpload >= keyPressDelay){
|
||||
#if defined(HAVE_X11) || defined(_WIN32)
|
||||
pressed = keys_are_pressed(params.upload_logs);
|
||||
#else
|
||||
pressed = false;
|
||||
#endif
|
||||
if (pressed){
|
||||
last_upload_press = now;
|
||||
logger->upload_last_logs();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
#include <windows.h>
|
||||
#include <iostream>
|
||||
#include "nvidia_info.h"
|
||||
#include "gpu.h"
|
||||
|
||||
// magic numbers, do not change them
|
||||
#define NVAPI_MAX_PHYSICAL_GPUS 64
|
||||
#define NVAPI_MAX_USAGES_PER_GPU 34
|
||||
|
||||
// function pointer types
|
||||
typedef int *(*NvAPI_QueryInterface_t)(unsigned int offset);
|
||||
typedef int (*NvAPI_Initialize_t)();
|
||||
typedef int (*NvAPI_EnumPhysicalGPUs_t)(int **handles, int *count);
|
||||
typedef int (*NvAPI_GPU_GetUsages_t)(int *handle, unsigned int *usages);
|
||||
|
||||
NvAPI_QueryInterface_t NvAPI_QueryInterface = NULL;
|
||||
NvAPI_Initialize_t NvAPI_Initialize = NULL;
|
||||
NvAPI_EnumPhysicalGPUs_t NvAPI_EnumPhysicalGPUs = NULL;
|
||||
NvAPI_GPU_GetUsages_t NvAPI_GPU_GetUsages = NULL;
|
||||
HMODULE hmod;
|
||||
bool init_nvapi_bool;
|
||||
int *gpuHandles[NVAPI_MAX_PHYSICAL_GPUS] = { NULL };
|
||||
int gpuCount = 0;
|
||||
unsigned int gpuUsages[NVAPI_MAX_USAGES_PER_GPU] = { 0 };
|
||||
|
||||
bool checkNVAPI(){
|
||||
|
||||
#if _WIN64
|
||||
hmod = LoadLibraryA("nvapi64.dll");
|
||||
#else
|
||||
hmod = LoadLibraryA("nvapi.dll");
|
||||
#endif
|
||||
|
||||
if (hmod == NULL)
|
||||
{
|
||||
printf("Failed to load nvapi.dll");
|
||||
return false;
|
||||
}
|
||||
NvAPI_QueryInterface = (NvAPI_QueryInterface_t) GetProcAddress(hmod, "nvapi_QueryInterface");
|
||||
NvAPI_Initialize = (NvAPI_Initialize_t) (*NvAPI_QueryInterface)(0x0150E828);
|
||||
NvAPI_EnumPhysicalGPUs = (NvAPI_EnumPhysicalGPUs_t) (*NvAPI_QueryInterface)(0xE5AC921F);
|
||||
NvAPI_GPU_GetUsages = (NvAPI_GPU_GetUsages_t) (*NvAPI_QueryInterface)(0x189A1FDF);
|
||||
if (NvAPI_Initialize == NULL || NvAPI_EnumPhysicalGPUs == NULL ||
|
||||
NvAPI_EnumPhysicalGPUs == NULL || NvAPI_GPU_GetUsages == NULL)
|
||||
{
|
||||
std::cerr << "Couldn't get functions in nvapi.dll" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
(*NvAPI_Initialize)();
|
||||
|
||||
int *gpuHandles[NVAPI_MAX_PHYSICAL_GPUS] = { NULL };
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void nvapi_util()
|
||||
{
|
||||
if (!init_nvapi_bool){
|
||||
init_nvapi_bool = checkNVAPI();
|
||||
}
|
||||
|
||||
gpuUsages[0] = (NVAPI_MAX_USAGES_PER_GPU * 4) | 0x10000;
|
||||
(*NvAPI_EnumPhysicalGPUs)(gpuHandles, &gpuCount);
|
||||
(*NvAPI_GPU_GetUsages)(gpuHandles[0], gpuUsages);
|
||||
gpu_info.load = gpuUsages[3];
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,36 @@
|
||||
#include "kiero.h"
|
||||
|
||||
#if KIERO_INCLUDE_D3D11
|
||||
|
||||
#include "d3d11_hook.h"
|
||||
#include <d3d11.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "d3d_shared.h"
|
||||
|
||||
typedef long(__stdcall* Present)(IDXGISwapChain*, UINT, UINT);
|
||||
static Present oPresent = NULL;
|
||||
|
||||
long __stdcall hkPresent11(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
static auto addr = _ReturnAddress();
|
||||
if(addr == _ReturnAddress()){
|
||||
#else
|
||||
static auto addr = __builtin_return_address(0);
|
||||
if(addr == __builtin_return_address(0)){
|
||||
#endif
|
||||
d3d_run();
|
||||
}
|
||||
return oPresent(pSwapChain, SyncInterval, Flags);
|
||||
}
|
||||
|
||||
void impl::d3d11::init()
|
||||
{
|
||||
printf("init d3d11\n");
|
||||
auto ret = kiero::bind(8, (void**)&oPresent, reinterpret_cast<void *>(hkPresent11));
|
||||
assert(ret == kiero::Status::Success);
|
||||
init_d3d_shared();
|
||||
}
|
||||
|
||||
#endif // KIERO_INCLUDE_D3D11
|
@ -0,0 +1,13 @@
|
||||
#ifndef __D3D11_IMPL_H__
|
||||
#define __D3D11_IMPL_H__
|
||||
|
||||
namespace impl
|
||||
{
|
||||
namespace d3d11
|
||||
{
|
||||
void init();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // __D3D11_IMPL_H__
|
@ -0,0 +1,22 @@
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include "kiero.h"
|
||||
#include "d3d12_hook.h"
|
||||
#include "d3d_shared.h"
|
||||
#include "../overlay.h"
|
||||
|
||||
typedef long(__fastcall* PresentD3D12) (IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags);
|
||||
PresentD3D12 oPresentD3D12;
|
||||
|
||||
long __fastcall hkPresent12(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT Flags){
|
||||
d3d_run();
|
||||
return oPresentD3D12(pSwapChain, SyncInterval, Flags);
|
||||
}
|
||||
|
||||
void impl::d3d12::init()
|
||||
{
|
||||
printf("init d3d12\n");
|
||||
auto ret = kiero::bind(140, (void**)&oPresentD3D12, reinterpret_cast<void*>(hkPresent12));
|
||||
assert(ret == kiero::Status::Success);
|
||||
init_d3d_shared();
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_5.h>
|
||||
#include <dxgi1_4.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <d3d12.h>
|
||||
#else
|
||||
#include "/usr/include/wine/windows/d3d12.h"
|
||||
#endif
|
||||
#ifndef __D3D12_IMPL_H__
|
||||
#define __D3D12_IMPL_H__
|
||||
|
||||
namespace impl
|
||||
{
|
||||
namespace d3d12
|
||||
{
|
||||
void init();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // __D3D12_IMPL_H__
|
@ -0,0 +1,22 @@
|
||||
#include "d3d_shared.h"
|
||||
#include "overlay.h"
|
||||
|
||||
bool cfg_inited = false;
|
||||
ImVec2 window_size;
|
||||
overlay_params params {};
|
||||
struct swapchain_stats sw_stats {};
|
||||
uint32_t vendorID;
|
||||
|
||||
void init_d3d_shared(){
|
||||
vendorID = get_device_id_dxgi();
|
||||
if (cfg_inited)
|
||||
return;
|
||||
parse_overlay_config(¶ms, getenv("MANGOHUD_CONFIG"));
|
||||
cfg_inited = true;
|
||||
// init_cpu_stats(params);
|
||||
}
|
||||
|
||||
void d3d_run(){
|
||||
check_keybinds(sw_stats, params, vendorID);
|
||||
update_hud_info(sw_stats, params, vendorID);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
#include "../overlay.h"
|
||||
|
||||
extern bool cfg_inited;
|
||||
extern ImVec2 window_size;
|
||||
extern struct overlay_params params;
|
||||
extern struct swapchain_stats sw_stats;
|
||||
extern uint32_t vendorID;
|
||||
|
||||
extern void init_d3d_shared(void);
|
||||
extern void d3d_run(void);
|
||||
extern uint32_t get_device_id_dxgi(void);
|
@ -0,0 +1,44 @@
|
||||
#include "kiero.h"
|
||||
#include "windows.h"
|
||||
#include <dxgi.h>
|
||||
#include "kiero.h"
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef _UNICODE
|
||||
# define KIERO_TEXT(text) L##text
|
||||
#else
|
||||
# define KIERO_TEXT(text) text
|
||||
#endif
|
||||
|
||||
uint32_t get_device_id_dxgi(){
|
||||
HMODULE libDXGI;
|
||||
if ((libDXGI = ::GetModuleHandle(KIERO_TEXT("dxgi.dll"))) == NULL){
|
||||
printf("dxgi not found\n");
|
||||
return 0;
|
||||
}
|
||||
auto CreateDXGIFactory = reinterpret_cast<decltype(&::CreateDXGIFactory)>(::GetProcAddress(libDXGI, "CreateDXGIFactory"));
|
||||
if (!CreateDXGIFactory)
|
||||
{
|
||||
printf("can't create dxgi factory\n");
|
||||
return 0;
|
||||
}
|
||||
IDXGIAdapter* dxgi_adapter;
|
||||
IDXGIFactory* dxgi_factory;
|
||||
if (((long(__stdcall*)(const IID&, void**))(CreateDXGIFactory))(__uuidof(IDXGIFactory), (void**)&dxgi_factory) < 0)
|
||||
{
|
||||
printf("can't assign factory\n");
|
||||
return 0;
|
||||
}
|
||||
DXGI_ADAPTER_DESC AdapterDesc;
|
||||
int i;
|
||||
for (i = 0; SUCCEEDED(dxgi_factory->EnumAdapters(i, &dxgi_adapter)); i++) {
|
||||
dxgi_adapter->GetDesc(&AdapterDesc);
|
||||
if (AdapterDesc.VendorId == 0x10de)
|
||||
return AdapterDesc.VendorId;
|
||||
if (AdapterDesc.VendorId == 0x1002)
|
||||
return AdapterDesc.VendorId;
|
||||
if (AdapterDesc.VendorId == 0x8086)
|
||||
return AdapterDesc.VendorId;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,731 @@
|
||||
#include "kiero.h"
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
#include <cstdio>
|
||||
|
||||
#if KIERO_INCLUDE_D3D9
|
||||
# include <d3d9.h>
|
||||
#endif
|
||||
|
||||
#if KIERO_INCLUDE_D3D10
|
||||
# include <dxgi.h>
|
||||
# include <d3d10_1.h>
|
||||
# include <d3d10.h>
|
||||
#endif
|
||||
|
||||
#if KIERO_INCLUDE_D3D11
|
||||
# include <dxgi.h>
|
||||
# include <d3d11.h>
|
||||
#endif
|
||||
|
||||
#if KIERO_INCLUDE_D3D12
|
||||
# include <dxgi.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <d3d12.h>
|
||||
#else
|
||||
#include "/usr/include/wine/windows/d3d12.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if KIERO_INCLUDE_OPENGL
|
||||
# include <gl/GL.h>
|
||||
#endif
|
||||
|
||||
#if KIERO_INCLUDE_VULKAN
|
||||
# include <vulkan/vulkan.h>
|
||||
#endif
|
||||
|
||||
#if KIERO_USE_MINHOOK
|
||||
# include "MinHook.h"
|
||||
#endif
|
||||
|
||||
#ifdef _UNICODE
|
||||
# define KIERO_TEXT(text) L##text
|
||||
#else
|
||||
# define KIERO_TEXT(text) text
|
||||
#endif
|
||||
|
||||
#define KIERO_ARRAY_SIZE(arr) ((size_t)(sizeof(arr)/sizeof(arr[0])))
|
||||
|
||||
static kiero::RenderType::Enum g_renderType = kiero::RenderType::None;
|
||||
static uint150_t* g_methodsTable = NULL;
|
||||
|
||||
kiero::Status::Enum kiero::init(RenderType::Enum _renderType)
|
||||
{
|
||||
if (g_renderType != RenderType::None)
|
||||
{
|
||||
return Status::AlreadyInitializedError;
|
||||
}
|
||||
|
||||
if (_renderType != RenderType::None)
|
||||
{
|
||||
if (_renderType >= RenderType::D3D9 && _renderType <= RenderType::D3D12)
|
||||
{
|
||||
WNDCLASSEX windowClass;
|
||||
windowClass.cbSize = sizeof(WNDCLASSEX);
|
||||
windowClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
windowClass.lpfnWndProc = DefWindowProc;
|
||||
windowClass.cbClsExtra = 0;
|
||||
windowClass.cbWndExtra = 0;
|
||||
windowClass.hInstance = GetModuleHandle(NULL);
|
||||
windowClass.hIcon = NULL;
|
||||
windowClass.hCursor = NULL;
|
||||
windowClass.hbrBackground = NULL;
|
||||
windowClass.lpszMenuName = NULL;
|
||||
windowClass.lpszClassName = KIERO_TEXT("Kiero");
|
||||
windowClass.hIconSm = NULL;
|
||||
|
||||
::RegisterClassEx(&windowClass);
|
||||
|
||||
HWND window = ::CreateWindow(windowClass.lpszClassName, KIERO_TEXT("Kiero DirectX Window"), WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, windowClass.hInstance, NULL);
|
||||
|
||||
if (_renderType == RenderType::D3D9)
|
||||
{
|
||||
#if KIERO_INCLUDE_D3D9
|
||||
HMODULE libD3D9;
|
||||
if ((libD3D9 = ::GetModuleHandle(KIERO_TEXT("d3d9.dll"))) == NULL)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::ModuleNotFoundError;
|
||||
}
|
||||
|
||||
void* Direct3DCreate9;
|
||||
if ((Direct3DCreate9 = ::GetProcAddress(libD3D9, "Direct3DCreate9")) == NULL)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
LPDIRECT3D9 direct3D9;
|
||||
if ((direct3D9 = ((LPDIRECT3D9(__stdcall*)(uint32_t))(Direct3DCreate9))(D3D_SDK_VERSION)) == NULL)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
D3DDISPLAYMODE displayMode;
|
||||
if (direct3D9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode) < 0)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
D3DPRESENT_PARAMETERS params;
|
||||
params.BackBufferWidth = 0;
|
||||
params.BackBufferHeight = 0;
|
||||
params.BackBufferFormat = displayMode.Format;
|
||||
params.BackBufferCount = 0;
|
||||
params.MultiSampleType = D3DMULTISAMPLE_NONE;
|
||||
params.MultiSampleQuality = NULL;
|
||||
params.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
params.hDeviceWindow = window;
|
||||
params.Windowed = 1;
|
||||
params.EnableAutoDepthStencil = 0;
|
||||
params.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
|
||||
params.Flags = NULL;
|
||||
params.FullScreen_RefreshRateInHz = 0;
|
||||
params.PresentationInterval = 0;
|
||||
|
||||
LPDIRECT3DDEVICE9 device;
|
||||
if (direct3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_DISABLE_DRIVER_MANAGEMENT, ¶ms, &device) < 0)
|
||||
{
|
||||
direct3D9->Release();
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
g_methodsTable = (uint150_t*)::calloc(119, sizeof(uint150_t));
|
||||
::memcpy(g_methodsTable, *(uint150_t**)device, 119 * sizeof(uint150_t));
|
||||
|
||||
#if KIERO_USE_MINHOOK
|
||||
MH_Initialize();
|
||||
#endif
|
||||
|
||||
direct3D9->Release();
|
||||
direct3D9 = NULL;
|
||||
|
||||
device->Release();
|
||||
device = NULL;
|
||||
|
||||
g_renderType = RenderType::D3D9;
|
||||
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
|
||||
return Status::Success;
|
||||
#endif
|
||||
}
|
||||
else if (_renderType == RenderType::D3D10)
|
||||
{
|
||||
#if KIERO_INCLUDE_D3D10
|
||||
HMODULE libDXGI;
|
||||
HMODULE libD3D10;
|
||||
if ((libDXGI = ::GetModuleHandle(KIERO_TEXT("dxgi.dll"))) == NULL || (libD3D10 = ::GetModuleHandle(KIERO_TEXT("d3d10.dll"))) == NULL)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::ModuleNotFoundError;
|
||||
}
|
||||
|
||||
void* CreateDXGIFactory;
|
||||
if ((CreateDXGIFactory = ::GetProcAddress(libDXGI, "CreateDXGIFactory")) == NULL)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
IDXGIFactory* factory;
|
||||
if (((long(__stdcall*)(const IID&, void**))(CreateDXGIFactory))(__uuidof(IDXGIFactory), (void**)&factory) < 0)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
IDXGIAdapter* adapter;
|
||||
if (factory->EnumAdapters(0, &adapter) == DXGI_ERROR_NOT_FOUND)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
void* D3D10CreateDeviceAndSwapChain;
|
||||
if ((D3D10CreateDeviceAndSwapChain = ::GetProcAddress(libD3D10, "D3D10CreateDeviceAndSwapChain")) == NULL)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
DXGI_RATIONAL refreshRate;
|
||||
refreshRate.Numerator = 60;
|
||||
refreshRate.Denominator = 1;
|
||||
|
||||
DXGI_MODE_DESC bufferDesc;
|
||||
bufferDesc.Width = 100;
|
||||
bufferDesc.Height = 100;
|
||||
bufferDesc.RefreshRate = refreshRate;
|
||||
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
|
||||
DXGI_SAMPLE_DESC sampleDesc;
|
||||
sampleDesc.Count = 1;
|
||||
sampleDesc.Quality = 0;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
||||
swapChainDesc.BufferDesc = bufferDesc;
|
||||
swapChainDesc.SampleDesc = sampleDesc;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferCount = 1;
|
||||
swapChainDesc.OutputWindow = window;
|
||||
swapChainDesc.Windowed = 1;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
|
||||
IDXGISwapChain* swapChain;
|
||||
ID3D10Device* device;
|
||||
|
||||
if (((long(__stdcall*)(
|
||||
IDXGIAdapter*,
|
||||
D3D10_DRIVER_TYPE,
|
||||
HMODULE,
|
||||
UINT,
|
||||
UINT,
|
||||
DXGI_SWAP_CHAIN_DESC*,
|
||||
IDXGISwapChain**,
|
||||
ID3D10Device**))(D3D10CreateDeviceAndSwapChain))(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &swapChainDesc, &swapChain, &device) < 0)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
g_methodsTable = (uint150_t*)::calloc(116, sizeof(uint150_t));
|
||||
::memcpy(g_methodsTable, *(uint150_t**)swapChain, 18 * sizeof(uint150_t));
|
||||
::memcpy(g_methodsTable + 18, *(uint150_t**)device, 98 * sizeof(uint150_t));
|
||||
|
||||
#if KIERO_USE_MINHOOK
|
||||
MH_Initialize();
|
||||
#endif
|
||||
|
||||
swapChain->Release();
|
||||
swapChain = NULL;
|
||||
|
||||
device->Release();
|
||||
device = NULL;
|
||||
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
|
||||
g_renderType = RenderType::D3D10;
|
||||
|
||||
return Status::Success;
|
||||
#endif
|
||||
}
|
||||
else if (_renderType == RenderType::D3D11)
|
||||
{
|
||||
#if KIERO_INCLUDE_D3D11
|
||||
HMODULE libD3D11;
|
||||
if ((libD3D11 = ::GetModuleHandle(KIERO_TEXT("d3d11.dll"))) == NULL)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::ModuleNotFoundError;
|
||||
}
|
||||
|
||||
auto D3D11CreateDeviceAndSwapChain = reinterpret_cast<decltype(&::D3D11CreateDeviceAndSwapChain)>(::GetProcAddress(libD3D11, "D3D11CreateDeviceAndSwapChain"));
|
||||
if (!D3D11CreateDeviceAndSwapChain)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
D3D_FEATURE_LEVEL featureLevel;
|
||||
const D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_11_0 };
|
||||
|
||||
DXGI_RATIONAL refreshRate;
|
||||
refreshRate.Numerator = 60;
|
||||
refreshRate.Denominator = 1;
|
||||
|
||||
DXGI_MODE_DESC bufferDesc;
|
||||
bufferDesc.Width = 100;
|
||||
bufferDesc.Height = 100;
|
||||
bufferDesc.RefreshRate = refreshRate;
|
||||
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
|
||||
DXGI_SAMPLE_DESC sampleDesc;
|
||||
sampleDesc.Count = 1;
|
||||
sampleDesc.Quality = 0;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
||||
swapChainDesc.BufferDesc = bufferDesc;
|
||||
swapChainDesc.SampleDesc = sampleDesc;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferCount = 1;
|
||||
swapChainDesc.OutputWindow = window;
|
||||
swapChainDesc.Windowed = 1;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
|
||||
IDXGISwapChain* swapChain;
|
||||
ID3D11Device* device;
|
||||
ID3D11DeviceContext* context;
|
||||
|
||||
if (((long(__stdcall*)(
|
||||
IDXGIAdapter*,
|
||||
D3D_DRIVER_TYPE,
|
||||
HMODULE,
|
||||
UINT,
|
||||
const D3D_FEATURE_LEVEL*,
|
||||
UINT,
|
||||
UINT,
|
||||
const DXGI_SWAP_CHAIN_DESC*,
|
||||
IDXGISwapChain**,
|
||||
ID3D11Device**,
|
||||
D3D_FEATURE_LEVEL*,
|
||||
ID3D11DeviceContext**))(D3D11CreateDeviceAndSwapChain))(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, featureLevels, 2, D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &device, &featureLevel, &context) < 0)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
g_methodsTable = (uint150_t*)::calloc(205, sizeof(uint150_t));
|
||||
::memcpy(g_methodsTable, *(uint150_t**)swapChain, 18 * sizeof(uint150_t));
|
||||
::memcpy(g_methodsTable + 18, *(uint150_t**)device, 43 * sizeof(uint150_t));
|
||||
::memcpy(g_methodsTable + 18 + 43, *(uint150_t**)context, 144 * sizeof(uint150_t));
|
||||
|
||||
#if KIERO_USE_MINHOOK
|
||||
MH_Initialize();
|
||||
#endif
|
||||
|
||||
swapChain->Release();
|
||||
swapChain = NULL;
|
||||
|
||||
device->Release();
|
||||
device = NULL;
|
||||
|
||||
context->Release();
|
||||
context = NULL;
|
||||
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
|
||||
g_renderType = RenderType::D3D11;
|
||||
|
||||
return Status::Success;
|
||||
#endif
|
||||
}
|
||||
else if (_renderType == RenderType::D3D12)
|
||||
{
|
||||
#if KIERO_INCLUDE_D3D12
|
||||
HMODULE libDXGI;
|
||||
HMODULE libD3D12;
|
||||
if ((libDXGI = ::GetModuleHandle(KIERO_TEXT("dxgi.dll"))) == NULL || (libD3D12 = ::GetModuleHandle(KIERO_TEXT("d3d12.dll"))) == NULL)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::ModuleNotFoundError;
|
||||
}
|
||||
|
||||
auto CreateDXGIFactory = reinterpret_cast<decltype(&::CreateDXGIFactory)>(::GetProcAddress(libDXGI, "CreateDXGIFactory"));
|
||||
if (!CreateDXGIFactory)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
IDXGIFactory* factory;
|
||||
if (((long(__stdcall*)(const IID&, void**))(CreateDXGIFactory))(__uuidof(IDXGIFactory), (void**)&factory) < 0)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
IDXGIAdapter* adapter;
|
||||
if (factory->EnumAdapters(0, &adapter) == DXGI_ERROR_NOT_FOUND)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
auto D3D12CreateDevice = reinterpret_cast<decltype(&::D3D12CreateDevice)>(::GetProcAddress(libD3D12, "D3D12CreateDevice"));
|
||||
if (!D3D12CreateDevice)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
ID3D12Device* device;
|
||||
if (((long(__stdcall*)(IUnknown*, D3D_FEATURE_LEVEL, const IID&, void**))(D3D12CreateDevice))(adapter, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void**)&device) < 0)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc;
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
queueDesc.Priority = 0;
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.NodeMask = 0;
|
||||
|
||||
ID3D12CommandQueue* commandQueue;
|
||||
if (device->CreateCommandQueue(&queueDesc, __uuidof(ID3D12CommandQueue), (void**)&commandQueue) < 0)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
ID3D12CommandAllocator* commandAllocator;
|
||||
if (device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&commandAllocator) < 0)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList* commandList;
|
||||
if (device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, commandAllocator, NULL, __uuidof(ID3D12GraphicsCommandList), (void**)&commandList) < 0)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
DXGI_RATIONAL refreshRate;
|
||||
refreshRate.Numerator = 60;
|
||||
refreshRate.Denominator = 1;
|
||||
|
||||
DXGI_MODE_DESC bufferDesc;
|
||||
bufferDesc.Width = 100;
|
||||
bufferDesc.Height = 100;
|
||||
bufferDesc.RefreshRate = refreshRate;
|
||||
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
|
||||
DXGI_SAMPLE_DESC sampleDesc;
|
||||
sampleDesc.Count = 1;
|
||||
sampleDesc.Quality = 0;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
|
||||
swapChainDesc.BufferDesc = bufferDesc;
|
||||
swapChainDesc.SampleDesc = sampleDesc;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferCount = 2;
|
||||
swapChainDesc.OutputWindow = window;
|
||||
swapChainDesc.Windowed = 1;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
|
||||
IDXGISwapChain* swapChain;
|
||||
if (factory->CreateSwapChain(commandQueue, &swapChainDesc, &swapChain) < 0)
|
||||
{
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
return Status::UnknownError;
|
||||
}
|
||||
|
||||
g_methodsTable = (uint150_t*)::calloc(150, sizeof(uint150_t));
|
||||
::memcpy(g_methodsTable, *(uint150_t**)device, 44 * sizeof(uint150_t));
|
||||
::memcpy(g_methodsTable + 44, *(uint150_t**)commandQueue, 19 * sizeof(uint150_t));
|
||||
::memcpy(g_methodsTable + 44 + 19, *(uint150_t**)commandAllocator, 9 * sizeof(uint150_t));
|
||||
::memcpy(g_methodsTable + 44 + 19 + 9, *(uint150_t**)commandList, 60 * sizeof(uint150_t));
|
||||
::memcpy(g_methodsTable + 44 + 19 + 9 + 60, *(uint150_t**)swapChain, 18 * sizeof(uint150_t));
|
||||
|
||||
#if KIERO_USE_MINHOOK
|
||||
MH_Initialize();
|
||||
#endif
|
||||
|
||||
device->Release();
|
||||
device = NULL;
|
||||
|
||||
commandQueue->Release();
|
||||
commandQueue = NULL;
|
||||
|
||||
commandAllocator->Release();
|
||||
commandAllocator = NULL;
|
||||
|
||||
commandList->Release();
|
||||
commandList = NULL;
|
||||
|
||||
swapChain->Release();
|
||||
swapChain = NULL;
|
||||
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
|
||||
g_renderType = RenderType::D3D12;
|
||||
return Status::Success;
|
||||
#endif
|
||||
}
|
||||
|
||||
::DestroyWindow(window);
|
||||
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
||||
|
||||
return Status::NotSupportedError;
|
||||
}
|
||||
else if (_renderType != RenderType::Auto)
|
||||
{
|
||||
if (_renderType == RenderType::OpenGL)
|
||||
{
|
||||
#if KIERO_INCLUDE_OPENGL
|
||||
HMODULE libOpenGL32;
|
||||
if ((libOpenGL32 = ::GetModuleHandle(KIERO_TEXT("opengl32.dll"))) == NULL)
|
||||
{
|
||||
return Status::ModuleNotFoundError;
|
||||
}
|
||||
|
||||
const char* const methodsNames[] = {
|
||||
"glAccum", "glAlphaFunc", "glAreTexturesResident", "glArrayElement", "glBegin", "glBindTexture", "glBitmap", "glBlendFunc", "glCallList", "glCallLists", "glClear", "glClearAccum",
|
||||
"glClearColor", "glClearDepth", "glClearIndex", "glClearStencil", "glClipPlane", "glColor3b", "glColor3bv", "glColor3d", "glColor3dv", "glColor3f", "glColor3fv", "glColor3i", "glColor3iv",
|
||||
"glColor3s", "glColor3sv", "glColor3ub", "glColor3ubv", "glColor3ui", "glColor3uiv", "glColor3us", "glColor3usv", "glColor4b", "glColor4bv", "glColor4d", "glColor4dv", "glColor4f",
|
||||
"glColor4fv", "glColor4i", "glColor4iv", "glColor4s", "glColor4sv", "glColor4ub", "glColor4ubv", "glColor4ui", "glColor4uiv", "glColor4us", "glColor4usv", "glColorMask", "glColorMaterial",
|
||||
"glColorPointer", "glCopyPixels", "glCopyTexImage1D", "glCopyTexImage2D", "glCopyTexSubImage1D", "glCopyTexSubImage2D", "glCullFaceglCullFace", "glDeleteLists", "glDeleteTextures",
|
||||
"glDepthFunc", "glDepthMask", "glDepthRange", "glDisable", "glDisableClientState", "glDrawArrays", "glDrawBuffer", "glDrawElements", "glDrawPixels", "glEdgeFlag", "glEdgeFlagPointer",
|
||||
"glEdgeFlagv", "glEnable", "glEnableClientState", "glEnd", "glEndList", "glEvalCoord1d", "glEvalCoord1dv", "glEvalCoord1f", "glEvalCoord1fv", "glEvalCoord2d", "glEvalCoord2dv",
|
||||
"glEvalCoord2f", "glEvalCoord2fv", "glEvalMesh1", "glEvalMesh2", "glEvalPoint1", "glEvalPoint2", "glFeedbackBuffer", "glFinish", "glFlush", "glFogf", "glFogfv", "glFogi", "glFogiv",
|
||||
"glFrontFace", "glFrustum", "glGenLists", "glGenTextures", "glGetBooleanv", "glGetClipPlane", "glGetDoublev", "glGetError", "glGetFloatv", "glGetIntegerv", "glGetLightfv", "glGetLightiv",
|
||||
"glGetMapdv", "glGetMapfv", "glGetMapiv", "glGetMaterialfv", "glGetMaterialiv", "glGetPixelMapfv", "glGetPixelMapuiv", "glGetPixelMapusv", "glGetPointerv", "glGetPolygonStipple",
|
||||
"glGetString", "glGetTexEnvfv", "glGetTexEnviv", "glGetTexGendv", "glGetTexGenfv", "glGetTexGeniv", "glGetTexImage", "glGetTexLevelParameterfv", "glGetTexLevelParameteriv",
|
||||
"glGetTexParameterfv", "glGetTexParameteriv", "glHint", "glIndexMask", "glIndexPointer", "glIndexd", "glIndexdv", "glIndexf", "glIndexfv", "glIndexi", "glIndexiv", "glIndexs", "glIndexsv",
|
||||
"glIndexub", "glIndexubv", "glInitNames", "glInterleavedArrays", "glIsEnabled", "glIsList", "glIsTexture", "glLightModelf", "glLightModelfv", "glLightModeli", "glLightModeliv", "glLightf",
|
||||
"glLightfv", "glLighti", "glLightiv", "glLineStipple", "glLineWidth", "glListBase", "glLoadIdentity", "glLoadMatrixd", "glLoadMatrixf", "glLoadName", "glLogicOp", "glMap1d", "glMap1f",
|
||||
"glMap2d", "glMap2f", "glMapGrid1d", "glMapGrid1f", "glMapGrid2d", "glMapGrid2f", "glMaterialf", "glMaterialfv", "glMateriali", "glMaterialiv", "glMatrixMode", "glMultMatrixd",
|
||||
"glMultMatrixf", "glNewList", "glNormal3b", "glNormal3bv", "glNormal3d", "glNormal3dv", "glNormal3f", "glNormal3fv", "glNormal3i", "glNormal3iv", "glNormal3s", "glNormal3sv",
|
||||
"glNormalPointer", "glOrtho", "glPassThrough", "glPixelMapfv", "glPixelMapuiv", "glPixelMapusv", "glPixelStoref", "glPixelStorei", "glPixelTransferf", "glPixelTransferi", "glPixelZoom",
|
||||
"glPointSize", "glPolygonMode", "glPolygonOffset", "glPolygonStipple", "glPopAttrib", "glPopClientAttrib", "glPopMatrix", "glPopName", "glPrioritizeTextures", "glPushAttrib",
|
||||
"glPushClientAttrib", "glPushMatrix", "glPushName", "glRasterPos2d", "glRasterPos2dv", "glRasterPos2f", "glRasterPos2fv", "glRasterPos2i", "glRasterPos2iv", "glRasterPos2s",
|
||||
"glRasterPos2sv", "glRasterPos3d", "glRasterPos3dv", "glRasterPos3f", "glRasterPos3fv", "glRasterPos3i", "glRasterPos3iv", "glRasterPos3s", "glRasterPos3sv", "glRasterPos4d",
|
||||
"glRasterPos4dv", "glRasterPos4f", "glRasterPos4fv", "glRasterPos4i", "glRasterPos4iv", "glRasterPos4s", "glRasterPos4sv", "glReadBuffer", "glReadPixels", "glRectd", "glRectdv", "glRectf",
|
||||
"glRectfv", "glRecti", "glRectiv", "glRects", "glRectsv", "glRenderMode", "glRotated", "glRotatef", "glScaled", "glScalef", "glScissor", "glSelectBuffer", "glShadeModel", "glStencilFunc",
|
||||
"glStencilMask", "glStencilOp", "glTexCoord1d", "glTexCoord1dv", "glTexCoord1f", "glTexCoord1fv", "glTexCoord1i", "glTexCoord1iv", "glTexCoord1s", "glTexCoord1sv", "glTexCoord2d",
|
||||
"glTexCoord2dv", "glTexCoord2f", "glTexCoord2fv", "glTexCoord2i", "glTexCoord2iv", "glTexCoord2s", "glTexCoord2sv", "glTexCoord3d", "glTexCoord3dv", "glTexCoord3f", "glTexCoord3fv",
|
||||
"glTexCoord3i", "glTexCoord3iv", "glTexCoord3s", "glTexCoord3sv", "glTexCoord4d", "glTexCoord4dv", "glTexCoord4f", "glTexCoord4fv", "glTexCoord4i", "glTexCoord4iv", "glTexCoord4s",
|
||||
"glTexCoord4sv", "glTexCoordPointer", "glTexEnvf", "glTexEnvfv", "glTexEnvi", "glTexEnviv", "glTexGend", "glTexGendv", "glTexGenf", "glTexGenfv", "glTexGeni", "glTexGeniv", "glTexImage1D",
|
||||
"glTexImage2D", "glTexParameterf", "glTexParameterfv", "glTexParameteri", "glTexParameteriv", "glTexSubImage1D", "glTexSubImage2D", "glTranslated", "glTranslatef", "glVertex2d",
|
||||
"glVertex2dv", "glVertex2f", "glVertex2fv", "glVertex2i", "glVertex2iv", "glVertex2s", "glVertex2sv", "glVertex3d", "glVertex3dv", "glVertex3f", "glVertex3fv", "glVertex3i", "glVertex3iv",
|
||||
"glVertex3s", "glVertex3sv", "glVertex4d", "glVertex4dv", "glVertex4f", "glVertex4fv", "glVertex4i", "glVertex4iv", "glVertex4s", "glVertex4sv", "glVertexPointer", "glViewport"
|
||||
};
|
||||
|
||||
size_t size = KIERO_ARRAY_SIZE(methodsNames);
|
||||
|
||||
g_methodsTable = (uint150_t*)::calloc(size, sizeof(uint150_t));
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
g_methodsTable[i] = (uint150_t)::GetProcAddress(libOpenGL32, methodsNames[i]);
|
||||
}
|
||||
|
||||
#if KIERO_USE_MINHOOK
|
||||
MH_Initialize();
|
||||
#endif
|
||||
|
||||
g_renderType = RenderType::OpenGL;
|
||||
|
||||
return Status::Success;
|
||||
#endif
|
||||
}
|
||||
else if (_renderType == RenderType::Vulkan)
|
||||
{
|
||||
#if KIERO_INCLUDE_VULKAN
|
||||
HMODULE libVulkan;
|
||||
if ((libVulkan = GetModuleHandle(KIERO_TEXT("vulkan-1.dll"))) == NULL)
|
||||
{
|
||||
return Status::ModuleNotFoundError;
|
||||
}
|
||||
|
||||
const char* const methodsNames[] = {
|
||||
"vkCreateInstance", "vkDestroyInstance", "vkEnumeratePhysicalDevices", "vkGetPhysicalDeviceFeatures", "vkGetPhysicalDeviceFormatProperties", "vkGetPhysicalDeviceImageFormatProperties",
|
||||
"vkGetPhysicalDeviceProperties", "vkGetPhysicalDeviceQueueFamilyProperties", "vkGetPhysicalDeviceMemoryProperties", "vkGetInstanceProcAddr", "vkGetDeviceProcAddr", "vkCreateDevice",
|
||||
"vkDestroyDevice", "vkEnumerateInstanceExtensionProperties", "vkEnumerateDeviceExtensionProperties", "vkEnumerateDeviceLayerProperties", "vkGetDeviceQueue", "vkQueueSubmit", "vkQueueWaitIdle",
|
||||
"vkDeviceWaitIdle", "vkAllocateMemory", "vkFreeMemory", "vkMapMemory", "vkUnmapMemory", "vkFlushMappedMemoryRanges", "vkInvalidateMappedMemoryRanges", "vkGetDeviceMemoryCommitment",
|
||||
"vkBindBufferMemory", "vkBindImageMemory", "vkGetBufferMemoryRequirements", "vkGetImageMemoryRequirements", "vkGetImageSparseMemoryRequirements", "vkGetPhysicalDeviceSparseImageFormatProperties",
|
||||
"vkQueueBindSparse", "vkCreateFence", "vkDestroyFence", "vkResetFences", "vkGetFenceStatus", "vkWaitForFences", "vkCreateSemaphore", "vkDestroySemaphore", "vkCreateEvent", "vkDestroyEvent",
|
||||
"vkGetEventStatus", "vkSetEvent", "vkResetEvent", "vkCreateQueryPool", "vkDestroyQueryPool", "vkGetQueryPoolResults", "vkCreateBuffer", "vkDestroyBuffer", "vkCreateBufferView", "vkDestroyBufferView",
|
||||
"vkCreateImage", "vkDestroyImage", "vkGetImageSubresourceLayout", "vkCreateImageView", "vkDestroyImageView", "vkCreateShaderModule", "vkDestroyShaderModule", "vkCreatePipelineCache",
|
||||
"vkDestroyPipelineCache", "vkGetPipelineCacheData", "vkMergePipelineCaches", "vkCreateGraphicsPipelines", "vkCreateComputePipelines", "vkDestroyPipeline", "vkCreatePipelineLayout",
|
||||
"vkDestroyPipelineLayout", "vkCreateSampler", "vkDestroySampler", "vkCreateDescriptorSetLayout", "vkDestroyDescriptorSetLayout", "vkCreateDescriptorPool", "vkDestroyDescriptorPool",
|
||||
"vkResetDescriptorPool", "vkAllocateDescriptorSets", "vkFreeDescriptorSets", "vkUpdateDescriptorSets", "vkCreateFramebuffer", "vkDestroyFramebuffer", "vkCreateRenderPass", "vkDestroyRenderPass",
|
||||
"vkGetRenderAreaGranularity", "vkCreateCommandPool", "vkDestroyCommandPool", "vkResetCommandPool", "vkAllocateCommandBuffers", "vkFreeCommandBuffers", "vkBeginCommandBuffer", "vkEndCommandBuffer",
|
||||
"vkResetCommandBuffer", "vkCmdBindPipeline", "vkCmdSetViewport", "vkCmdSetScissor", "vkCmdSetLineWidth", "vkCmdSetDepthBias", "vkCmdSetBlendConstants", "vkCmdSetDepthBounds",
|
||||
"vkCmdSetStencilCompareMask", "vkCmdSetStencilWriteMask", "vkCmdSetStencilReference", "vkCmdBindDescriptorSets", "vkCmdBindIndexBuffer", "vkCmdBindVertexBuffers", "vkCmdDraw", "vkCmdDrawIndexed",
|
||||
"vkCmdDrawIndirect", "vkCmdDrawIndexedIndirect", "vkCmdDispatch", "vkCmdDispatchIndirect", "vkCmdCopyBuffer", "vkCmdCopyImage", "vkCmdBlitImage", "vkCmdCopyBufferToImage", "vkCmdCopyImageToBuffer",
|
||||
"vkCmdUpdateBuffer", "vkCmdFillBuffer", "vkCmdClearColorImage", "vkCmdClearDepthStencilImage", "vkCmdClearAttachments", "vkCmdResolveImage", "vkCmdSetEvent", "vkCmdResetEvent", "vkCmdWaitEvents",
|
||||
"vkCmdPipelineBarrier", "vkCmdBeginQuery", "vkCmdEndQuery", "vkCmdResetQueryPool", "vkCmdWriteTimestamp", "vkCmdCopyQueryPoolResults", "vkCmdPushConstants", "vkCmdBeginRenderPass", "vkCmdNextSubpass",
|
||||
"vkCmdEndRenderPass", "vkCmdExecuteCommands"
|
||||
};
|
||||
|
||||
size_t size = KIERO_ARRAY_SIZE(methodsNames);
|
||||
|
||||
g_methodsTable = (uint150_t*)::calloc(size, sizeof(uint150_t));
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
g_methodsTable[i] = (uint150_t)::GetProcAddress(libVulkan, methodsNames[i]);
|
||||
}
|
||||
|
||||
#if KIERO_USE_MINHOOK
|
||||
MH_Initialize();
|
||||
#endif
|
||||
|
||||
g_renderType = RenderType::Vulkan;
|
||||
|
||||
return Status::Success;
|
||||
#endif
|
||||
}
|
||||
|
||||
return Status::NotSupportedError;
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderType::Enum type = RenderType::None;
|
||||
|
||||
if (::GetModuleHandle(KIERO_TEXT("d3d9.dll")) != NULL)
|
||||
{
|
||||
type = RenderType::D3D9;
|
||||
}
|
||||
else if (::GetModuleHandle(KIERO_TEXT("d3d10.dll")) != NULL)
|
||||
{
|
||||
type = RenderType::D3D10;
|
||||
}
|
||||
else if (::GetModuleHandle(KIERO_TEXT("d3d11.dll")) != NULL)
|
||||
{
|
||||
type = RenderType::D3D11;
|
||||
}
|
||||
else if (::GetModuleHandle(KIERO_TEXT("d3d12.dll")) != NULL)
|
||||
{
|
||||
type = RenderType::D3D12;
|
||||
}
|
||||
else if (::GetModuleHandle(KIERO_TEXT("opengl32.dll")) != NULL)
|
||||
{
|
||||
type = RenderType::OpenGL;
|
||||
}
|
||||
else if (::GetModuleHandle(KIERO_TEXT("vulkan-1.dll")) != NULL)
|
||||
{
|
||||
type = RenderType::Vulkan;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Status::NotSupportedError;
|
||||
}
|
||||
|
||||
return init(type);
|
||||
}
|
||||
}
|
||||
|
||||
return Status::Success;
|
||||
}
|
||||
|
||||
void kiero::shutdown()
|
||||
{
|
||||
if (g_renderType != RenderType::None)
|
||||
{
|
||||
#if KIERO_USE_MINHOOK
|
||||
MH_DisableHook(MH_ALL_HOOKS);
|
||||
#endif
|
||||
|
||||
::free(g_methodsTable);
|
||||
g_methodsTable = NULL;
|
||||
g_renderType = RenderType::None;
|
||||
}
|
||||
}
|
||||
|
||||
kiero::Status::Enum kiero::bind(uint16_t _index, void** _original, void* _function)
|
||||
{
|
||||
// TODO: Need own detour function
|
||||
|
||||
assert(_original != NULL && _function != NULL);
|
||||
|
||||
if (g_renderType != RenderType::None)
|
||||
{
|
||||
#if KIERO_USE_MINHOOK
|
||||
void* target = (void*)g_methodsTable[_index];
|
||||
if (MH_CreateHook(target, _function, _original) != MH_OK || MH_EnableHook(target) != MH_OK)
|
||||
{
|
||||
return Status::UnknownError;
|
||||
}
|
||||
#endif
|
||||
|
||||
return Status::Success;
|
||||
}
|
||||
|
||||
return Status::NotInitializedError;
|
||||
}
|
||||
|
||||
void kiero::unbind(uint16_t _index)
|
||||
{
|
||||
if (g_renderType != RenderType::None)
|
||||
{
|
||||
#if KIERO_USE_MINHOOK
|
||||
MH_DisableHook((void*)g_methodsTable[_index]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
kiero::RenderType::Enum kiero::getRenderType()
|
||||
{
|
||||
return g_renderType;
|
||||
}
|
||||
|
||||
uint150_t* kiero::getMethodsTable()
|
||||
{
|
||||
return g_methodsTable;
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
#ifndef __KIERO_H__
|
||||
#define __KIERO_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define KIERO_VERSION "1.2.10"
|
||||
|
||||
#define KIERO_INCLUDE_D3D9 0 // 1 if you need D3D9 hook
|
||||
#define KIERO_INCLUDE_D3D10 0 // 1 if you need D3D10 hook
|
||||
#define KIERO_INCLUDE_D3D11 1 // 1 if you need D3D11 hook
|
||||
#define KIERO_INCLUDE_D3D12 1 // 1 if you need D3D12 hook
|
||||
#define KIERO_INCLUDE_OPENGL 0 // 1 if you need OpenGL hook
|
||||
#define KIERO_INCLUDE_VULKAN 1 // 1 if you need Vulkan hook
|
||||
#define KIERO_USE_MINHOOK 1 // 1 if you will use kiero::bind function
|
||||
|
||||
#define KIERO_ARCH_X64 0
|
||||
#define KIERO_ARCH_X86 0
|
||||
|
||||
#if defined(_M_X64)
|
||||
# undef KIERO_ARCH_X64
|
||||
# define KIERO_ARCH_X64 1
|
||||
#else
|
||||
# undef KIERO_ARCH_X86
|
||||
# define KIERO_ARCH_X86 1
|
||||
#endif
|
||||
|
||||
#if KIERO_ARCH_X64
|
||||
typedef uint64_t uint150_t;
|
||||
#else
|
||||
typedef uint32_t uint150_t;
|
||||
#endif
|
||||
|
||||
namespace kiero
|
||||
{
|
||||
struct Status
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
UnknownError = -1,
|
||||
NotSupportedError = -2,
|
||||
ModuleNotFoundError = -3,
|
||||
|
||||
AlreadyInitializedError = -4,
|
||||
NotInitializedError = -5,
|
||||
|
||||
Success = 0,
|
||||
};
|
||||
};
|
||||
|
||||
struct RenderType
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
None,
|
||||
|
||||
D3D9,
|
||||
D3D10,
|
||||
D3D11,
|
||||
D3D12,
|
||||
|
||||
OpenGL,
|
||||
Vulkan,
|
||||
|
||||
Auto
|
||||
};
|
||||
};
|
||||
|
||||
Status::Enum init(RenderType::Enum renderType);
|
||||
void shutdown();
|
||||
|
||||
Status::Enum bind(uint16_t index, void** original, void* function);
|
||||
void unbind(uint16_t index);
|
||||
|
||||
RenderType::Enum getRenderType();
|
||||
uint150_t* getMethodsTable();
|
||||
}
|
||||
|
||||
#endif // __KIERO_H__
|
@ -0,0 +1,59 @@
|
||||
#include "windows.h"
|
||||
#include <cstdio>
|
||||
#include "kiero.h"
|
||||
#if KIERO_INCLUDE_D3D11
|
||||
# include "d3d11_hook.h"
|
||||
#endif
|
||||
#if KIERO_INCLUDE_D3D12
|
||||
# include "d3d12_hook.h"
|
||||
#endif
|
||||
|
||||
void ConsoleSetup()
|
||||
{
|
||||
// With this trick we'll be able to print content to the console, and if we have luck we could get information printed by the game.
|
||||
AllocConsole();
|
||||
SetConsoleTitle("MangoHud");
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
freopen("CONOUT$", "w", stderr);
|
||||
freopen("CONIN$", "r", stdin);
|
||||
}
|
||||
|
||||
int MainThread()
|
||||
{
|
||||
ConsoleSetup();
|
||||
printf("MangoHud Attached!\n");
|
||||
if (kiero::init(kiero::RenderType::Auto) == kiero::Status::Success)
|
||||
{
|
||||
switch (kiero::getRenderType())
|
||||
{
|
||||
#if KIERO_INCLUDE_D3D11
|
||||
case kiero::RenderType::D3D11:
|
||||
impl::d3d11::init();
|
||||
break;
|
||||
#endif
|
||||
#if KIERO_INCLUDE_D3D12
|
||||
case kiero::RenderType::D3D12:
|
||||
impl::d3d12::init();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID)
|
||||
{
|
||||
|
||||
DisableThreadLibraryCalls(hInstance);
|
||||
|
||||
switch (fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MainThread, NULL, 0, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
FROM scratch
|
||||
ADD com.valvesoftware.SteamRuntime.Sdk-amd64,i386-%RUNTIME%-sysroot.tar.gz /
|
||||
WORKDIR /build
|
||||
RUN \
|
||||
set -e; \
|
||||
mkdir -p /run/systemd; \
|
||||
echo 'docker' > /run/systemd/container; \
|
||||
mkdir -p /prep; cd /prep; \
|
||||
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py; \
|
||||
if [ ! -f /usr/bin/unzip ]; then apt-get update; apt-get -y install unzip; fi; \
|
||||
if [ -f /usr/bin/python3.5 ]; then ln -sf python3.5 /usr/bin/python3; fi; \
|
||||
python3 ./get-pip.py; \
|
||||
pip3 install meson mako; \
|
||||
curl -LO http://mirrors.kernel.org/ubuntu/pool/main/n/nvidia-settings/libxnvctrl0_440.64-0ubuntu1_amd64.deb; \
|
||||
curl -LO http://mirrors.kernel.org/ubuntu/pool/main/n/nvidia-settings/libxnvctrl-dev_440.64-0ubuntu1_amd64.deb; \
|
||||
dpkg -i libxnvctrl0_440.64-0ubuntu1_amd64.deb libxnvctrl-dev_440.64-0ubuntu1_amd64.deb; \
|
||||
cd /; rm -fr /prep; \
|
||||
:
|
||||
|
||||
CMD ["/bin/bash"]
|
@ -1,10 +1,8 @@
|
||||
[wrap-file]
|
||||
directory = Vulkan-Headers-1.2.142
|
||||
|
||||
source_url = https://github.com/KhronosGroup/Vulkan-Headers/archive/v1.2.142.tar.gz
|
||||
source_filename = v1.2.142.tar.gz
|
||||
source_hash = 6770503b0e06bd45e8cb1dba1e40ad37097d1100c2de7cd45c07de3b2d383a3e
|
||||
|
||||
patch_url = https://wrapdb.mesonbuild.com/v1/projects/vulkan-headers/1.2.142/1/get_zip
|
||||
patch_filename = vulkan-headers-1.2.142-1-wrap.zip
|
||||
patch_hash = ca4ebafdf6eff48261ac87ec674bf82bf2cb7e2aedf45ef1cf5ea6326e27c123
|
||||
directory = Vulkan-Headers-1.2.158
|
||||
source_url = https://github.com/KhronosGroup/Vulkan-Headers/archive/v1.2.158.tar.gz
|
||||
source_filename = v1.2.158.tar.gz
|
||||
source_hash = 53361271cfe274df8782e1e47bdc9e61b7af432ba30acbfe31723f9df2c257f3
|
||||
patch_url = https://wrapdb.mesonbuild.com/v1/projects/vulkan-headers/1.2.158/1/get_zip
|
||||
patch_filename = vulkan-headers-1.2.158-1-wrap.zip
|
||||
patch_hash = 5c791eaecf0b0a71bd1d854dc77ee131a242e14a108fdebd917ffa03491949d2
|
||||
|
Loading…
Reference in New Issue