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
|
#pragma once
|
||||||
#ifndef MANGOHUD_BLACKLIST_H
|
#ifndef MANGOHUD_BLACKLIST_H
|
||||||
#define MANGOHUD_BLACKLIST_H
|
#define MANGOHUD_BLACKLIST_H
|
||||||
|
#include<string>
|
||||||
bool is_blacklisted(bool force_recheck = false);
|
bool is_blacklisted(bool force_recheck = false);
|
||||||
|
void add_blacklist(std::string);
|
||||||
|
|
||||||
|
|
||||||
#endif //MANGOHUD_BLACKLIST_H
|
#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]
|
[wrap-file]
|
||||||
directory = Vulkan-Headers-1.2.142
|
directory = Vulkan-Headers-1.2.158
|
||||||
|
source_url = https://github.com/KhronosGroup/Vulkan-Headers/archive/v1.2.158.tar.gz
|
||||||
source_url = https://github.com/KhronosGroup/Vulkan-Headers/archive/v1.2.142.tar.gz
|
source_filename = v1.2.158.tar.gz
|
||||||
source_filename = v1.2.142.tar.gz
|
source_hash = 53361271cfe274df8782e1e47bdc9e61b7af432ba30acbfe31723f9df2c257f3
|
||||||
source_hash = 6770503b0e06bd45e8cb1dba1e40ad37097d1100c2de7cd45c07de3b2d383a3e
|
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_url = https://wrapdb.mesonbuild.com/v1/projects/vulkan-headers/1.2.142/1/get_zip
|
patch_hash = 5c791eaecf0b0a71bd1d854dc77ee131a242e14a108fdebd917ffa03491949d2
|
||||||
patch_filename = vulkan-headers-1.2.142-1-wrap.zip
|
|
||||||
patch_hash = ca4ebafdf6eff48261ac87ec674bf82bf2cb7e2aedf45ef1cf5ea6326e27c123
|
|
||||||
|
Loading…
Reference in New Issue