diff --git a/.gitmodules b/.gitmodules index cb83ff7..8332ce1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "Src/ThirdParty/gpudetect"] path = Src/ThirdParty/gpudetect url = https://github.com/GameTechDev/gpudetect.git -[submodule "Src/ThirdParty/rapidjson"] - path = Src/ThirdParty/rapidjson - url = https://github.com/Tencent/rapidjson.git [submodule "Src/ThirdParty/nvapi"] path = Src/ThirdParty/nvapi url = https://github.com/NVIDIA/nvapi.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 626ed0b..5784397 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,14 +10,40 @@ cmake_minimum_required(VERSION 3.17) project(D3d12info LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) -file(GLOB CPP_FILES "Src/*.cpp") -file(GLOB HPP_FILES "Src/*.hpp") -set(RAPIDJSON_NATVIS_FILE "Src/ThirdParty/rapidjson/contrib/natvis/rapidjson.natvis") -set(INTEL_GPUDETECT_CFG_FILE "Src/ThirdParty/gpudetect/IntelGfx.cfg") +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +set(CPP_FILES + Src/AgsData.cpp + Src/AmdDeviceInfoData.cpp + Src/IntelData.cpp + Src/Main.cpp + Src/NvApiData.cpp + Src/Printer.cpp + Src/Resources.rc + Src/Utils.cpp + Src/VulkanData.cpp + Src/ReportFormatter/TextReportFormatter.cpp + Src/ReportFormatter/JSONReportFormatter.cpp + Src/ReportFormatter/ReportFormatter.cpp +) + +set(HPP_FILES + Src/AgsData.hpp + Src/AmdDeviceInfoData.hpp + Src/Enums.hpp + Src/IntelData.hpp + Src/NvApiData.hpp + Src/pch.hpp + Src/Printer.hpp + Src/Utils.hpp + Src/VulkanData.hpp + Src/ReportFormatter/TextReportFormatter.hpp + Src/ReportFormatter/JSONReportFormatter.hpp + Src/ReportFormatter/ReportFormatter.hpp +) -if(NOT EXISTS "${PROJECT_SOURCE_DIR}/Src/ThirdParty/rapidjson/include/rapidjson/rapidjson.h") - message(FATAL_ERROR "rapidjson library not found. This is likely due to missing submodule. Please initialize submodules.") -endif() +set(INTEL_GPUDETECT_CFG_FILE "Src/ThirdParty/gpudetect/IntelGfx.cfg") option(ENABLE_AGS "Enables usage of AMD GPU Services (AGS) library." ON) if(ENABLE_AGS) @@ -82,6 +108,7 @@ function(add_my_executable USE_PREVIEW_AGILITY_SDK) endif() add_executable(${EXE_NAME} ${CPP_FILES} ${HPP_FILES}) + target_include_directories(${EXE_NAME} PRIVATE Src) # Change Visual C++ runtime library to get rid of dependency on Visual C++ Redistributable set_property(TARGET ${EXE_NAME} PROPERTY @@ -91,9 +118,6 @@ function(add_my_executable USE_PREVIEW_AGILITY_SDK) target_compile_definitions(${EXE_NAME} PRIVATE UNICODE _UNICODE) target_precompile_headers(${EXE_NAME} PRIVATE "Src/pch.hpp") - target_sources(${EXE_NAME} PRIVATE "${PROJECT_SOURCE_DIR}/${RAPIDJSON_NATVIS_FILE}") - source_group("ThirdParty" FILES ${RAPIDJSON_NATVIS_FILE}) - if(USE_PREVIEW_AGILITY_SDK) target_compile_definitions(${EXE_NAME} PRIVATE USE_PREVIEW_AGILITY_SDK=1) set(AGILITY_SDK_DIRECTORY "${PROJECT_SOURCE_DIR}/Src/ThirdParty/microsoft.direct3d.d3d12.1.716.0-preview") diff --git a/README.md b/README.md index 3ea0055..10206c0 100644 --- a/README.md +++ b/README.md @@ -60,9 +60,10 @@ Options: -h --Help Only print this help (command line syntax). -l --List Only print the list of all adapters. -a --Adapter= Print details of adapter at specified index. - --AllNonSoftware Print details of all (except WARP and Software) adapters (default behavior). - --AllAdapters Print details of all (except WARP) adapters. + --AllAdapters Print details of all adapters. -j --JSON Print output in JSON format instead of human-friendly text. + --MinimizeJson Print JSON in minimal size form. + -o --OutputFile= Output to specified file. -f --Formats Include information about DXGI format capabilities. --MetaCommands Include information about meta commands. -e --Enums Include information about all known enums and their values. @@ -89,8 +90,6 @@ It uses following thirt-party libraries: - **[DirectX 12 Agility SDK](https://devblogs.microsoft.com/directx/directx12agility/)** - latest API to Direct3D, by Microsoft. - Embedded in directory: Src\ThirdParty\microsoft.direct3d.d3d12.* -- **[RapidJSON](https://rapidjson.org/)** - a fast JSON parser/generator, by Tencent. License: MIT. - - Linked via submodule. - **[AMD GPU Services](https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK)** - custom vendor extensions to graphics APIs by AMD. - Linked via submodule. - Optional, controlled by Cmake variable `ENABLE_AGS` - on by default. diff --git a/Src/AgsData.cpp b/Src/AgsData.cpp index 39234e7..a61e190 100644 --- a/Src/AgsData.cpp +++ b/Src/AgsData.cpp @@ -8,10 +8,9 @@ License: MIT For more information, see files README.md, LICENSE.txt. */ #include "AgsData.hpp" -#include "Printing.hpp" #include "Utils.hpp" -#include "Json.hpp" #include "Enums.hpp" +#include "ReportFormatter/ReportFormatter.hpp" // Macro set by Cmake. #if USE_AGS @@ -67,22 +66,11 @@ static bool FindDevice(const AGS_Initialize_RAII::DeviceId& id, int& outIndex) void AGS_Initialize_RAII::PrintStaticParams() { - Print_string(L"AMD_AGS_VERSION", std::format(L"{}.{}.{}", + ReportFormatter::GetInstance().AddFieldString(L"AMD_AGS_VERSION", std::format(L"{}.{}.{}", AMD_AGS_VERSION_MAJOR, AMD_AGS_VERSION_MINOR, AMD_AGS_VERSION_PATCH).c_str()); const uint32_t version = (uint32_t)agsGetVersionNumber(); - if(g_UseJson) - { - Print_hex32(L"agsGetVersionNumber", version); - } - else - { - wstring s = std::format(L"{}.{}.{}", - version >> 22, - (version >> 12) & 0b11'1111'1111, - version & 0b1111'1111'1111); - Print_string(L"agsGetVersionNumber", s.c_str()); - } + ReportFormatter::GetInstance().AddFieldAMDVersion(L"agsGetVersionNumber", version); } AGS_Initialize_RAII::AGS_Initialize_RAII() @@ -110,9 +98,9 @@ void AGS_Initialize_RAII::PrintData() if(IsStrEmpty(g_GpuInfo.driverVersion) && IsStrEmpty(g_GpuInfo.radeonSoftwareVersion)) return; - ScopedStructRegion region(L"AGSGPUInfo"); - Print_string(L"driverVersion", StrToWstr(g_GpuInfo.driverVersion, CP_ACP).c_str()); - Print_string(L"radeonSoftwareVersion", StrToWstr(g_GpuInfo.radeonSoftwareVersion, CP_ACP).c_str()); + ReportScopeObject region(L"AGSGPUInfo"); + ReportFormatter::GetInstance().AddFieldString(L"driverVersion", StrToWstr(g_GpuInfo.driverVersion, CP_ACP).c_str()); + ReportFormatter::GetInstance().AddFieldString(L"radeonSoftwareVersion", StrToWstr(g_GpuInfo.radeonSoftwareVersion, CP_ACP).c_str()); } void AGS_Initialize_RAII::PrintAgsDeviceData(const DeviceId& id) @@ -124,23 +112,24 @@ void AGS_Initialize_RAII::PrintAgsDeviceData(const DeviceId& id) return; const AGSDeviceInfo& device = g_GpuInfo.devices[deviceIndex]; - ScopedStructRegion region(L"AGSDeviceInfo"); - Print_string(L"adapterString", StrToWstr(device.adapterString, CP_ACP).c_str()); - PrintEnum(L"asicFamily", device.asicFamily, Enum_AGSDeviceInfo_AsicFamily); - Print_BOOL(L"isAPU", device.isAPU); - Print_BOOL(L"isExternal", device.isExternal); - PrintVendorId(L"vendorId", (uint32_t)device.vendorId); - Print_hex32(L"deviceId", (uint32_t)device.deviceId); - Print_hex32(L"revisionId", (uint32_t)device.revisionId); - Print_int32(L"numCUs", device.numCUs); - Print_int32(L"numWGPs", device.numWGPs); - Print_int32(L"numROPs", device.numROPs); - Print_int32(L"coreClock", device.coreClock, L"MHz"); - Print_int32(L"memoryClock", device.memoryClock, L"MHz"); - Print_int32(L"memoryBandwidth", device.memoryBandwidth, L"MB/s"); - Print_float(L"teraFlops", device.teraFlops, L"TFLOPS"); - Print_size(L"localMemoryInBytes", device.localMemoryInBytes); - Print_size(L"sharedMemoryInBytes", device.sharedMemoryInBytes); + ReportScopeObject region(L"AGSDeviceInfo"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldString(L"adapterString", StrToWstr(device.adapterString, CP_ACP).c_str()); + formatter.AddFieldEnum(L"asicFamily", device.asicFamily, Enum_AGSDeviceInfo_AsicFamily); + formatter.AddFieldBool(L"isAPU", device.isAPU); + formatter.AddFieldBool(L"isExternal", device.isExternal); + formatter.AddFieldVendorId(L"vendorId", (uint32_t)device.vendorId); + formatter.AddFieldHex32(L"deviceId", (uint32_t)device.deviceId); + formatter.AddFieldHex32(L"revisionId", (uint32_t)device.revisionId); + formatter.AddFieldInt32(L"numCUs", device.numCUs); + formatter.AddFieldInt32(L"numWGPs", device.numWGPs); + formatter.AddFieldInt32(L"numROPs", device.numROPs); + formatter.AddFieldInt32(L"coreClock", device.coreClock, L"MHz"); + formatter.AddFieldInt32(L"memoryClock", device.memoryClock, L"MHz"); + formatter.AddFieldInt32(L"memoryBandwidth", device.memoryBandwidth, L"MB/s"); + formatter.AddFieldFloat(L"teraFlops", device.teraFlops, L"TFLOPS"); + formatter.AddFieldSize(L"localMemoryInBytes", device.localMemoryInBytes); + formatter.AddFieldSize(L"sharedMemoryInBytes", device.sharedMemoryInBytes); } ComPtr AGS_Initialize_RAII::CreateDeviceAndPrintData(IDXGIAdapter* adapter, D3D_FEATURE_LEVEL featureLevel) @@ -163,20 +152,21 @@ ComPtr AGS_Initialize_RAII::CreateDeviceAndPrintData(IDXGIAdapter* ComPtr device{returnedParams.pDevice}; g_DeviceCreatedWithAgs = true; - ScopedStructRegion region(L"AGSDX12ReturnedParams::ExtensionsSupported"); - Print_BOOL(L"intrinsics16", returnedParams.extensionsSupported.intrinsics16); - Print_BOOL(L"intrinsics17", returnedParams.extensionsSupported.intrinsics17); - Print_BOOL(L"userMarkers", returnedParams.extensionsSupported.userMarkers); - Print_BOOL(L"appRegistration", returnedParams.extensionsSupported.appRegistration); - Print_BOOL(L"UAVBindSlot", returnedParams.extensionsSupported.UAVBindSlot); - Print_BOOL(L"intrinsics19", returnedParams.extensionsSupported.intrinsics19); - Print_BOOL(L"baseVertex", returnedParams.extensionsSupported.baseVertex); - Print_BOOL(L"baseInstance", returnedParams.extensionsSupported.baseInstance); - Print_BOOL(L"getWaveSize", returnedParams.extensionsSupported.getWaveSize); - Print_BOOL(L"floatConversion", returnedParams.extensionsSupported.floatConversion); - Print_BOOL(L"readLaneAt", returnedParams.extensionsSupported.readLaneAt); - Print_BOOL(L"rayHitToken", returnedParams.extensionsSupported.rayHitToken); - Print_BOOL(L"shaderClock", returnedParams.extensionsSupported.shaderClock); + ReportScopeObject region(L"AGSDX12ReturnedParams::ExtensionsSupported"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldBool(L"intrinsics16", returnedParams.extensionsSupported.intrinsics16); + formatter.AddFieldBool(L"intrinsics17", returnedParams.extensionsSupported.intrinsics17); + formatter.AddFieldBool(L"userMarkers", returnedParams.extensionsSupported.userMarkers); + formatter.AddFieldBool(L"appRegistration", returnedParams.extensionsSupported.appRegistration); + formatter.AddFieldBool(L"UAVBindSlot", returnedParams.extensionsSupported.UAVBindSlot); + formatter.AddFieldBool(L"intrinsics19", returnedParams.extensionsSupported.intrinsics19); + formatter.AddFieldBool(L"baseVertex", returnedParams.extensionsSupported.baseVertex); + formatter.AddFieldBool(L"baseInstance", returnedParams.extensionsSupported.baseInstance); + formatter.AddFieldBool(L"getWaveSize", returnedParams.extensionsSupported.getWaveSize); + formatter.AddFieldBool(L"floatConversion", returnedParams.extensionsSupported.floatConversion); + formatter.AddFieldBool(L"readLaneAt", returnedParams.extensionsSupported.readLaneAt); + formatter.AddFieldBool(L"rayHitToken", returnedParams.extensionsSupported.rayHitToken); + formatter.AddFieldBool(L"shaderClock", returnedParams.extensionsSupported.shaderClock); return device; } diff --git a/Src/AmdDeviceInfoData.cpp b/Src/AmdDeviceInfoData.cpp index cabbb1b..3b3de2c 100644 --- a/Src/AmdDeviceInfoData.cpp +++ b/Src/AmdDeviceInfoData.cpp @@ -8,10 +8,9 @@ License: MIT For more information, see files README.md, LICENSE.txt. */ #include "AmdDeviceInfoData.hpp" -#include "Printing.hpp" #include "Utils.hpp" -#include "Json.hpp" #include "Enums.hpp" +#include "ReportFormatter/ReportFormatter.hpp" // Macro set by Cmake. #if USE_AMD_DEVICE_INFO @@ -116,7 +115,7 @@ static const GDT_GfxCardInfo* FindCardInfo(const AmdDeviceInfo_Initialize_RAII:: void AmdDeviceInfo_Initialize_RAII::PrintStaticParams() { - Print_string(L"AMD device_info compiled version", AMD_DEVICE_INFO_COMPILED_VERSION); + ReportFormatter::GetInstance().AddFieldString(L"AMD device_info compiled version", AMD_DEVICE_INFO_COMPILED_VERSION); } void AmdDeviceInfo_Initialize_RAII::PrintDeviceData(const DeviceId& id) @@ -125,13 +124,15 @@ void AmdDeviceInfo_Initialize_RAII::PrintDeviceData(const DeviceId& id) if(!cardInfo) return; + ReportFormatter& formatter = ReportFormatter::GetInstance(); + { - ScopedStructRegion region{L"AMD GDT_GfxCardInfo"}; - PrintEnum(L"asicType", cardInfo->m_asicType, Enum_GDT_HW_ASIC_TYPE); - PrintEnum(L"generation", cardInfo->m_generation, Enum_GDT_HW_GENERATION); - Print_BOOL(L"APU", cardInfo->m_bAPU ? TRUE : FALSE); - Print_string(L"CALName", StrToWstr(cardInfo->m_szCALName, CP_UTF8).c_str()); - Print_string(L"MarketingName", StrToWstr(cardInfo->m_szMarketingName, CP_UTF8).c_str()); + ReportScopeObject region{ L"AMD GDT_GfxCardInfo" }; + formatter.AddFieldEnum(L"asicType", cardInfo->m_asicType, Enum_GDT_HW_ASIC_TYPE); + formatter.AddFieldEnum(L"generation", cardInfo->m_generation, Enum_GDT_HW_GENERATION); + formatter.AddFieldBool(L"APU", cardInfo->m_bAPU ? TRUE : FALSE); + formatter.AddFieldString(L"CALName", StrToWstr(cardInfo->m_szCALName, CP_UTF8).c_str()); + formatter.AddFieldString(L"MarketingName", StrToWstr(cardInfo->m_szMarketingName, CP_UTF8).c_str()); } if(cardInfo->m_asicType >= 0 && cardInfo->m_asicType < gs_deviceInfoSize) @@ -139,16 +140,16 @@ void AmdDeviceInfo_Initialize_RAII::PrintDeviceData(const DeviceId& id) const GDT_DeviceInfo& devInfo = gs_deviceInfo[cardInfo->m_asicType]; if(devInfo.m_deviceInfoValid) { - ScopedStructRegion region(L"AMD GDT_DeviceInfo"); - Print_uint64(L"NumShaderEngines", devInfo.m_nNumShaderEngines); // Number of shader engines. - Print_uint64(L"MaxWavePerSIMD", devInfo.m_nMaxWavePerSIMD); // Number of wave slots per SIMD. - Print_uint64(L"ClocksPrim", devInfo.m_suClocksPrim); // Number of clocks it takes to process a primitive. - Print_uint64(L"NumSQMaxCounters", devInfo.m_nNumSQMaxCounters); // Max number of SQ counters. - Print_uint64(L"NumPrimPipes", devInfo.m_nNumPrimPipes); // Number of primitive pipes. - Print_uint64(L"WaveSize", devInfo.m_nWaveSize); // Wavefront size. - Print_uint64(L"NumSHPerSE", devInfo.m_nNumSHPerSE); // Number of shader array per Shader Engine. - Print_uint64(L"NumCUPerSH", devInfo.m_nNumCUPerSH); // Number of compute unit per Shader Array. - Print_uint64(L"NumSIMDPerCU", devInfo.m_nNumSIMDPerCU); // Number of SIMDs per Compute unit. + ReportScopeObject region(L"AMD GDT_DeviceInfo"); + formatter.AddFieldUint64(L"NumShaderEngines", devInfo.m_nNumShaderEngines); // Number of shader engines. + formatter.AddFieldUint64(L"MaxWavePerSIMD", devInfo.m_nMaxWavePerSIMD); // Number of wave slots per SIMD. + formatter.AddFieldUint64(L"ClocksPrim", devInfo.m_suClocksPrim); // Number of clocks it takes to process a primitive. + formatter.AddFieldUint64(L"NumSQMaxCounters", devInfo.m_nNumSQMaxCounters); // Max number of SQ counters. + formatter.AddFieldUint64(L"NumPrimPipes", devInfo.m_nNumPrimPipes); // Number of primitive pipes. + formatter.AddFieldUint64(L"WaveSize", devInfo.m_nWaveSize); // Wavefront size. + formatter.AddFieldUint64(L"NumSHPerSE", devInfo.m_nNumSHPerSE); // Number of shader array per Shader Engine. + formatter.AddFieldUint64(L"NumCUPerSH", devInfo.m_nNumCUPerSH); // Number of compute unit per Shader Array. + formatter.AddFieldUint64(L"NumSIMDPerCU", devInfo.m_nNumSIMDPerCU); // Number of SIMDs per Compute unit. } } } diff --git a/Src/Enums.hpp b/Src/Enums.hpp index e044f62..f1b82a5 100644 --- a/Src/Enums.hpp +++ b/Src/Enums.hpp @@ -9,8 +9,6 @@ For more information, see files README.md, LICENSE.txt. */ #pragma once -#include - struct EnumItem { const wchar_t* m_Name; diff --git a/Src/IntelData.cpp b/Src/IntelData.cpp index 3b8380f..a406911 100644 --- a/Src/IntelData.cpp +++ b/Src/IntelData.cpp @@ -13,10 +13,10 @@ License: Apache 2.0 See the original library in directory: Src\ThirdParty\gpudetect */ #include "IntelData.hpp" -#include "Printing.hpp" #include "Utils.hpp" -#include "Json.hpp" #include "Enums.hpp" +#include "ReportFormatter/ReportFormatter.hpp" +#include "Printer.hpp" // Macro set by Cmake. #if USE_INTEL_GPUDETECT @@ -1549,7 +1549,7 @@ PresetLevel GetDefaultFidelityPreset( const GPUData* const gpuData ) } else { - fprintf( stderr, "Error: %s not found! Fallback to default presets.\n", cfgFileName ); + ErrorPrinter::PrintFormat("Error: {} not found! Fallback to default presets.", std::make_format_args(cfgFileName)); } // @@ -1979,7 +1979,7 @@ namespace IntelData void PrintStaticParams() { - Print_string(L"Intel GPU Detect compiled version", INTEL_GPU_DETECT_COMPILED_VERSION); + ReportFormatter::GetInstance().AddFieldString(L"Intel GPU Detect compiled version", INTEL_GPU_DETECT_COMPILED_VERSION); } void PrintAdapterData(IDXGIAdapter* adapter) @@ -1994,29 +1994,30 @@ void PrintAdapterData(IDXGIAdapter* adapter) if(r != EXIT_SUCCESS) return; - ScopedStructRegion region(L"Intel GPUDetect::GPUData"); - PrintVendorId(L"VendorId", gpuData.vendorID); - Print_hex32(L"deviceID", gpuData.deviceID); - Print_BOOL(L"isUMAArchitecture", gpuData.isUMAArchitecture ? TRUE : FALSE); - Print_size(L"videoMemory", gpuData.videoMemory); - Print_string(L"description", gpuData.description); - Print_hex32(L"extensionVersion", gpuData.extensionVersion); - Print_BOOL(L"intelExtensionAvailability", gpuData.intelExtensionAvailability ? TRUE : FALSE); + ReportScopeObject region(L"Intel GPUDetect::GPUData"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldVendorId(L"VendorId", gpuData.vendorID); + formatter.AddFieldHex32(L"deviceID", gpuData.deviceID); + formatter.AddFieldBool(L"isUMAArchitecture", gpuData.isUMAArchitecture ? TRUE : FALSE); + formatter.AddFieldSize(L"videoMemory", gpuData.videoMemory); + formatter.AddFieldString(L"description", gpuData.description); + formatter.AddFieldHex32(L"extensionVersion", gpuData.extensionVersion); + formatter.AddFieldBool(L"intelExtensionAvailability", gpuData.intelExtensionAvailability ? TRUE : FALSE); r = GPUDetect::InitDxDriverVersion(&gpuData); if(r == EXIT_SUCCESS && gpuData.d3dRegistryDataAvailability) { char driverVersionStr[19] = {}; GPUDetect::GetDriverVersionAsCString(&gpuData, driverVersionStr, _countof(driverVersionStr)); - Print_string(L"dxDriverVersion", StrToWstr(driverVersionStr, CP_ACP).c_str()); - Print_uint32(L"driverInfo.driverReleaseRevision", gpuData.driverInfo.driverReleaseRevision); - Print_uint32(L"driverInfo.driverBuildNumber", gpuData.driverInfo.driverBuildNumber); + formatter.AddFieldString(L"dxDriverVersion", StrToWstr(driverVersionStr, CP_ACP).c_str()); + formatter.AddFieldUint32(L"driverInfo.driverReleaseRevision", gpuData.driverInfo.driverReleaseRevision); + formatter.AddFieldUint32(L"driverInfo.driverBuildNumber", gpuData.driverInfo.driverBuildNumber); } if(gpuData.vendorID == GPUDetect::INTEL_VENDOR_ID) { const GPUDetect::PresetLevel presetLevel = GPUDetect::GetDefaultFidelityPreset(&gpuData); - PrintEnum(L"DefaultFidelityPreset", (uint32_t)presetLevel, GPUDetect::Enum_PresetLevel); + formatter.AddFieldEnum(L"DefaultFidelityPreset", (uint32_t)presetLevel, GPUDetect::Enum_PresetLevel); r = GPUDetect::InitCounterInfo(&gpuData, device.Get()); if(r == EXIT_SUCCESS) @@ -2024,24 +2025,24 @@ void PrintAdapterData(IDXGIAdapter* adapter) string architectureStr = GPUDetect::GetIntelGPUArchitectureString(gpuData.architecture); if(architectureStr == "Unknown") architectureStr = std::format("Unknown ({})", (uint32_t)gpuData.architecture); - Print_string(L"GPUArchitecture", StrToWstr(architectureStr.c_str(), CP_ACP).c_str()); + formatter.AddFieldString(L"GPUArchitecture", StrToWstr(architectureStr.c_str(), CP_ACP).c_str()); const GPUDetect::IntelGraphicsGeneration generation = GPUDetect::GetIntelGraphicsGeneration(gpuData.architecture); string generationStr = GPUDetect::GetIntelGraphicsGenerationString(generation); if(generationStr == "Unknown") generationStr = std::format("Unknown ({})", (uint32_t)generation); - Print_string(L"GraphicsGeneration", StrToWstr(generationStr.c_str(), CP_ACP).c_str()); + formatter.AddFieldString(L"GraphicsGeneration", StrToWstr(generationStr.c_str(), CP_ACP).c_str()); if(gpuData.advancedCounterDataAvailability) { - Print_uint32(L"euCount", gpuData.euCount); - Print_uint32(L"packageTDP", gpuData.packageTDP, L"W"); - Print_uint32(L"maxFillRate", gpuData.maxFillRate, L"pixels/clock"); + formatter.AddFieldUint32(L"euCount", gpuData.euCount); + formatter.AddFieldUint32(L"packageTDP", gpuData.packageTDP, L"W"); + formatter.AddFieldUint32(L"maxFillRate", gpuData.maxFillRate, L"pixels/clock"); } - Print_uint32(L"maxFrequency", gpuData.maxFrequency, L"MHz"); - Print_uint32(L"minFrequency", gpuData.minFrequency, L"MHz"); + formatter.AddFieldUint32(L"maxFrequency", gpuData.maxFrequency, L"MHz"); + formatter.AddFieldUint32(L"minFrequency", gpuData.minFrequency, L"MHz"); } } } diff --git a/Src/Json.cpp b/Src/Json.cpp deleted file mode 100644 index 6796e34..0000000 --- a/Src/Json.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* -This file is part of D3d12info project: -https://github.com/sawickiap/D3d12info - -Copyright (c) 2018-2024 Adam Sawicki, https://asawicki.info -License: MIT - -For more information, see files README.md, LICENSE.txt. -*/ -#include "Json.hpp" - -#define RAPIDJSON_HAS_STDSTRING 1 -#define RAPIDJSON_NO_SIZETYPEDEFINE -#define RAPIDJSON_SSE2 -namespace rapidjson { typedef size_t SizeType; } - -#include "ThirdParty/rapidjson/include/rapidjson/document.h" -#include "ThirdParty/rapidjson/include/rapidjson/prettywriter.h" -#include "ThirdParty/rapidjson/include/rapidjson/stringbuffer.h" -#include "ThirdParty/rapidjson/include/rapidjson/allocators.h" -#include "ThirdParty/rapidjson/include/rapidjson/encodings.h" -#include "ThirdParty/rapidjson/include/rapidjson/error/en.h" - -namespace Json -{ - - -//////////////////////////////////////////////////////////////////////////////// -// PRIVATE IMPLEMENTATION - -using ValueType = rapidjson::GenericValue< rapidjson::UTF16<> >; -using StringRefType = rapidjson::GenericStringRef; -static rapidjson::GenericDocument< rapidjson::UTF16<> > g_Document{rapidjson::kObjectType}; -static std::vector g_ValueStack; -static wstring g_CurrentKey; - -static void PushValue(ValueType&& val) -{ - using namespace rapidjson; - assert(!g_ValueStack.empty()); - ValueType* const currVal = g_ValueStack.back(); - const bool newValNeedsPush = val.GetType() == kObjectType || val.GetType() == kArrayType; - switch(currVal->GetType()) - { - case kArrayType: - { - currVal->PushBack(val, g_Document.GetAllocator()); - if(newValNeedsPush) - g_ValueStack.push_back(&currVal->GetArray()[currVal->GetArray().Size() - 1]); - break; - } - case kObjectType: - { - assert(!g_CurrentKey.empty()); - currVal->AddMember( - ValueType{g_CurrentKey.data(), g_CurrentKey.length(), g_Document.GetAllocator()}, - val, g_Document.GetAllocator()); - if(newValNeedsPush) - g_ValueStack.push_back(&currVal->GetObj()[g_CurrentKey]); - g_CurrentKey.clear(); - break; - } - default: - assert(0); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// PUBLIC INTERFACE - -void Begin() -{ - assert(g_ValueStack.empty() && g_CurrentKey.empty()); - g_ValueStack.push_back(&g_Document); -} - -wstring End() -{ - using namespace rapidjson; - using StringBufferType = GenericStringBuffer< UTF16LE<> >; - StringBufferType stringBuffer; - { - PrettyWriter< StringBufferType, UTF16<>, UTF16LE<> > writer{stringBuffer}; - g_Document.Accept(writer); - } - - assert(g_ValueStack.size() == 1 && g_ValueStack[0] == &g_Document && g_CurrentKey.empty()); - g_ValueStack.clear(); - - return wstring{stringBuffer.GetString(), stringBuffer.GetLength()}; -} - -void WriteString(const wchar_t* str, size_t length) -{ - using namespace rapidjson; - assert(!g_ValueStack.empty()); - ValueType* const currVal = g_ValueStack.back(); - // Writing key - if(currVal->GetType() == kObjectType && g_CurrentKey.empty()) - g_CurrentKey = wstring{str, length}; - // Writing value - else - PushValue(ValueType{str, length, g_Document.GetAllocator()}); -} - -void WriteString(const wchar_t* str) -{ - WriteString(str, wcslen(str)); -} - -void WriteString(wstring&& str) -{ - using namespace rapidjson; - assert(!g_ValueStack.empty()); - ValueType* const currVal = g_ValueStack.back(); - // Writing key - if(currVal->GetType() == kObjectType && g_CurrentKey.empty()) - g_CurrentKey = std::move(str); - // Writing value - else - PushValue(ValueType{str.data(), str.length(), g_Document.GetAllocator()}); -} - -void WriteNull() -{ - PushValue(ValueType{rapidjson::kNullType}); -} - -void WriteBool(bool value) -{ - PushValue(ValueType{value}); - -} - -void WriteNumber(uint32_t value) -{ - PushValue(ValueType{value}); -} - -void WriteNumber(uint64_t value) -{ - PushValue(ValueType{value}); -} - -void WriteNumber(int32_t value) -{ - PushValue(ValueType{value}); -} - -void WriteNumber(float value) -{ - PushValue(ValueType{value}); -} - -void BeginObject() -{ - PushValue(ValueType{rapidjson::kObjectType}); -} - -void EndObject() -{ - assert(!g_ValueStack.empty() && g_ValueStack.back()->GetType() == rapidjson::kObjectType); - g_ValueStack.pop_back(); -} - -void BeginArray() -{ - PushValue(ValueType{rapidjson::kArrayType}); -} - -void EndArray() -{ - assert(!g_ValueStack.empty() && g_ValueStack.back()->GetType() == rapidjson::kArrayType); - g_ValueStack.pop_back(); -} - -void WriteNameAndString(const wchar_t* name, const wchar_t* str, size_t length) -{ - WriteString(name); - WriteString(str, length); -} - -void WriteNameAndString(const wchar_t* name, const wchar_t* str) -{ - WriteString(name); - WriteString(str); -} - -void WriteNameAndString(const wchar_t* name, wstring&& str) -{ - WriteString(name); - WriteString(std::move(str)); -} - -void WriteNameAndBool(const wchar_t* name, bool value) -{ - WriteString(name); - WriteBool(value); -} - -void WriteNameAndNumber(const wchar_t* name, uint32_t value) -{ - WriteString(name); - WriteNumber(value); -} - -void WriteNameAndNumber(const wchar_t* name, uint64_t value) -{ - WriteString(name); - WriteNumber(value); -} - -void WriteNameAndNumber(const wchar_t* name, int32_t value) -{ - WriteString(name); - WriteNumber(value); -} - -void WriteNameAndNumber(const wchar_t* name, float value) -{ - WriteString(name); - WriteNumber(value); -} - -} // namespace Json diff --git a/Src/Json.hpp b/Src/Json.hpp deleted file mode 100644 index 81d7cdd..0000000 --- a/Src/Json.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* -This file is part of D3d12info project: -https://github.com/sawickiap/D3d12info - -Copyright (c) 2018-2024 Adam Sawicki, https://asawicki.info -License: MIT - -For more information, see files README.md, LICENSE.txt. -*/ -#pragma once - -namespace Json -{ - -void Begin(); -wstring End(); - -void WriteString(const wchar_t* str, size_t length); -void WriteString(const wchar_t* str); -void WriteString(wstring&& str); -void WriteNull(); -void WriteBool(bool value); -void WriteNumber(uint32_t value); -void WriteNumber(uint64_t value); -void WriteNumber(int32_t value); -void WriteNumber(float value); -void BeginObject(); -void EndObject(); -void BeginArray(); -void EndArray(); - -void WriteNameAndString(const wchar_t* name, const wchar_t* str, size_t length); -void WriteNameAndString(const wchar_t* name, const wchar_t* str); -void WriteNameAndString(const wchar_t* name, wstring&& str); -void WriteNameAndBool(const wchar_t* name, bool value); -void WriteNameAndNumber(const wchar_t* name, uint32_t value); -void WriteNameAndNumber(const wchar_t* name, uint64_t value); -void WriteNameAndNumber(const wchar_t* name, int32_t value); -void WriteNameAndNumber(const wchar_t* name, float value); - -} // namespace Json diff --git a/Src/Main.cpp b/Src/Main.cpp index 6c0fc3e..cb4a28f 100644 --- a/Src/Main.cpp +++ b/Src/Main.cpp @@ -14,8 +14,14 @@ For more information, see files README.md, LICENSE.txt. #include "VulkanData.hpp" #include "Utils.hpp" #include "Enums.hpp" -#include "Json.hpp" -#include "Printing.hpp" +#include "Printer.hpp" +#include "ReportFormatter/ReportFormatter.hpp" + +#define WIDE_CHAR_STRING_HELPER(x) L ## x +#define WIDE_CHAR_STRING(x) WIDE_CHAR_STRING_HELPER(x) +constexpr const wchar_t* BUILD_TIME = WIDE_CHAR_STRING(__DATE__) L" " WIDE_CHAR_STRING(__TIME__); +#undef WIDE_CHAR_STRING +#undef WIDE_CHAR_STRING_HELPER // For Direct3D 12 Agility SDK extern "C" @@ -79,9 +85,16 @@ PFN_D3D12_GET_INTERFACE g_D3D12GetInterface; #endif // #if defined(AUTO_LINK_DX12) +// Command line flags +static bool g_ShowVersionAndQuit = false; +static bool g_ShowCommandLineSyntaxAndQuit = false; +static bool g_ShowCommandLineSyntaxAndFail = false; static bool g_ListAdapters = false; static bool g_ShowAllAdapters = true; static bool g_SkipSoftwareAdapter = true; +static bool g_UseJsonOutput = false; +static bool g_UseJsonPrettyPrint = true; +static bool g_OutputFile = false; static bool g_PrintFormats = false; static bool g_PrintMetaCommands = false; static bool g_PrintEnums = false; @@ -93,6 +106,10 @@ static bool g_EnableExperimental = false; #endif static bool g_ForceVendorAPI = false; static bool g_WARP = false; +static std::wstring g_OutputFilePath; + +// Derived flags +static bool g_PrintAdaptersAsArray = true; static wstring LuidToStr(LUID value) { @@ -103,341 +120,342 @@ static wstring LuidToStr(LUID value) static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS(const D3D12_FEATURE_DATA_D3D12_OPTIONS& options) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS"); - Print_BOOL( L"DoublePrecisionFloatShaderOps", options.DoublePrecisionFloatShaderOps); - Print_BOOL( L"OutputMergerLogicOp", options.OutputMergerLogicOp); - PrintEnum( L"MinPrecisionSupport", options.MinPrecisionSupport, Enum_D3D12_SHADER_MIN_PRECISION_SUPPORT); - PrintEnum( L"TiledResourcesTier", options.TiledResourcesTier, Enum_D3D12_TILED_RESOURCES_TIER); - PrintEnum( L"ResourceBindingTier", options.ResourceBindingTier, Enum_D3D12_RESOURCE_BINDING_TIER); - Print_BOOL( L"PSSpecifiedStencilRefSupported", options.PSSpecifiedStencilRefSupported); - Print_BOOL( L"TypedUAVLoadAdditionalFormats", options.TypedUAVLoadAdditionalFormats); - Print_BOOL( L"ROVsSupported", options.ROVsSupported); - PrintEnum( L"ConservativeRasterizationTier", options.ConservativeRasterizationTier, Enum_D3D12_CONSERVATIVE_RASTERIZATION_TIER); - Print_uint32(L"MaxGPUVirtualAddressBitsPerResource", options.MaxGPUVirtualAddressBitsPerResource); - Print_BOOL( L"StandardSwizzle64KBSupported", options.StandardSwizzle64KBSupported); - PrintEnum( L"CrossNodeSharingTier", options.CrossNodeSharingTier, Enum_D3D12_CROSS_NODE_SHARING_TIER); - Print_BOOL( L"CrossAdapterRowMajorTextureSupported", options.CrossAdapterRowMajorTextureSupported); - Print_BOOL( L"VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation", options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation); - PrintEnum( L"ResourceHeapTier", options.ResourceHeapTier, Enum_D3D12_RESOURCE_HEAP_TIER); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldBool(L"DoublePrecisionFloatShaderOps", options.DoublePrecisionFloatShaderOps); + formatter.AddFieldBool(L"OutputMergerLogicOp", options.OutputMergerLogicOp); + formatter.AddFieldEnum(L"MinPrecisionSupport", options.MinPrecisionSupport, Enum_D3D12_SHADER_MIN_PRECISION_SUPPORT); + formatter.AddFieldEnum(L"TiledResourcesTier", options.TiledResourcesTier, Enum_D3D12_TILED_RESOURCES_TIER); + formatter.AddFieldEnum(L"ResourceBindingTier", options.ResourceBindingTier, Enum_D3D12_RESOURCE_BINDING_TIER); + formatter.AddFieldBool(L"PSSpecifiedStencilRefSupported", options.PSSpecifiedStencilRefSupported); + formatter.AddFieldBool(L"TypedUAVLoadAdditionalFormats", options.TypedUAVLoadAdditionalFormats); + formatter.AddFieldBool(L"ROVsSupported", options.ROVsSupported); + formatter.AddFieldEnum(L"ConservativeRasterizationTier", options.ConservativeRasterizationTier, Enum_D3D12_CONSERVATIVE_RASTERIZATION_TIER); + formatter.AddFieldUint32(L"MaxGPUVirtualAddressBitsPerResource", options.MaxGPUVirtualAddressBitsPerResource); + formatter.AddFieldBool(L"StandardSwizzle64KBSupported", options.StandardSwizzle64KBSupported); + formatter.AddFieldEnum(L"CrossNodeSharingTier", options.CrossNodeSharingTier, Enum_D3D12_CROSS_NODE_SHARING_TIER); + formatter.AddFieldBool(L"CrossAdapterRowMajorTextureSupported", options.CrossAdapterRowMajorTextureSupported); + formatter.AddFieldBool(L"VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation", options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation); + formatter.AddFieldEnum(L"ResourceHeapTier", options.ResourceHeapTier, Enum_D3D12_RESOURCE_HEAP_TIER); } static void Print_D3D12_FEATURE_DATA_ARCHITECTURE(const D3D12_FEATURE_DATA_ARCHITECTURE& architecture) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_ARCHITECTURE"); - Print_uint32(L"NodeIndex", architecture.NodeIndex); - Print_BOOL (L"TileBasedRenderer", architecture.TileBasedRenderer); - Print_BOOL (L"UMA", architecture.UMA); - Print_BOOL (L"CacheCoherentUMA", architecture.CacheCoherentUMA); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_ARCHITECTURE"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldUint32(L"NodeIndex", architecture.NodeIndex); + formatter.AddFieldBool(L"TileBasedRenderer", architecture.TileBasedRenderer); + formatter.AddFieldBool(L"UMA", architecture.UMA); + formatter.AddFieldBool(L"CacheCoherentUMA", architecture.CacheCoherentUMA); } static void Print_D3D12_FEATURE_DATA_ARCHITECTURE1(const D3D12_FEATURE_DATA_ARCHITECTURE1& architecture1) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_ARCHITECTURE1"); - Print_uint32(L"NodeIndex", architecture1.NodeIndex); - Print_BOOL (L"TileBasedRenderer", architecture1.TileBasedRenderer); - Print_BOOL (L"UMA", architecture1.UMA); - Print_BOOL (L"CacheCoherentUMA", architecture1.CacheCoherentUMA); - Print_BOOL (L"IsolatedMMU", architecture1.IsolatedMMU); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_ARCHITECTURE1"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldUint32(L"NodeIndex", architecture1.NodeIndex); + formatter.AddFieldBool(L"TileBasedRenderer", architecture1.TileBasedRenderer); + formatter.AddFieldBool(L"UMA", architecture1.UMA); + formatter.AddFieldBool(L"CacheCoherentUMA", architecture1.CacheCoherentUMA); + formatter.AddFieldBool(L"IsolatedMMU", architecture1.IsolatedMMU); } static void Print_D3D12_FEATURE_DATA_FEATURE_LEVELS(const D3D12_FEATURE_DATA_FEATURE_LEVELS& featureLevels) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_FEATURE_LEVELS"); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_FEATURE_LEVELS"); -#if 0 // TODO Is this an output parameter or not? How to correctly query and print it??? - Print_uint32(L"NumFeatureLevels", featureLevels.NumFeatureLevels); - BeginArray(); - for(uint32_t i = 0; i < featureLevels.NumFeatureLevels; ++i) - { - PrintEnum(L"pFeatureLevelsRequested", featureLevels.pFeatureLevelsRequested[i], Enum_D3D_FEATURE_LEVEL); - StepArray(); - } - EndArray(); -#endif - PrintEnum(L"MaxSupportedFeatureLevel", featureLevels.MaxSupportedFeatureLevel, Enum_D3D_FEATURE_LEVEL); + // NumFeatureLevels and pFeatureLevelsRequested are IN parameters + // They let the app to specify what enum values does the app expect + // So same API can be used when new feature levels are added in the future + // No need to print those IN parameters here + ReportFormatter::GetInstance().AddFieldEnum(L"MaxSupportedFeatureLevel", featureLevels.MaxSupportedFeatureLevel, Enum_D3D_FEATURE_LEVEL); } static void Print_D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT(const D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT& virtualAddressSupport) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT"); - Print_uint32(L"MaxGPUVirtualAddressBitsPerResource", virtualAddressSupport.MaxGPUVirtualAddressBitsPerResource); - Print_uint32(L"MaxGPUVirtualAddressBitsPerProcess", virtualAddressSupport.MaxGPUVirtualAddressBitsPerProcess); - + ReportScopeObject scope(L"D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT"); + ReportFormatter::GetInstance().AddFieldUint32(L"MaxGPUVirtualAddressBitsPerResource", virtualAddressSupport.MaxGPUVirtualAddressBitsPerResource); + ReportFormatter::GetInstance().AddFieldUint32(L"MaxGPUVirtualAddressBitsPerProcess", virtualAddressSupport.MaxGPUVirtualAddressBitsPerProcess); } static void Print_D3D12_FEATURE_DATA_SHADER_MODEL(const D3D12_FEATURE_DATA_SHADER_MODEL& shaderModel) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_SHADER_MODEL"); - PrintEnum(L"HighestShaderModel", shaderModel.HighestShaderModel, Enum_D3D_SHADER_MODEL); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_SHADER_MODEL"); + ReportFormatter::GetInstance().AddFieldEnum(L"HighestShaderModel", shaderModel.HighestShaderModel, Enum_D3D_SHADER_MODEL); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS1(const D3D12_FEATURE_DATA_D3D12_OPTIONS1& options1) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS1"); - Print_BOOL (L"WaveOps", options1.WaveOps); - Print_uint32(L"WaveLaneCountMin", options1.WaveLaneCountMin); - Print_uint32(L"WaveLaneCountMax", options1.WaveLaneCountMax); - Print_uint32(L"TotalLaneCount", options1.TotalLaneCount); - Print_BOOL (L"ExpandedComputeResourceStates", options1.ExpandedComputeResourceStates); - Print_BOOL (L"Int64ShaderOps", options1.Int64ShaderOps); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS1"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldBool(L"WaveOps", options1.WaveOps); + formatter.AddFieldUint32(L"WaveLaneCountMin", options1.WaveLaneCountMin); + formatter.AddFieldUint32(L"WaveLaneCountMax", options1.WaveLaneCountMax); + formatter.AddFieldUint32(L"TotalLaneCount", options1.TotalLaneCount); + formatter.AddFieldBool(L"ExpandedComputeResourceStates", options1.ExpandedComputeResourceStates); + formatter.AddFieldBool(L"Int64ShaderOps", options1.Int64ShaderOps); } static void Print_D3D12_FEATURE_DATA_ROOT_SIGNATURE(const D3D12_FEATURE_DATA_ROOT_SIGNATURE& rootSignature) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_ROOT_SIGNATURE"); - PrintEnum(L"HighestVersion", rootSignature.HighestVersion, Enum_D3D_ROOT_SIGNATURE_VERSION); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_ROOT_SIGNATURE"); + ReportFormatter::GetInstance().AddFieldEnum(L"HighestVersion", rootSignature.HighestVersion, Enum_D3D_ROOT_SIGNATURE_VERSION); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS2(const D3D12_FEATURE_DATA_D3D12_OPTIONS2& options2) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS2"); - Print_BOOL(L"DepthBoundsTestSupported", options2.DepthBoundsTestSupported); - PrintEnum (L"ProgrammableSamplePositionsTier", options2.ProgrammableSamplePositionsTier, Enum_D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS2"); + ReportFormatter::GetInstance().AddFieldBool(L"DepthBoundsTestSupported", options2.DepthBoundsTestSupported); + ReportFormatter::GetInstance().AddFieldEnum(L"ProgrammableSamplePositionsTier", options2.ProgrammableSamplePositionsTier, Enum_D3D12_PROGRAMMABLE_SAMPLE_POSITIONS_TIER); } static void Print_D3D12_FEATURE_DATA_SHADER_CACHE(const D3D12_FEATURE_DATA_SHADER_CACHE& shaderCache) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_SHADER_CACHE"); - PrintFlags(L"SupportFlags", shaderCache.SupportFlags, Enum_D3D12_SHADER_CACHE_SUPPORT_FLAGS); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_SHADER_CACHE"); + ReportFormatter::GetInstance().AddFieldFlags(L"SupportFlags", shaderCache.SupportFlags, Enum_D3D12_SHADER_CACHE_SUPPORT_FLAGS); } static void Print_D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY(const std::array& commandQueuePriority) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY"); - Print_BOOL(L"TYPE_DIRECT.PRIORITY_NORMAL.PriorityForTypeIsSupported", commandQueuePriority[0]); - Print_BOOL(L"TYPE_DIRECT.PRIORITY_HIGH.PriorityForTypeIsSupported", commandQueuePriority[1]); - Print_BOOL(L"TYPE_DIRECT.PRIORITY_GLOBAL_REALTIME.PriorityForTypeIsSupported", commandQueuePriority[2]); - Print_BOOL(L"TYPE_COMPUTE.PRIORITY_NORMAL.PriorityForTypeIsSupported", commandQueuePriority[3]); - Print_BOOL(L"TYPE_COMPUTE.PRIORITY_HIGH.PriorityForTypeIsSupported", commandQueuePriority[4]); - Print_BOOL(L"TYPE_COMPUTE.PRIORITY_GLOBAL_REALTIME.PriorityForTypeIsSupported", commandQueuePriority[5]); - Print_BOOL(L"TYPE_COPY.PRIORITY_NORMAL.PriorityForTypeIsSupported", commandQueuePriority[6]); - Print_BOOL(L"TYPE_COPY.PRIORITY_HIGH.PriorityForTypeIsSupported", commandQueuePriority[7]); - Print_BOOL(L"TYPE_COPY.PRIORITY_GLOBAL_REALTIME.PriorityForTypeIsSupported", commandQueuePriority[8]); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_COMMAND_QUEUE_PRIORITY"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldBool(L"TYPE_DIRECT.PRIORITY_NORMAL.PriorityForTypeIsSupported", commandQueuePriority[0]); + formatter.AddFieldBool(L"TYPE_DIRECT.PRIORITY_HIGH.PriorityForTypeIsSupported", commandQueuePriority[1]); + formatter.AddFieldBool(L"TYPE_DIRECT.PRIORITY_GLOBAL_REALTIME.PriorityForTypeIsSupported", commandQueuePriority[2]); + formatter.AddFieldBool(L"TYPE_COMPUTE.PRIORITY_NORMAL.PriorityForTypeIsSupported", commandQueuePriority[3]); + formatter.AddFieldBool(L"TYPE_COMPUTE.PRIORITY_HIGH.PriorityForTypeIsSupported", commandQueuePriority[4]); + formatter.AddFieldBool(L"TYPE_COMPUTE.PRIORITY_GLOBAL_REALTIME.PriorityForTypeIsSupported", commandQueuePriority[5]); + formatter.AddFieldBool(L"TYPE_COPY.PRIORITY_NORMAL.PriorityForTypeIsSupported", commandQueuePriority[6]); + formatter.AddFieldBool(L"TYPE_COPY.PRIORITY_HIGH.PriorityForTypeIsSupported", commandQueuePriority[7]); + formatter.AddFieldBool(L"TYPE_COPY.PRIORITY_GLOBAL_REALTIME.PriorityForTypeIsSupported", commandQueuePriority[8]); } static void Print_D3D12_FEATURE_DATA_SERIALIZATION(const D3D12_FEATURE_DATA_SERIALIZATION& serialization) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_SERIALIZATION"); - PrintEnum(L"HeapSerializationTier", serialization.HeapSerializationTier, Enum_D3D12_HEAP_SERIALIZATION_TIER); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_SERIALIZATION"); + ReportFormatter::GetInstance().AddFieldEnum(L"HeapSerializationTier", serialization.HeapSerializationTier, Enum_D3D12_HEAP_SERIALIZATION_TIER); } static void Print_D3D12_FEATURE_CROSS_NODE(const D3D12_FEATURE_DATA_CROSS_NODE& crossNode) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_CROSS_NODE"); - PrintEnum(L"SharingTier", crossNode.SharingTier, Enum_D3D12_CROSS_NODE_SHARING_TIER); - Print_BOOL(L"AtomicShaderInstructions", crossNode.AtomicShaderInstructions); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_CROSS_NODE"); + ReportFormatter::GetInstance().AddFieldEnum(L"SharingTier", crossNode.SharingTier, Enum_D3D12_CROSS_NODE_SHARING_TIER); + ReportFormatter::GetInstance().AddFieldBool(L"AtomicShaderInstructions", crossNode.AtomicShaderInstructions); } static void Print_D3D12_FEATURE_PREDICATION(const D3D12_FEATURE_DATA_PREDICATION& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_PREDICATION"); - Print_BOOL(L"Supported", o.Supported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_PREDICATION"); + ReportFormatter::GetInstance().AddFieldBool(L"Supported", o.Supported); } static void Print_D3D12_FEATURE_HARDWARE_COPY(const D3D12_FEATURE_DATA_HARDWARE_COPY& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_HARDWARE_COPY"); - Print_BOOL(L"Supported", o.Supported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_HARDWARE_COPY"); + ReportFormatter::GetInstance().AddFieldBool(L"Supported", o.Supported); } #ifdef USE_PREVIEW_AGILITY_SDK static void Print_D3D12_FEATURE_DATA_APPLICATION_SPECIFIC_DRIVER_STATE(const D3D12_FEATURE_DATA_APPLICATION_SPECIFIC_DRIVER_STATE& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_APPLICATION_SPECIFIC_DRIVER_STATE"); - Print_BOOL(L"Supported", o.Supported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_APPLICATION_SPECIFIC_DRIVER_STATE"); + ReportFormatter::GetInstance().AddFieldBool(L"Supported", o.Supported); } #endif // #ifdef USE_PREVIEW_AGILITY_SDK static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS3(const D3D12_FEATURE_DATA_D3D12_OPTIONS3& options3) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS3"); - Print_BOOL(L"CopyQueueTimestampQueriesSupported", options3.CopyQueueTimestampQueriesSupported); - Print_BOOL(L"CastingFullyTypedFormatSupported", options3.CastingFullyTypedFormatSupported); - PrintFlags(L"WriteBufferImmediateSupportFlags", options3.WriteBufferImmediateSupportFlags, Enum_D3D12_COMMAND_LIST_SUPPORT_FLAGS); - PrintEnum (L"ViewInstancingTier", options3.ViewInstancingTier, Enum_D3D12_VIEW_INSTANCING_TIER); - Print_BOOL(L"BarycentricsSupported", options3.BarycentricsSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS3"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldBool(L"CopyQueueTimestampQueriesSupported", options3.CopyQueueTimestampQueriesSupported); + formatter.AddFieldBool(L"CastingFullyTypedFormatSupported", options3.CastingFullyTypedFormatSupported); + formatter.AddFieldFlags(L"WriteBufferImmediateSupportFlags", options3.WriteBufferImmediateSupportFlags, Enum_D3D12_COMMAND_LIST_SUPPORT_FLAGS); + formatter.AddFieldEnum(L"ViewInstancingTier", options3.ViewInstancingTier, Enum_D3D12_VIEW_INSTANCING_TIER); + formatter.AddFieldBool(L"BarycentricsSupported", options3.BarycentricsSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS4(const D3D12_FEATURE_DATA_D3D12_OPTIONS4& options4) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS4"); - Print_BOOL(L"MSAA64KBAlignedTextureSupported", options4.MSAA64KBAlignedTextureSupported); - PrintEnum(L"SharedResourceCompatibilityTier", options4.SharedResourceCompatibilityTier, Enum_D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER); - Print_BOOL(L"Native16BitShaderOpsSupported", options4.Native16BitShaderOpsSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS4"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldBool(L"MSAA64KBAlignedTextureSupported", options4.MSAA64KBAlignedTextureSupported); + formatter.AddFieldEnum(L"SharedResourceCompatibilityTier", options4.SharedResourceCompatibilityTier, Enum_D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER); + formatter.AddFieldBool(L"Native16BitShaderOpsSupported", options4.Native16BitShaderOpsSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS5(const D3D12_FEATURE_DATA_D3D12_OPTIONS5& options5) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS5"); - Print_BOOL(L"SRVOnlyTiledResourceTier3", options5.SRVOnlyTiledResourceTier3); - PrintEnum(L"RenderPassesTier", options5.RenderPassesTier, Enum_D3D12_RENDER_PASS_TIER); - PrintEnum(L"RaytracingTier", options5.RaytracingTier, Enum_D3D12_RAYTRACING_TIER); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS5"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldBool(L"SRVOnlyTiledResourceTier3", options5.SRVOnlyTiledResourceTier3); + formatter.AddFieldEnum(L"RenderPassesTier", options5.RenderPassesTier, Enum_D3D12_RENDER_PASS_TIER); + formatter.AddFieldEnum(L"RaytracingTier", options5.RaytracingTier, Enum_D3D12_RAYTRACING_TIER); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS6(const D3D12_FEATURE_DATA_D3D12_OPTIONS6& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS6"); - Print_BOOL(L"AdditionalShadingRatesSupported", o.AdditionalShadingRatesSupported); - Print_BOOL(L"PerPrimitiveShadingRateSupportedWithViewportIndexing", o.PerPrimitiveShadingRateSupportedWithViewportIndexing); - PrintEnum(L"VariableShadingRateTier", o.VariableShadingRateTier, Enum_D3D12_VARIABLE_SHADING_RATE_TIER); - Print_uint32(L"ShadingRateImageTileSize", o.ShadingRateImageTileSize); - Print_BOOL(L"BackgroundProcessingSupported", o.BackgroundProcessingSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS6"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldBool(L"AdditionalShadingRatesSupported", o.AdditionalShadingRatesSupported); + formatter.AddFieldBool(L"PerPrimitiveShadingRateSupportedWithViewportIndexing", o.PerPrimitiveShadingRateSupportedWithViewportIndexing); + formatter.AddFieldEnum(L"VariableShadingRateTier", o.VariableShadingRateTier, Enum_D3D12_VARIABLE_SHADING_RATE_TIER); + formatter.AddFieldUint32(L"ShadingRateImageTileSize", o.ShadingRateImageTileSize); + formatter.AddFieldBool(L"BackgroundProcessingSupported", o.BackgroundProcessingSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS7(const D3D12_FEATURE_DATA_D3D12_OPTIONS7& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS7"); - PrintEnum(L"MeshShaderTier", o.MeshShaderTier, Enum_D3D12_MESH_SHADER_TIER); - PrintEnum(L"SamplerFeedbackTier", o.SamplerFeedbackTier, Enum_D3D12_SAMPLER_FEEDBACK_TIER); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS7"); + ReportFormatter::GetInstance().AddFieldEnum(L"MeshShaderTier", o.MeshShaderTier, Enum_D3D12_MESH_SHADER_TIER); + ReportFormatter::GetInstance().AddFieldEnum(L"SamplerFeedbackTier", o.SamplerFeedbackTier, Enum_D3D12_SAMPLER_FEEDBACK_TIER); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS8(const D3D12_FEATURE_DATA_D3D12_OPTIONS8& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS8"); - Print_BOOL(L"UnalignedBlockTexturesSupported", o.UnalignedBlockTexturesSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS8"); + ReportFormatter::GetInstance().AddFieldBool(L"UnalignedBlockTexturesSupported", o.UnalignedBlockTexturesSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS9(const D3D12_FEATURE_DATA_D3D12_OPTIONS9& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS9"); - Print_BOOL(L"MeshShaderPipelineStatsSupported", o.MeshShaderPipelineStatsSupported); - Print_BOOL(L"MeshShaderSupportsFullRangeRenderTargetArrayIndex", o.MeshShaderSupportsFullRangeRenderTargetArrayIndex); - Print_BOOL(L"AtomicInt64OnTypedResourceSupported", o.AtomicInt64OnTypedResourceSupported); - Print_BOOL(L"AtomicInt64OnGroupSharedSupported", o.AtomicInt64OnGroupSharedSupported); - Print_BOOL(L"DerivativesInMeshAndAmplificationShadersSupported", o.DerivativesInMeshAndAmplificationShadersSupported); - PrintEnum(L"WaveMMATier", o.WaveMMATier, Enum_D3D12_WAVE_MMA_TIER); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS9"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldBool(L"MeshShaderPipelineStatsSupported", o.MeshShaderPipelineStatsSupported); + formatter.AddFieldBool(L"MeshShaderSupportsFullRangeRenderTargetArrayIndex", o.MeshShaderSupportsFullRangeRenderTargetArrayIndex); + formatter.AddFieldBool(L"AtomicInt64OnTypedResourceSupported", o.AtomicInt64OnTypedResourceSupported); + formatter.AddFieldBool(L"AtomicInt64OnGroupSharedSupported", o.AtomicInt64OnGroupSharedSupported); + formatter.AddFieldBool(L"DerivativesInMeshAndAmplificationShadersSupported", o.DerivativesInMeshAndAmplificationShadersSupported); + formatter.AddFieldEnum(L"WaveMMATier", o.WaveMMATier, Enum_D3D12_WAVE_MMA_TIER); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS10(const D3D12_FEATURE_DATA_D3D12_OPTIONS10& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS10"); - Print_BOOL(L"VariableRateShadingSumCombinerSupported", o.VariableRateShadingSumCombinerSupported); - Print_BOOL(L"MeshShaderPerPrimitiveShadingRateSupported", o.MeshShaderPerPrimitiveShadingRateSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS10"); + ReportFormatter::GetInstance().AddFieldBool(L"VariableRateShadingSumCombinerSupported", o.VariableRateShadingSumCombinerSupported); + ReportFormatter::GetInstance().AddFieldBool(L"MeshShaderPerPrimitiveShadingRateSupported", o.MeshShaderPerPrimitiveShadingRateSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS11(const D3D12_FEATURE_DATA_D3D12_OPTIONS11& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS11"); - Print_BOOL(L"AtomicInt64OnDescriptorHeapResourceSupported", o.AtomicInt64OnDescriptorHeapResourceSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS11"); + ReportFormatter::GetInstance().AddFieldBool(L"AtomicInt64OnDescriptorHeapResourceSupported", o.AtomicInt64OnDescriptorHeapResourceSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS12(const D3D12_FEATURE_DATA_D3D12_OPTIONS12& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS12"); - PrintEnum(L"MSPrimitivesPipelineStatisticIncludesCulledPrimitives", o.MSPrimitivesPipelineStatisticIncludesCulledPrimitives, Enum_D3D12_TRI_STATE, true); - Print_BOOL(L"EnhancedBarriersSupported", o.EnhancedBarriersSupported); - Print_BOOL(L"RelaxedFormatCastingSupported", o.RelaxedFormatCastingSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS12"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldEnumSigned(L"MSPrimitivesPipelineStatisticIncludesCulledPrimitives", o.MSPrimitivesPipelineStatisticIncludesCulledPrimitives, Enum_D3D12_TRI_STATE); + formatter.AddFieldBool(L"EnhancedBarriersSupported", o.EnhancedBarriersSupported); + formatter.AddFieldBool(L"RelaxedFormatCastingSupported", o.RelaxedFormatCastingSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS13(const D3D12_FEATURE_DATA_D3D12_OPTIONS13& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS13"); - Print_BOOL(L"UnrestrictedBufferTextureCopyPitchSupported", o.UnrestrictedBufferTextureCopyPitchSupported); - Print_BOOL(L"UnrestrictedVertexElementAlignmentSupported", o.UnrestrictedVertexElementAlignmentSupported); - Print_BOOL(L"InvertedViewportHeightFlipsYSupported", o.InvertedViewportHeightFlipsYSupported); - Print_BOOL(L"InvertedViewportDepthFlipsZSupported", o.InvertedViewportDepthFlipsZSupported); - Print_BOOL(L"TextureCopyBetweenDimensionsSupported", o.TextureCopyBetweenDimensionsSupported); - Print_BOOL(L"AlphaBlendFactorSupported", o.AlphaBlendFactorSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS13"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldBool(L"UnrestrictedBufferTextureCopyPitchSupported", o.UnrestrictedBufferTextureCopyPitchSupported); + formatter.AddFieldBool(L"UnrestrictedVertexElementAlignmentSupported", o.UnrestrictedVertexElementAlignmentSupported); + formatter.AddFieldBool(L"InvertedViewportHeightFlipsYSupported", o.InvertedViewportHeightFlipsYSupported); + formatter.AddFieldBool(L"InvertedViewportDepthFlipsZSupported", o.InvertedViewportDepthFlipsZSupported); + formatter.AddFieldBool(L"TextureCopyBetweenDimensionsSupported", o.TextureCopyBetweenDimensionsSupported); + formatter.AddFieldBool(L"AlphaBlendFactorSupported", o.AlphaBlendFactorSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS14(const D3D12_FEATURE_DATA_D3D12_OPTIONS14& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS14"); - Print_BOOL(L"AdvancedTextureOpsSupported", o.AdvancedTextureOpsSupported); - Print_BOOL(L"WriteableMSAATexturesSupported", o.WriteableMSAATexturesSupported); - Print_BOOL(L"IndependentFrontAndBackStencilRefMaskSupported", o.IndependentFrontAndBackStencilRefMaskSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS14"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldBool(L"AdvancedTextureOpsSupported", o.AdvancedTextureOpsSupported); + formatter.AddFieldBool(L"WriteableMSAATexturesSupported", o.WriteableMSAATexturesSupported); + formatter.AddFieldBool(L"IndependentFrontAndBackStencilRefMaskSupported", o.IndependentFrontAndBackStencilRefMaskSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS15(const D3D12_FEATURE_DATA_D3D12_OPTIONS15& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS15"); - Print_BOOL(L"TriangleFanSupported", o.TriangleFanSupported); - Print_BOOL(L"DynamicIndexBufferStripCutSupported", o.DynamicIndexBufferStripCutSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS15"); + ReportFormatter::GetInstance().AddFieldBool(L"TriangleFanSupported", o.TriangleFanSupported); + ReportFormatter::GetInstance().AddFieldBool(L"DynamicIndexBufferStripCutSupported", o.DynamicIndexBufferStripCutSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS16(const D3D12_FEATURE_DATA_D3D12_OPTIONS16& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS16"); - Print_BOOL(L"DynamicDepthBiasSupported", o.DynamicDepthBiasSupported); - Print_BOOL(L"GPUUploadHeapSupported", o.GPUUploadHeapSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS16"); + ReportFormatter::GetInstance().AddFieldBool(L"DynamicDepthBiasSupported", o.DynamicDepthBiasSupported); + ReportFormatter::GetInstance().AddFieldBool(L"GPUUploadHeapSupported", o.GPUUploadHeapSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS17(const D3D12_FEATURE_DATA_D3D12_OPTIONS17& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS17"); - Print_BOOL(L"NonNormalizedCoordinateSamplersSupported", o.NonNormalizedCoordinateSamplersSupported); - Print_BOOL(L"ManualWriteTrackingResourceSupported", o.ManualWriteTrackingResourceSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS17"); + ReportFormatter::GetInstance().AddFieldBool(L"NonNormalizedCoordinateSamplersSupported", o.NonNormalizedCoordinateSamplersSupported); + ReportFormatter::GetInstance().AddFieldBool(L"ManualWriteTrackingResourceSupported", o.ManualWriteTrackingResourceSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS18(const D3D12_FEATURE_DATA_D3D12_OPTIONS18& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS18"); - Print_BOOL(L"RenderPassesValid", o.RenderPassesValid); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS18"); + ReportFormatter::GetInstance().AddFieldBool(L"RenderPassesValid", o.RenderPassesValid); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS19(const D3D12_FEATURE_DATA_D3D12_OPTIONS19& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS19"); - Print_BOOL(L"MismatchingOutputDimensionsSupported", o.MismatchingOutputDimensionsSupported); - Print_uint32(L"SupportedSampleCountsWithNoOutputs", o.SupportedSampleCountsWithNoOutputs); - Print_BOOL(L"PointSamplingAddressesNeverRoundUp", o.PointSamplingAddressesNeverRoundUp); - Print_BOOL(L"RasterizerDesc2Supported", o.RasterizerDesc2Supported); - Print_BOOL(L"NarrowQuadrilateralLinesSupported", o.NarrowQuadrilateralLinesSupported); - Print_BOOL(L"AnisoFilterWithPointMipSupported", o.AnisoFilterWithPointMipSupported); - Print_uint32(L"MaxSamplerDescriptorHeapSize", o.MaxSamplerDescriptorHeapSize); - Print_uint32(L"MaxSamplerDescriptorHeapSizeWithStaticSamplers", o.MaxSamplerDescriptorHeapSizeWithStaticSamplers); - Print_uint32(L"MaxViewDescriptorHeapSize", o.MaxViewDescriptorHeapSize); - Print_BOOL(L"ComputeOnlyCustomHeapSupported", o.ComputeOnlyCustomHeapSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS19"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldBool(L"MismatchingOutputDimensionsSupported", o.MismatchingOutputDimensionsSupported); + formatter.AddFieldUint32(L"SupportedSampleCountsWithNoOutputs", o.SupportedSampleCountsWithNoOutputs); + formatter.AddFieldBool(L"PointSamplingAddressesNeverRoundUp", o.PointSamplingAddressesNeverRoundUp); + formatter.AddFieldBool(L"RasterizerDesc2Supported", o.RasterizerDesc2Supported); + formatter.AddFieldBool(L"NarrowQuadrilateralLinesSupported", o.NarrowQuadrilateralLinesSupported); + formatter.AddFieldBool(L"AnisoFilterWithPointMipSupported", o.AnisoFilterWithPointMipSupported); + formatter.AddFieldUint32(L"MaxSamplerDescriptorHeapSize", o.MaxSamplerDescriptorHeapSize); + formatter.AddFieldUint32(L"MaxSamplerDescriptorHeapSizeWithStaticSamplers", o.MaxSamplerDescriptorHeapSizeWithStaticSamplers); + formatter.AddFieldUint32(L"MaxViewDescriptorHeapSize", o.MaxViewDescriptorHeapSize); + formatter.AddFieldBool(L"ComputeOnlyCustomHeapSupported", o.ComputeOnlyCustomHeapSupported); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS20(const D3D12_FEATURE_DATA_D3D12_OPTIONS20& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS20"); - Print_BOOL(L"ComputeOnlyWriteWatchSupported", o.ComputeOnlyWriteWatchSupported); - PrintEnum(L"RecreateAtTier", o.RecreateAtTier, Enum_D3D12_RECREATE_AT_TIER); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS20"); + ReportFormatter::GetInstance().AddFieldBool(L"ComputeOnlyWriteWatchSupported", o.ComputeOnlyWriteWatchSupported); + ReportFormatter::GetInstance().AddFieldEnum(L"RecreateAtTier", o.RecreateAtTier, Enum_D3D12_RECREATE_AT_TIER); } static void Print_D3D12_FEATURE_DATA_D3D12_OPTIONS21(const D3D12_FEATURE_DATA_D3D12_OPTIONS21& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_D3D12_OPTIONS21"); - PrintEnum(L"WorkGraphsTier", o.WorkGraphsTier, Enum_D3D12_WORK_GRAPHS_TIER); - PrintEnum(L"ExecuteIndirectTier", o.ExecuteIndirectTier, Enum_D3D12_EXECUTE_INDIRECT_TIER); - Print_BOOL(L"SampleCmpGradientAndBiasSupported", o.SampleCmpGradientAndBiasSupported); - Print_BOOL(L"ExtendedCommandInfoSupported", o.ExtendedCommandInfoSupported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_D3D12_OPTIONS21"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldEnum(L"WorkGraphsTier", o.WorkGraphsTier, Enum_D3D12_WORK_GRAPHS_TIER); + formatter.AddFieldEnum(L"ExecuteIndirectTier", o.ExecuteIndirectTier, Enum_D3D12_EXECUTE_INDIRECT_TIER); + formatter.AddFieldBool(L"SampleCmpGradientAndBiasSupported", o.SampleCmpGradientAndBiasSupported); + formatter.AddFieldBool(L"ExtendedCommandInfoSupported", o.ExtendedCommandInfoSupported); } static void Print_D3D12_FEATURE_DATA_BYTECODE_BYPASS_HASH_SUPPORTED(const D3D12_FEATURE_DATA_BYTECODE_BYPASS_HASH_SUPPORTED& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_BYTECODE_BYPASS_HASH_SUPPORTED"); - Print_BOOL(L"Supported", o.Supported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_BYTECODE_BYPASS_HASH_SUPPORTED"); + ReportFormatter::GetInstance().AddFieldBool(L"Supported", o.Supported); } #ifdef USE_PREVIEW_AGILITY_SDK static void Print_D3D12_FEATURE_DATA_TIGHT_ALIGNMENT(const D3D12_FEATURE_DATA_TIGHT_ALIGNMENT& o) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_TIGHT_ALIGNMENT"); - PrintEnum(L"SupportTier", o.SupportTier, Enum_D3D12_TIGHT_ALIGNMENT_TIER); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_TIGHT_ALIGNMENT"); + ReportFormatter::GetInstance().AddFieldEnum(L"SupportTier", o.SupportTier, Enum_D3D12_TIGHT_ALIGNMENT_TIER); } #endif // #ifdef USE_PREVIEW_AGILITY_SDK static void Print_D3D12_FEATURE_DATA_EXISTING_HEAPS(const D3D12_FEATURE_DATA_EXISTING_HEAPS& existingHeaps) { - ScopedStructRegion region(L"D3D12_FEATURE_DATA_EXISTING_HEAPS"); - Print_BOOL(L"Supported", existingHeaps.Supported); + ReportScopeObject scope(L"D3D12_FEATURE_DATA_EXISTING_HEAPS"); + ReportFormatter::GetInstance().AddFieldBool(L"Supported", existingHeaps.Supported); } static void Print_DXGI_QUERY_VIDEO_MEMORY_INFO(const DXGI_QUERY_VIDEO_MEMORY_INFO& videoMemoryInfo) { // Not printing videoMemoryInfo.CurrentUsage, videoMemoryInfo.CurrentReservation. - Print_size(L"Budget", videoMemoryInfo.Budget); - Print_size(L"AvailableForReservation", videoMemoryInfo.AvailableForReservation); -} - -static wstring MakeBuildDateTime() -{ - wchar_t s[128]; - swprintf_s(s, L"%hs, %hs", __DATE__, __TIME__); - return wstring{s}; + ReportFormatter::GetInstance().AddFieldSize(L"Budget", videoMemoryInfo.Budget); + ReportFormatter::GetInstance().AddFieldSize(L"AvailableForReservation", videoMemoryInfo.AvailableForReservation); } #ifdef _DEBUG @@ -462,74 +480,53 @@ static wstring MakeCurrentDate() return wstring{dateStr}; } -static void PrintHeader_Text() +static void PrintVersionHeader() { - wprintf(L"============================\n"); - wprintf(L"D3D12INFO %s\n", PROGRAM_VERSION); - wprintf(L"BuildDate: %s\n", MakeBuildDateTime().c_str()); - wprintf(L"Configuration: %s, %s\n", CONFIG_STR, CONFIG_BIT_STR); - wprintf(L"============================\n"); - PrintEmptyLine(); -} - -static void PrintHeader_Json() -{ - Json::WriteString(L"Header"); - Json::BeginObject(); - - Json::WriteNameAndString(L"Program", L"D3d12info"); - Json::WriteNameAndString(L"Version", PROGRAM_VERSION); - Json::WriteNameAndString(L"Build Date", MakeBuildDateTime()); - Json::WriteNameAndString(L"Configuration", CONFIG_STR); - Json::WriteNameAndString(L"Configuration bits", CONFIG_BIT_STR); - Json::WriteNameAndString(L"Generated on", MakeCurrentDate().c_str()); #ifdef USE_PREVIEW_AGILITY_SDK - Json::WriteNameAndBool(L"Using preview Agility SDK", true); - Json::WriteNameAndNumber(L"D3D12_PREVIEW_SDK_VERSION", uint32_t(D3D12SDKVersion)); + const wchar_t* const AGILITY_SDK_NOTE = L" (preview Agility SDK)"; #else - Json::WriteNameAndBool(L"Using preview Agility SDK", false); - Json::WriteNameAndNumber(L"D3D12_SDK_VERSION", uint32_t(D3D12SDKVersion)); + const wchar_t* const AGILITY_SDK_NOTE = L""; #endif + Printer::PrintString(L"============================\n"); + Printer::PrintFormat(L"D3D12INFO {}{}\n", std::make_wformat_args(PROGRAM_VERSION, AGILITY_SDK_NOTE)); + Printer::PrintFormat(L"BuildDate: {}\n", std::make_wformat_args(BUILD_TIME)); + Printer::PrintFormat(L"Configuration: {}, {}\n", std::make_wformat_args(CONFIG_STR, CONFIG_BIT_STR)); + Printer::PrintString(L"============================"); +} - if(!g_PureD3D12) +static void PrintVersionData() +{ + if (IsTextOutput()) { -#if USE_NVAPI - NvAPI_Inititalize_RAII::PrintStaticParams(); -#endif -#if USE_AGS - AGS_Initialize_RAII::PrintStaticParams(); -#endif -#if USE_AMD_DEVICE_INFO - AmdDeviceInfo_Initialize_RAII::PrintStaticParams(); -#endif -#if USE_VULKAN - Vulkan_Initialize_RAII::PrintStaticParams(); -#endif -#if USE_INTEL_GPUDETECT - IntelData::PrintStaticParams(); -#endif + PrintVersionHeader(); + Printer::PrintNewLine(); + Printer::PrintNewLine(); } - Json::EndObject(); -} - -static void PrintHeaderData() -{ - if(g_UseJson) - PrintHeader_Json(); - else - PrintHeader_Text(); -} + ReportScopeObject scope(SelectString(L"General", L"Header")); + ReportFormatter& formatter = ReportFormatter::GetInstance(); -static void PrintGeneralData() -{ - PrintHeader(L"General", 0); - ++g_Indent; - Print_string(L"Current date", MakeCurrentDate().c_str()); + if (IsJsonOutput()) + { + formatter.AddFieldString(L"Program", L"D3d12info"); + formatter.AddFieldString(L"Version", PROGRAM_VERSION); + formatter.AddFieldString(L"Build Date", BUILD_TIME); + formatter.AddFieldString(L"Configuration", CONFIG_STR); + formatter.AddFieldString(L"Configuration bits", CONFIG_BIT_STR); + } + formatter.AddFieldString(L"Generated on", MakeCurrentDate().c_str()); #ifdef USE_PREVIEW_AGILITY_SDK - Print_uint32(L"D3D12_PREVIEW_SDK_VERSION", uint32_t(D3D12SDKVersion)); + if (IsJsonOutput()) + { + formatter.AddFieldBool(L"Using preview Agility SDK", true); + } + formatter.AddFieldUint32(L"D3D12_PREVIEW_SDK_VERSION", uint32_t(D3D12SDKVersion)); #else - Print_uint32(L"D3D12_SDK_VERSION", uint32_t(D3D12SDKVersion)); + if (IsJsonOutput()) + { + formatter.AddFieldBool(L"Using preview Agility SDK", false); + } + formatter.AddFieldUint32(L"D3D12_SDK_VERSION", uint32_t(D3D12SDKVersion)); #endif if(!g_PureD3D12) @@ -550,56 +547,32 @@ static void PrintGeneralData() IntelData::PrintStaticParams(); #endif } - --g_Indent; - PrintEmptyLine(); } -static void PrintEnums_Json() +static void PrintEnums() { - Json::WriteString(L"Enums"); - Json::BeginObject(); + ReportScopeObject scope(L"Enums"); EnumCollection& enumCollection = EnumCollection::GetInstance(); for(const auto it : enumCollection.m_Enums) { - Json::WriteString(it.first.data(), it.first.length()); - Json::BeginObject(); + ReportScopeObject scope2(std::wstring(it.first.data(), it.first.length())); for(const EnumItem* item = it.second; item->m_Name != nullptr; ++item) { - Json::WriteNameAndNumber(item->m_Name, item->m_Value); + ReportFormatter::GetInstance().AddFieldUint32(item->m_Name, item->m_Value); } - - Json::EndObject(); - } - - Json::EndObject(); -} - -static void PrintEnums_Text() -{ - PrintHeader(L"Enums", 0); - PrintEmptyLine(); - - EnumCollection& enumCollection = EnumCollection::GetInstance(); - for(const auto it : enumCollection.m_Enums) - { - PrintHeader(it.first.c_str(), 1); - - for(const EnumItem* item = it.second; item->m_Name != nullptr; ++item) - Print_uint32(item->m_Name, item->m_Value); - - PrintEmptyLine(); } } static void PrintOsVersionInfo() { - ScopedStructRegion region(L"OS Info"); + ReportScopeObject scope(L"OS Info"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); HMODULE m = GetModuleHandle(L"ntdll.dll"); if(!m) { - Print_string(L"Windows version", L"Unknown"); + formatter.AddFieldString(L"Windows version", L"Unknown"); return; } @@ -607,7 +580,7 @@ static void PrintOsVersionInfo() RtlGetVersionFunc RtlGetVersion = (RtlGetVersionFunc)GetProcAddress(m, "RtlGetVersion"); if(!RtlGetVersion) { - Print_string(L"Windows version", L"Unknown"); + formatter.AddFieldString(L"Windows version", L"Unknown"); return; } @@ -615,14 +588,14 @@ static void PrintOsVersionInfo() // Documentation says it always returns success. RtlGetVersion(&osVersionInfo); - PrintFormat(L"Windows version", L"%lu.%lu.%lu", - osVersionInfo.dwMajorVersion, osVersionInfo.dwMinorVersion, - osVersionInfo.dwBuildNumber); + formatter.AddFieldString(L"Windows version", std::format(L"{}.{}.{}", + osVersionInfo.dwMajorVersion, osVersionInfo.dwMinorVersion, + osVersionInfo.dwBuildNumber)); } static void PrintDXGIFeatureInfo() { - ScopedStructRegion region(L"DXGI_FEATURE"); + ReportScopeObject scope(L"DXGI_FEATURE"); ComPtr dxgiFactory = nullptr; HRESULT hr; #if defined(AUTO_LINK_DX12) @@ -637,24 +610,25 @@ static void PrintDXGIFeatureInfo() &allowTearing, sizeof(allowTearing)); if(SUCCEEDED(hr)) { - Print_BOOL(L"DXGI_FEATURE_PRESENT_ALLOW_TEARING", allowTearing); + ReportFormatter::GetInstance().AddFieldBool(L"DXGI_FEATURE_PRESENT_ALLOW_TEARING", allowTearing); } } static void PrintSystemMemoryInfo() { - ScopedStructRegion region(L"System memory"); + ReportScopeObject scope(L"System memory"); if(uint64_t physicallyInstalledSystemMemory = 0; GetPhysicallyInstalledSystemMemory(&physicallyInstalledSystemMemory)) - Print_sizeKilobytes(L"GetPhysicallyInstalledSystemMemory", physicallyInstalledSystemMemory); + ReportFormatter::GetInstance().AddFieldSizeKilobytes(L"GetPhysicallyInstalledSystemMemory", physicallyInstalledSystemMemory); if(MEMORYSTATUSEX memStatEx = {sizeof(MEMORYSTATUSEX)}; GlobalMemoryStatusEx(&memStatEx)) { - Print_size(L"MEMORYSTATUSEX::ullTotalPhys", memStatEx.ullTotalPhys); - Print_size(L"MEMORYSTATUSEX::ullTotalPageFile", memStatEx.ullTotalPageFile); - Print_size(L"MEMORYSTATUSEX::ullTotalVirtual", memStatEx.ullTotalVirtual); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldSize(L"MEMORYSTATUSEX::ullTotalPhys", memStatEx.ullTotalPhys); + formatter.AddFieldSize(L"MEMORYSTATUSEX::ullTotalPageFile", memStatEx.ullTotalPageFile); + formatter.AddFieldSize(L"MEMORYSTATUSEX::ullTotalVirtual", memStatEx.ullTotalVirtual); } } @@ -703,92 +677,68 @@ static void EnableExperimentalFeatures() if(featureBitMask != 0) // Means enablement succeeded. { - if(g_UseJson) - { - Json::WriteString(L"D3D12EnableExperimentalFeatures"); - Json::BeginArray(); - for(size_t featureIndex = 0; featureIndex < FEATURE_COUNT; ++featureIndex) - { - if((featureBitMask & (1u << featureIndex)) != 0) - Json::WriteString(FEATURE_NAMES[featureIndex]); - } - Json::EndArray(); - } - else - { - PrintHeader(L"D3D12EnableExperimentalFeatures", 1); - ++g_Indent; + std::vector enabledFeatures; - for(size_t featureIndex = 0; featureIndex < FEATURE_COUNT; ++featureIndex) + for(size_t featureIndex = 0; featureIndex < FEATURE_COUNT; ++featureIndex) + { + if((featureBitMask & (1u << featureIndex)) != 0) { - if((featureBitMask & (1u << featureIndex)) != 0) - { - PrintIndent(); - wprintf(L"%s\n", FEATURE_NAMES[featureIndex]); - } + enabledFeatures.push_back(FEATURE_NAMES[featureIndex]); } - - --g_Indent; - PrintEmptyLine(); } - } -} -static void PrintEnumsData() -{ - if(g_UseJson) - PrintEnums_Json(); - else - PrintEnums_Text(); + ReportFormatter::GetInstance().AddFieldStringArray(L"D3D12EnableExperimentalFeatures", enabledFeatures); + } } static void PrintAdapterDescMembers(const DXGI_ADAPTER_DESC& desc) { - Print_string(L"Description", desc.Description); - PrintVendorId(L"VendorId", desc.VendorId); - Print_hex32(L"DeviceId", desc.DeviceId); - PrintSubsystemId(L"SubSysId", desc.SubSysId); - Print_hex32(L"Revision", desc.Revision); - Print_size(L"DedicatedVideoMemory", desc.DedicatedVideoMemory); - Print_size(L"DedicatedSystemMemory", desc.DedicatedSystemMemory); - Print_size(L"SharedSystemMemory", desc.SharedSystemMemory); - Print_string(L"AdapterLuid", LuidToStr(desc.AdapterLuid).c_str()); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldString(L"Description", desc.Description); + formatter.AddFieldVendorId(L"VendorId", desc.VendorId); + formatter.AddFieldHex32(L"DeviceId", desc.DeviceId); + formatter.AddFieldSubsystemId(L"SubSysId", desc.SubSysId); + formatter.AddFieldHex32(L"Revision", desc.Revision); + formatter.AddFieldSize(L"DedicatedVideoMemory", desc.DedicatedVideoMemory); + formatter.AddFieldSize(L"DedicatedSystemMemory", desc.DedicatedSystemMemory); + formatter.AddFieldSize(L"SharedSystemMemory", desc.SharedSystemMemory); + formatter.AddFieldString(L"AdapterLuid", LuidToStr(desc.AdapterLuid).c_str()); } static void PrintAdapterDesc1Members(const DXGI_ADAPTER_DESC1& desc1) { PrintAdapterDescMembers((const DXGI_ADAPTER_DESC&)desc1); - PrintFlags(L"Flags", desc1.Flags, Enum_DXGI_ADAPTER_FLAG); + ReportFormatter::GetInstance().AddFieldFlags(L"Flags", desc1.Flags, Enum_DXGI_ADAPTER_FLAG); } static void PrintAdapterDesc2Members(const DXGI_ADAPTER_DESC2& desc2) { PrintAdapterDesc1Members((const DXGI_ADAPTER_DESC1&)desc2); - PrintEnum(L"GraphicsPreemptionGranularity", desc2.GraphicsPreemptionGranularity, Enum_DXGI_GRAPHICS_PREEMPTION_GRANULARITY); - PrintEnum(L"ComputePreemptionGranularity", desc2.ComputePreemptionGranularity, Enum_DXGI_COMPUTE_PREEMPTION_GRANULARITY); + ReportFormatter::GetInstance().AddFieldEnum(L"GraphicsPreemptionGranularity", desc2.GraphicsPreemptionGranularity, Enum_DXGI_GRAPHICS_PREEMPTION_GRANULARITY); + ReportFormatter::GetInstance().AddFieldEnum(L"ComputePreemptionGranularity", desc2.ComputePreemptionGranularity, Enum_DXGI_COMPUTE_PREEMPTION_GRANULARITY); } static void PrintAdapterDesc(const DXGI_ADAPTER_DESC& desc) { - ScopedStructRegion region(L"DXGI_ADAPTER_DESC"); + ReportScopeObject scope(L"DXGI_ADAPTER_DESC"); PrintAdapterDescMembers(desc); } static void PrintAdapterDesc1(const DXGI_ADAPTER_DESC1& desc1) { - ScopedStructRegion region(L"DXGI_ADAPTER_DESC1"); + ReportScopeObject scope(L"DXGI_ADAPTER_DESC1"); PrintAdapterDesc1Members(desc1); } static void PrintAdapterDesc2(const DXGI_ADAPTER_DESC2& desc2) { - ScopedStructRegion region(L"DXGI_ADAPTER_DESC2"); + ReportScopeObject scope(L"DXGI_ADAPTER_DESC2"); PrintAdapterDesc2Members(desc2); } static void PrintAdapterDesc3(const DXGI_ADAPTER_DESC3& desc3) { - ScopedStructRegion region(L"DXGI_ADAPTER_DESC3"); + ReportScopeObject scope(L"DXGI_ADAPTER_DESC3"); // Same members as DESC2. They only added new items to Flags. PrintAdapterDesc2Members((const DXGI_ADAPTER_DESC2&)desc3); } @@ -839,7 +789,7 @@ static void PrintAdapterMemoryInfo(IDXGIAdapter* adapter) assert(0); } { - ScopedStructRegion region(structName); + ReportScopeObject scope(structName); Print_DXGI_QUERY_VIDEO_MEMORY_INFO(videoMemoryInfo); } } @@ -851,20 +801,8 @@ static void PrintAdapterInterfaceSupport(IDXGIAdapter* adapter) { if(LARGE_INTEGER i; SUCCEEDED(adapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &i))) { - ScopedStructRegion region(L"CheckInterfaceSupport"); - if(g_UseJson) - { - Print_uint64(L"UMDVersion", i.QuadPart); - } - else - { - wstring s = std::format(L"{}.{}.{}.{}", - i.QuadPart >> 48, - (i.QuadPart >> 32) & 0xFFFF, - (i.QuadPart >> 16) & 0xFFFF, - i.QuadPart & 0xFFFF); - Print_string(L"UMDVersion", s.c_str()); - } + ReportScopeObject scope(L"CheckInterfaceSupport"); + ReportFormatter::GetInstance().AddFieldMicrosoftVersion(L"UMDVersion", i.QuadPart); } } @@ -895,13 +833,8 @@ static FormatSupportResult CheckFormatSupport(ID3D12Device* device, D3D12_FEATUR static void PrintFormatInformation(ID3D12Device* device) { - if(g_UseJson) - { - Json::WriteString(L"Formats"); - Json::BeginObject(); - } - else - PrintHeader(L"Formats", 1); + ReportScopeObject scope(L"Formats"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupport = {}; D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msQualityLevels = {}; @@ -916,85 +849,49 @@ static void PrintFormatInformation(ID3D12Device* device) const FormatSupportResult formatSupportResult = CheckFormatSupport(device, formatSupport); if(formatSupportResult == FormatSupportResult::Crashed) { - fwprintf(stderr, L"ERROR: ID3D12Device::CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, %s) crashed.\n", - name); + ErrorPrinter::PrintFormat(L"ERROR: ID3D12Device::CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, {}) crashed.\n", std::make_wformat_args(name)); break; } - if(g_UseJson) - { - Json::WriteString(std::format(L"{}", (size_t)format)); - Json::BeginObject(); - } - else - { - PrintIndent(); - wprintf(L"%s:\n", name); - ++g_Indent; - } + ReportScopeObjectConditional scope2(SelectString(name, std::format(L"{}", (size_t)format))); if(formatSupportResult == FormatSupportResult::Ok) { - PrintFlags(L"Support1", formatSupport.Support1, Enum_D3D12_FORMAT_SUPPORT1); - PrintFlags(L"Support2", formatSupport.Support2, Enum_D3D12_FORMAT_SUPPORT2); - - if(g_UseJson) - { - Json::WriteString(L"MultisampleQualityLevels"); - Json::BeginObject(); - } + scope2.Enable(); + formatter.AddFieldFlags(L"Support1", formatSupport.Support1, Enum_D3D12_FORMAT_SUPPORT1); + formatter.AddFieldFlags(L"Support2", formatSupport.Support2, Enum_D3D12_FORMAT_SUPPORT2); + + ReportScopeObjectConditional scope3(IsJsonOutput(), L"MultisampleQualityLevels"); msQualityLevels.Format = format; for(msQualityLevels.SampleCount = 1; ; msQualityLevels.SampleCount *= 2) { if(SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &msQualityLevels, UINT(sizeof msQualityLevels))) && msQualityLevels.NumQualityLevels > 0) { - if(g_UseJson) + if(IsJsonOutput()) { - Json::WriteString(std::format(L"{}", msQualityLevels.SampleCount)); - Json::BeginObject(); - - Json::WriteNameAndNumber(L"NumQualityLevels", msQualityLevels.NumQualityLevels); - Json::WriteNameAndNumber(L"Flags", uint32_t(msQualityLevels.Flags)); - - Json::EndObject(); + ReportScopeObject scope4(std::format(L"{}", msQualityLevels.SampleCount)); + formatter.AddFieldUint32(L"NumQualityLevels", msQualityLevels.NumQualityLevels); + formatter.AddFieldUint32(L"Flags", uint32_t(msQualityLevels.Flags)); } else { - PrintIndent(); - wprintf(L"SampleCount = %u: NumQualityLevels = %u", msQualityLevels.SampleCount, msQualityLevels.NumQualityLevels); - if((msQualityLevels.Flags & D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_TILED_RESOURCE) != 0) - wprintf(L" D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_TILED_RESOURCE\n"); - else - wprintf(L"\n"); + bool multisampleTiled = (msQualityLevels.Flags & D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_TILED_RESOURCE) != 0; + formatter.AddFieldString(L"SampleCount", std::format(L"{}: NumQualityLevels = {}{}", msQualityLevels.SampleCount, msQualityLevels.NumQualityLevels, multisampleTiled ? L" D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_TILED_RESOURCE" : L"")); } } else break; } - if(g_UseJson) - Json::EndObject(); } formatInfo.Format = format; if(SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, UINT(sizeof formatInfo)))) { - Print_uint32(L"PlaneCount", formatInfo.PlaneCount); - } - - if(g_UseJson) - Json::EndObject(); - else - { - --g_Indent; - PrintEmptyLine(); + scope2.Enable(); + formatter.AddFieldUint32(L"PlaneCount", formatInfo.PlaneCount); } } - - if(g_UseJson) - Json::EndObject(); - else - PrintEmptyLine(); } static void PrintDeviceOptions(ID3D12Device* device) @@ -1100,34 +997,27 @@ static void PrintDeviceOptions(ID3D12Device* device) static void PrintDescriptorSizes(ID3D12Device* device) { - ScopedStructRegion region(L"GetDescriptorHandleIncrementSize"); - Print_uint32(L"D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV", + ReportScopeObject scope(L"GetDescriptorHandleIncrementSize"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); + formatter.AddFieldUint32(L"D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV", device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)); - Print_uint32(L"D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER", + formatter.AddFieldUint32(L"D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER", device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER)); - Print_uint32(L"D3D12_DESCRIPTOR_HEAP_TYPE_RTV", + formatter.AddFieldUint32(L"D3D12_DESCRIPTOR_HEAP_TYPE_RTV", device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV)); - Print_uint32(L"D3D12_DESCRIPTOR_HEAP_TYPE_DSV", + formatter.AddFieldUint32(L"D3D12_DESCRIPTOR_HEAP_TYPE_DSV", device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV)); } static void PrintMetaCommand(ID3D12Device5* device5, UINT index, const D3D12_META_COMMAND_DESC& desc) { - if(g_UseJson) - { - Json::BeginObject(); - } - else - { - PrintIndent(); - wprintf(L"MetaCommand %u:\n", index); - ++g_Indent; - } + ReportScopeArrayItem scope; + ReportFormatter& formatter = ReportFormatter::GetInstance(); - Print_string(L"Id", GuidToStr(desc.Id).c_str()); - Print_string(L"Name", desc.Name); - PrintFlags(L"InitializationDirtyState", desc.InitializationDirtyState, Enum_D3D12_GRAPHICS_STATES); - PrintFlags(L"ExecutionDirtyState", desc.ExecutionDirtyState, Enum_D3D12_GRAPHICS_STATES); + formatter.AddFieldString(L"Id", GuidToStr(desc.Id).c_str()); + formatter.AddFieldString(L"Name", desc.Name); + formatter.AddFieldFlags(L"InitializationDirtyState", desc.InitializationDirtyState, Enum_D3D12_GRAPHICS_STATES); + formatter.AddFieldFlags(L"ExecutionDirtyState", desc.ExecutionDirtyState, Enum_D3D12_GRAPHICS_STATES); for(UINT stageIndex = 0; stageIndex < 3; ++stageIndex) { @@ -1138,22 +1028,12 @@ static void PrintMetaCommand(ID3D12Device5* device5, UINT index, const D3D12_MET &totalStructureSizeInBytes, ¶mCount, nullptr); if(FAILED(hr)) continue; - - if(g_UseJson) - { - Json::WriteString(Enum_D3D12_META_COMMAND_PARAMETER_STAGE[stageIndex].m_Name); - Json::BeginObject(); - Print_uint32(L"TotalStructureSizeInBytes", totalStructureSizeInBytes); - } - else + { - PrintIndent(); - wprintf(L"%s: TotalStructureSizeInBytes=%u\n", - Enum_D3D12_META_COMMAND_PARAMETER_STAGE[stageIndex].m_Name, - totalStructureSizeInBytes); - ++g_Indent; + ReportScopeObject scope2(Enum_D3D12_META_COMMAND_PARAMETER_STAGE[stageIndex].m_Name); + formatter.AddFieldUint32(L"TotalStructureSizeInBytes", totalStructureSizeInBytes); } - + if(paramCount > 0) { std::vector paramDescs(paramCount); @@ -1162,54 +1042,22 @@ static void PrintMetaCommand(ID3D12Device5* device5, UINT index, const D3D12_MET nullptr, ¶mCount, paramDescs.data()); if(SUCCEEDED(hr)) { - if(g_UseJson) - { - Json::WriteString(L"Parameters"); - Json::BeginArray(); - } + ReportScopeArray scope2(L"Parameters"); for(UINT paramIndex = 0; paramIndex < paramCount; ++paramIndex) { const auto& paramDesc = paramDescs[paramIndex]; - if(g_UseJson) - Json::BeginObject(); - else - { - PrintIndent(); - wprintf(L"Parameter %u:\n", paramIndex); - ++g_Indent; - } - - Print_string(L"Name", paramDesc.Name); - PrintEnum(L"Type", paramDesc.Type, Enum_D3D12_META_COMMAND_PARAMETER_TYPE); - PrintFlags(L"Flags", paramDesc.Flags, Enum_D3D12_META_COMMAND_PARAMETER_FLAGS); - PrintFlags(L"RequiredResourceState", paramDesc.RequiredResourceState, Enum_D3D12_RESOURCE_STATES); - Print_uint32(L"StructureOffset", paramDesc.StructureOffset); + ReportScopeArrayItem scope3; - if(g_UseJson) - Json::EndObject(); - else - --g_Indent; + formatter.AddFieldString(L"Name", paramDesc.Name); + formatter.AddFieldEnum(L"Type", paramDesc.Type, Enum_D3D12_META_COMMAND_PARAMETER_TYPE); + formatter.AddFieldFlags(L"Flags", paramDesc.Flags, Enum_D3D12_META_COMMAND_PARAMETER_FLAGS); + formatter.AddFieldFlags(L"RequiredResourceState", paramDesc.RequiredResourceState, Enum_D3D12_RESOURCE_STATES); + formatter.AddFieldUint32(L"StructureOffset", paramDesc.StructureOffset); } - - if(g_UseJson) - Json::EndArray(); } } - - if(g_UseJson) - Json::EndObject(); - else - --g_Indent; - } - - if(g_UseJson) - Json::EndObject(); - else - { - --g_Indent; - PrintEmptyLine(); } } @@ -1223,25 +1071,11 @@ static void PrintMetaCommands(ID3D12Device5* device5) std::vector descs(num); if(FAILED(device5->EnumerateMetaCommands(&num, descs.data()))) return; - - if(g_UseJson) - { - Json::WriteString(L"EnumerateMetaCommands"); - Json::BeginArray(); - } - else - { - PrintHeader(L"EnumerateMetaCommands", 1); - ++g_Indent; - } + + ReportScopeArray scope(L"EnumerateMetaCommands"); for(UINT i = 0; i < num; ++i) PrintMetaCommand(device5, i, descs[i]); - - if(g_UseJson) - Json::EndArray(); - else - --g_Indent; } static void PrintCommandQueuePriorities(ID3D12Device* device) @@ -1281,28 +1115,14 @@ static void PrintCommandQueuePriorities(ID3D12Device* device) static void PrintDirectSROptimizationRankings(const DSR_OPTIMIZATION_TYPE* optimizationRankings) { constexpr size_t count = _countof(DSR_SUPERRES_VARIANT_DESC::OptimizationRankings); - if(g_UseJson) - { - Json::WriteString(L"OptimizationRankings"); - Json::BeginArray(); - ++g_Indent; - for(size_t i = 0; i < count; ++i) - Json::WriteNumber((uint32_t)optimizationRankings[i]); - Json::EndArray(); - } - else + + uint32_t rankingsCopy[count]; + for(size_t i = 0; i < count; ++i) { - PrintIndent(); - wprintf(L"OptimizationRankings:\n"); - ++g_Indent; - for(size_t i = 0; i < count; ++i) - { - const DSR_OPTIMIZATION_TYPE optimizationType = optimizationRankings[i]; - PrintIndent(); - wprintf(L"%s\n", Enum_DSR_OPTIMIZATION_TYPE[optimizationType].m_Name); - } - --g_Indent; + rankingsCopy[i] = (uint32_t)optimizationRankings[i]; } + + ReportFormatter::GetInstance().AddEnumArray(L"OptimizationRankings", rankingsCopy, count, Enum_DSR_OPTIMIZATION_TYPE); } static void PrintDirectSR(ID3D12Device* device) @@ -1317,51 +1137,23 @@ static void PrintDirectSR(ID3D12Device* device) if(numVariants == 0) return; - if(g_UseJson) - { - Json::WriteString(L"DirectSR"); - Json::BeginArray(); - } - else - { - PrintHeader(L"DirectSR", 1); - ++g_Indent; - } + ReportScopeArray scope(L"DirectSR"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); for(UINT variantIndex = 0; variantIndex < numVariants; ++variantIndex) { DSR_SUPERRES_VARIANT_DESC desc = {}; if(SUCCEEDED(dsrDevice->GetSuperResVariantDesc(variantIndex, &desc))) { - if(g_UseJson) - Json::BeginObject(); - else - { - PrintIndent(); - wprintf(L"Variant %u:\n", variantIndex); - ++g_Indent; - } - - Print_string(L"VariantId", GuidToStr(desc.VariantId).c_str()); - Print_string(L"VariantName", StrToWstr(desc.VariantName, CP_UTF8).c_str()); - PrintFlags(L"Flags", desc.Flags, Enum_DSR_SUPERRES_VARIANT_FLAGS); - PrintDirectSROptimizationRankings(desc.OptimizationRankings); - PrintEnum(L"OptimalTargetFormat", desc.OptimalTargetFormat, Enum_DXGI_FORMAT); + ReportScopeArrayItem scope2; - if(g_UseJson) - Json::EndObject(); - else - { - --g_Indent; - PrintEmptyLine(); - } + formatter.AddFieldString(L"VariantId", GuidToStr(desc.VariantId).c_str()); + formatter.AddFieldString(L"VariantName", StrToWstr(desc.VariantName, CP_UTF8).c_str()); + formatter.AddFieldFlags(L"Flags", desc.Flags, Enum_DSR_SUPERRES_VARIANT_FLAGS); + PrintDirectSROptimizationRankings(desc.OptimizationRankings); + formatter.AddFieldEnum(L"OptimalTargetFormat", desc.OptimalTargetFormat, Enum_DXGI_FORMAT); } } - - if(g_UseJson) - Json::EndArray(); - else - --g_Indent; } #endif // #ifdef USE_PREVIEW_AGILITY_SDK @@ -1528,14 +1320,14 @@ static bool LoadLibraries() g_DxgiLibrary = ::LoadLibraryEx(DYN_LIB_DXGI, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); if (!g_DxgiLibrary) { - wprintf(L"could not load %s\n", DYN_LIB_DXGI); + ErrorPrinter::PrintFormat(L"could not load {}\n", std::make_wformat_args(DYN_LIB_DXGI)); return false; } g_Dx12Library = ::LoadLibraryEx(DYN_LIB_DX12, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); if (!g_Dx12Library) { - wprintf(L"could not load %s\n", DYN_LIB_DX12); + ErrorPrinter::PrintFormat(L"could not load {}\n", std::make_wformat_args(DYN_LIB_DX12)); return false; } @@ -1581,42 +1373,42 @@ static void UnloadLibraries() #endif -static void PrintCommandLineSyntax() -{ - wprintf(L"Options:\n"); - wprintf(L" -v --Version Only print program version information.\n"); - wprintf(L" -h --Help Only print this help (command line syntax).\n"); - wprintf(L" -l --List Only print the list of all adapters.\n"); - wprintf(L" -a --Adapter= Print details of adapter at specified index.\n"); - wprintf(L" --AllNonSoftware Print details of all (except WARP and Software) adapters (default behavior).\n"); - wprintf(L" --AllAdapters Print details of all (except WARP) adapters.\n"); - wprintf(L" -j --JSON Print output in JSON format instead of human-friendly text.\n"); - wprintf(L" -f --Formats Include information about DXGI format capabilities.\n"); - wprintf(L" --MetaCommands Include information about meta commands.\n"); - wprintf(L" -e --Enums Include information about all known enums and their values.\n"); - wprintf(L" --PureD3D12 Extract information only from D3D12 and no other sources.\n"); +template +void PrintCommandLineSyntax() +{ + PrinterClass::PrintString(L"Options:\n"); + PrinterClass::PrintString(L" -v --Version Only print program version information.\n"); + PrinterClass::PrintString(L" -h --Help Only print this help (command line syntax).\n"); + PrinterClass::PrintString(L" -l --List Only print the list of all adapters.\n"); + PrinterClass::PrintString(L" -a --Adapter= Print details of adapter at specified index.\n"); + PrinterClass::PrintString(L" --AllAdapters Print details of all adapters.\n"); + PrinterClass::PrintString(L" -j --JSON Print output in JSON format instead of human-friendly text.\n"); + PrinterClass::PrintString(L" --MinimizeJson Print JSON in minimal size form.\n"); + PrinterClass::PrintString(L" -o --OutputFile= Output to specified file.\n"); + PrinterClass::PrintString(L" -f --Formats Include information about DXGI format capabilities.\n"); + PrinterClass::PrintString(L" --MetaCommands Include information about meta commands.\n"); + PrinterClass::PrintString(L" -e --Enums Include information about all known enums and their values.\n"); + PrinterClass::PrintString(L" --PureD3D12 Extract information only from D3D12 and no other sources.\n"); #ifdef USE_PREVIEW_AGILITY_SDK - wprintf(L" -x --EnableExperimental= Whether to enable experimental features before querying device capabilities. Default is on (off for D3d12info and on for D3d12info_preview).\n"); + PrinterClass::PrintString(L" -x --EnableExperimental= Whether to enable experimental features before querying device capabilities. Default is on (off for D3d12info and on for D3d12info_preview).\n"); #else - wprintf(L" -x --EnableExperimental= Whether to enable experimental features before querying device capabilities. Default is off (off for D3d12info and on for D3d12info_preview).\n"); + PrinterClass::PrintString(L" -x --EnableExperimental= Whether to enable experimental features before querying device capabilities. Default is off (off for D3d12info and on for D3d12info_preview).\n"); #endif - wprintf(L" --ForceVendorAPI Tries to query info via vendor-specific APIs, even in case when vendor doesn't match.\n"); - wprintf(L" --WARP Use WARP adapter.\n"); + PrinterClass::PrintString(L" --ForceVendorAPI Tries to query info via vendor-specific APIs, even in case when vendor doesn't match.\n"); + PrinterClass::PrintString(L" --WARP Use WARP adapter.\n"); } static void ListAdapter(uint32_t adapterIndex, IDXGIAdapter* adapter, NvAPI_Inititalize_RAII* nvApi, AGS_Initialize_RAII* ags, AmdDeviceInfo_Initialize_RAII* amdDeviceInfo, Vulkan_Initialize_RAII* vk) { - if(g_UseJson) - { - Json::BeginObject(); - Print_uint32(L"AdapterIndex", adapterIndex); - } - else + ReportScopeArrayItem scope; + + if(!g_WARP && !g_ShowAllAdapters) { - PrintHeader(std::format(L"DXGI Adapter {}", adapterIndex).c_str(), 0); - PrintEmptyLine(); + // In case of WARP, we queried adapter via different API that didn't use adapter index + // In case we show all adapters, array index equals adapter index + ReportFormatter::GetInstance().AddFieldUint32(L"AdapterIndex", adapterIndex); } PrintAdapterData(adapter); @@ -1655,9 +1447,6 @@ static void ListAdapter(uint32_t adapterIndex, IDXGIAdapter* adapter, vk->PrintData(desc); #endif } - - if(g_UseJson) - Json::EndObject(); } static void ListAdapters(IDXGIFactory4* dxgiFactory, NvAPI_Inititalize_RAII* nvApi, AGS_Initialize_RAII* ags, @@ -1685,17 +1474,15 @@ int InspectAdapter(NvAPI_Inititalize_RAII* nvApi, AGS_Initialize_RAII* ags, AmdDeviceInfo_Initialize_RAII* amdDeviceInfo, Vulkan_Initialize_RAII* vk, uint32_t& adapterIndex, ComPtr& adapter1) { + ReportScopeArrayItemConditional scope(g_PrintAdaptersAsArray); + int programResult = PROGRAM_EXIT_SUCCESS; - if(g_UseJson) + if(!g_WARP && !g_ShowAllAdapters) { - Json::BeginObject(); - Print_uint32(L"AdapterIndex", adapterIndex); - } - else - { - PrintHeader(std::format(L"DXGI Adapter {}", adapterIndex).c_str(), 0); - PrintEmptyLine(); + // In case of WARP, we queried adapter via different API that didn't use adapter index + // In case we show all adapters, array index equals adapter index + ReportFormatter::GetInstance().AddFieldUint32(L"AdapterIndex", adapterIndex); } PrintAdapterData(adapter1.Get()); @@ -1746,9 +1533,6 @@ int InspectAdapter(NvAPI_Inititalize_RAII* nvApi, AGS_Initialize_RAII* ags, programResult = PrintDeviceDetails(adapter1.Get(), nvApi, ags); - if(g_UseJson) - Json::EndObject(); - return programResult; } @@ -1830,9 +1614,10 @@ int wmain3(int argc, wchar_t** argv) CMD_LINE_OPT_HELP, CMD_LINE_OPT_LIST, CMD_LINE_OPT_ADAPTER, - CMD_LINE_OPT_ALL_NON_SOFTWARE, CMD_LINE_OPT_ALL_ADAPTERS, CMD_LINE_OPT_JSON, + CMD_LINE_OPT_MINIMIZE_JSON, + CMD_LINE_OPT_OUTPUT_TO_FILE, CMD_LINE_OPT_FORMATS, CMD_LINE_OPT_META_COMMANDS, CMD_LINE_OPT_ENUMS, @@ -1850,10 +1635,12 @@ int wmain3(int argc, wchar_t** argv) cmdLineParser.RegisterOpt(CMD_LINE_OPT_LIST, L'l', false); cmdLineParser.RegisterOpt(CMD_LINE_OPT_ADAPTER, L"Adapter", true); cmdLineParser.RegisterOpt(CMD_LINE_OPT_ADAPTER, L'a', true); - cmdLineParser.RegisterOpt(CMD_LINE_OPT_ALL_NON_SOFTWARE, L"AllNonSoftware", false); cmdLineParser.RegisterOpt(CMD_LINE_OPT_ALL_ADAPTERS, L"AllAdapters", false); cmdLineParser.RegisterOpt(CMD_LINE_OPT_JSON, L"JSON", false); cmdLineParser.RegisterOpt(CMD_LINE_OPT_JSON, L'j', false); + cmdLineParser.RegisterOpt(CMD_LINE_OPT_MINIMIZE_JSON, L"MinimizeJson", false); + cmdLineParser.RegisterOpt(CMD_LINE_OPT_OUTPUT_TO_FILE, L'o', true); + cmdLineParser.RegisterOpt(CMD_LINE_OPT_OUTPUT_TO_FILE, L"OutputFile", true); cmdLineParser.RegisterOpt(CMD_LINE_OPT_FORMATS, L"Formats", false); cmdLineParser.RegisterOpt(CMD_LINE_OPT_FORMATS, L'f', false); cmdLineParser.RegisterOpt(CMD_LINE_OPT_META_COMMANDS, L"MetaCommands", false); @@ -1872,68 +1659,59 @@ int wmain3(int argc, wchar_t** argv) { case CmdLineParser::RESULT_ERROR: case CmdLineParser::RESULT_PARAMETER: - PrintCommandLineSyntax(); - return PROGRAM_EXIT_ERROR_COMMAND_LINE; + g_ShowCommandLineSyntaxAndFail = true; + break; case CmdLineParser::RESULT_OPT: switch(cmdLineParser.GetOptId()) { case CMD_LINE_OPT_VERSION: - PrintHeader_Text(); - return PROGRAM_EXIT_SUCCESS; + g_ShowVersionAndQuit = true; + break; case CMD_LINE_OPT_HELP: - PrintCommandLineSyntax(); - return PROGRAM_EXIT_SUCCESS; + g_ShowCommandLineSyntaxAndQuit = true; + break; case CMD_LINE_OPT_LIST: if(cmdLineParser.IsOptEncountered(CMD_LINE_OPT_ADAPTER) || - cmdLineParser.IsOptEncountered(CMD_LINE_OPT_ALL_NON_SOFTWARE) || cmdLineParser.IsOptEncountered(CMD_LINE_OPT_ALL_ADAPTERS) || cmdLineParser.IsOptEncountered(CMD_LINE_OPT_WARP)) { - PrintCommandLineSyntax(); - return PROGRAM_EXIT_ERROR_COMMAND_LINE; + g_ShowCommandLineSyntaxAndFail = true; + break; } g_ListAdapters = true; break; case CMD_LINE_OPT_ADAPTER: if(cmdLineParser.IsOptEncountered(CMD_LINE_OPT_LIST) || - cmdLineParser.IsOptEncountered(CMD_LINE_OPT_ALL_NON_SOFTWARE) || cmdLineParser.IsOptEncountered(CMD_LINE_OPT_ALL_ADAPTERS) || cmdLineParser.IsOptEncountered(CMD_LINE_OPT_WARP)) { - PrintCommandLineSyntax(); - return PROGRAM_EXIT_ERROR_COMMAND_LINE; + g_ShowCommandLineSyntaxAndFail = true; + break; } g_ShowAllAdapters = false; adapterIndex = _wtoi(cmdLineParser.GetParameter().c_str()); break; - case CMD_LINE_OPT_ALL_NON_SOFTWARE: - if(cmdLineParser.IsOptEncountered(CMD_LINE_OPT_LIST) || - cmdLineParser.IsOptEncountered(CMD_LINE_OPT_ADAPTER) || - cmdLineParser.IsOptEncountered(CMD_LINE_OPT_ALL_ADAPTERS) || - cmdLineParser.IsOptEncountered(CMD_LINE_OPT_WARP)) - { - PrintCommandLineSyntax(); - return PROGRAM_EXIT_ERROR_COMMAND_LINE; - } - g_ShowAllAdapters = true; - g_SkipSoftwareAdapter = true; - adapterIndex = UINT32_MAX; - break; case CMD_LINE_OPT_ALL_ADAPTERS: if(cmdLineParser.IsOptEncountered(CMD_LINE_OPT_LIST) || cmdLineParser.IsOptEncountered(CMD_LINE_OPT_ADAPTER) || - cmdLineParser.IsOptEncountered(CMD_LINE_OPT_ALL_NON_SOFTWARE) || cmdLineParser.IsOptEncountered(CMD_LINE_OPT_WARP)) { - PrintCommandLineSyntax(); - return PROGRAM_EXIT_ERROR_COMMAND_LINE; + g_ShowCommandLineSyntaxAndFail = true; + break; } g_ShowAllAdapters = true; g_SkipSoftwareAdapter = false; adapterIndex = UINT32_MAX; break; case CMD_LINE_OPT_JSON: - g_UseJson = true; + g_UseJsonOutput = true; + break; + case CMD_LINE_OPT_MINIMIZE_JSON: + g_UseJsonPrettyPrint = false; + break; + case CMD_LINE_OPT_OUTPUT_TO_FILE: + g_OutputFile = true; + g_OutputFilePath = cmdLineParser.GetParameter(); break; case CMD_LINE_OPT_FORMATS: g_PrintFormats = true; @@ -1947,8 +1725,8 @@ int wmain3(int argc, wchar_t** argv) case CMD_LINE_OPT_PURE_D3D12: if (cmdLineParser.IsOptEncountered(CMD_LINE_OPT_FORCE_VENDOR_SPECIFIC)) { - PrintCommandLineSyntax(); - return PROGRAM_EXIT_ERROR_COMMAND_LINE; + g_ShowCommandLineSyntaxAndFail = true; + break; } g_PureD3D12 = true; break; @@ -1959,8 +1737,8 @@ int wmain3(int argc, wchar_t** argv) bool isOff = ::_wcsicmp(param.c_str(), L"off") == 0; if (!isOn && !isOff) { - PrintCommandLineSyntax(); - return PROGRAM_EXIT_ERROR_COMMAND_LINE; + g_ShowCommandLineSyntaxAndFail = true; + break; } g_EnableExperimental = isOn; } @@ -1968,36 +1746,77 @@ int wmain3(int argc, wchar_t** argv) case CMD_LINE_OPT_FORCE_VENDOR_SPECIFIC: if (cmdLineParser.IsOptEncountered(CMD_LINE_OPT_PURE_D3D12)) { - PrintCommandLineSyntax(); - return PROGRAM_EXIT_ERROR_COMMAND_LINE; + g_ShowCommandLineSyntaxAndFail = true; + break; } g_ForceVendorAPI = true; break; case CMD_LINE_OPT_WARP: if(cmdLineParser.IsOptEncountered(CMD_LINE_OPT_LIST) || cmdLineParser.IsOptEncountered(CMD_LINE_OPT_ADAPTER) || - cmdLineParser.IsOptEncountered(CMD_LINE_OPT_ALL_NON_SOFTWARE) || cmdLineParser.IsOptEncountered(CMD_LINE_OPT_ALL_ADAPTERS)) { - PrintCommandLineSyntax(); - return PROGRAM_EXIT_ERROR_COMMAND_LINE; + g_ShowCommandLineSyntaxAndFail = true; + break; } g_WARP = true; break; default: - PrintCommandLineSyntax(); - return PROGRAM_EXIT_ERROR_COMMAND_LINE; + g_ShowCommandLineSyntaxAndFail = true; + break; } break; default: assert(0); + g_ShowCommandLineSyntaxAndFail = true; + break; } } - if(g_UseJson) - Json::Begin(); + if (g_ShowCommandLineSyntaxAndFail) + { + PrinterScope scope(false, {}); + PrintCommandLineSyntax(); + return PROGRAM_EXIT_ERROR_COMMAND_LINE; + } + + g_PrintAdaptersAsArray = g_ShowAllAdapters || g_UseJsonOutput; + + PrinterScope printerScope(g_OutputFile, g_OutputFilePath); + + ReportFormatter::FLAGS flags = ReportFormatter::FLAGS::FLAG_NONE; + + if (g_UseJsonOutput) + { + flags |= ReportFormatter::FLAGS::FLAG_JSON; + } + if (g_UseJsonPrettyPrint) + { + flags |= ReportFormatter::FLAGS::FLAG_JSON_PRETTY_PRINT; + } - PrintHeaderData(); + ReportFormatterScope formatterScope(flags); + + if (g_ShowVersionAndQuit) + { + if (IsTextOutput()) + { + PrintVersionHeader(); + } + else + { + PrintVersionData(); + } + return PROGRAM_EXIT_SUCCESS; + } + + if (g_ShowCommandLineSyntaxAndQuit) + { + PrintCommandLineSyntax(); + return PROGRAM_EXIT_SUCCESS; + } + + PrintVersionData(); #if !defined(AUTO_LINK_DX12) if(!LoadLibraries()) @@ -2028,24 +1847,16 @@ int wmain3(int argc, wchar_t** argv) vkObjPtr = std::make_unique(); #endif - - if(g_UseJson) - { - Json::WriteString(L"SystemInfo"); - Json::BeginObject(); - } - else { - PrintGeneralData(); - } + ReportScopeObject scope(SelectString(L"System Info", L"SystemInfo")); - if(!g_PureD3D12) - { - PrintOsVersionInfo(); - PrintSystemMemoryInfo(); - } + if(!g_PureD3D12) + { + PrintOsVersionInfo(); + PrintSystemMemoryInfo(); + } - PrintDXGIFeatureInfo(); + PrintDXGIFeatureInfo(); #if USE_NVAPI if(nvApiObjPtr && nvApiObjPtr->IsInitialized()) @@ -2056,15 +1867,11 @@ int wmain3(int argc, wchar_t** argv) agsObjPtr->PrintData(); #endif - EnableExperimentalFeatures(); - - if(g_UseJson) - { - Json::EndObject(); + EnableExperimentalFeatures(); } if(g_PrintEnums) - PrintEnumsData(); + PrintEnums(); int programResult = PROGRAM_EXIT_SUCCESS; @@ -2078,11 +1885,8 @@ int wmain3(int argc, wchar_t** argv) #endif assert(dxgiFactory != nullptr); - if(g_UseJson) - { - Json::WriteString(L"Adapters"); - Json::BeginArray(); - } + ReportScopeArrayConditional scopeArray(g_PrintAdaptersAsArray, SelectString(L"Adapter", L"Adapters"), ReportFormatter::ARRAY_SUFFIX_NONE); + ReportScopeObjectConditional scopeObject(!g_PrintAdaptersAsArray, L"Adapter"); if(g_ListAdapters) ListAdapters(dxgiFactory.Get(), nvApiObjPtr.get(), agsObjPtr.get(), amdDeviceInfoObjPtr.get(), vkObjPtr.get()); @@ -2095,25 +1899,12 @@ int wmain3(int argc, wchar_t** argv) else InspectAllAdapters(dxgiFactory.Get(), nvApiObjPtr.get(), agsObjPtr.get(), amdDeviceInfoObjPtr.get(), vkObjPtr.get()); } - - if(g_UseJson) - { - Json::EndArray(); - } } #if !defined(AUTO_LINK_DX12) UnloadLibraries(); #endif - if(g_UseJson && programResult == PROGRAM_EXIT_SUCCESS) - { - wstring json = Json::End(); - wprintf(L"%.*s", (int)json.length(), json.data()); - } - - fflush(stdout); - fflush(stderr); return programResult; } @@ -2125,16 +1916,13 @@ int wmain2(int argc, wchar_t** argv) } catch(const std::exception& ex) { - fwprintf(stderr, L"ERROR: %hs\n", ex.what()); - fflush(stdout); - fflush(stderr); + const char* errorMessage = ex.what(); + ErrorPrinter::PrintFormat("ERROR: {}\n", std::make_format_args(errorMessage)); return PROGRAM_EXIT_ERROR_EXCEPTION; } catch(...) { - fwprintf(stderr, L"UNKNOWN ERROR.\n"); - fflush(stdout); - fflush(stderr); + ErrorPrinter::PrintString("UNKNOWN ERROR.\n"); return PROGRAM_EXIT_ERROR_EXCEPTION; } } @@ -2147,9 +1935,8 @@ int wmain(int argc, wchar_t** argv) } __except(EXCEPTION_EXECUTE_HANDLER) { - fwprintf(stderr, L"STRUCTURED EXCEPTION: 0x%08X.\n", GetExceptionCode()); - fflush(stdout); - fflush(stderr); + unsigned long exceptionCode = GetExceptionCode(); + ErrorPrinter::PrintFormat("STRUCTURED EXCEPTION: 0x{:08X}\n", std::make_format_args(exceptionCode)); return PROGRAM_EXIT_ERROR_SEH_EXCEPTION; } } diff --git a/Src/NvApiData.cpp b/Src/NvApiData.cpp index 53b68b8..f8ece80 100644 --- a/Src/NvApiData.cpp +++ b/Src/NvApiData.cpp @@ -8,10 +8,9 @@ License: MIT For more information, see files README.md, LICENSE.txt. */ #include "NvApiData.hpp" -#include "Printing.hpp" #include "Enums.hpp" -#include "Json.hpp" #include "Utils.hpp" +#include "ReportFormatter/ReportFormatter.hpp" // Macro set by Cmake. #if USE_NVAPI @@ -343,6 +342,7 @@ static const EnumItem Enum_NV_ARCH_plus_IMPLEMENTATION_ID[] = { { L"NV_GPU_ARCH_IMPLEMENTATION_GA100", 0x00000170 }, { L"NV_GPU_ARCH_IMPLEMENTATION_GA102", 0x00000172 }, { L"NV_GPU_ARCH_IMPLEMENTATION_GA104", 0x00000174 }, + { L"NV_GPU_ARCH_IMPLEMENTATION_GA106", 0x00000176 }, { L"NV_GPU_ARCH_IMPLEMENTATION_AD102", 0x00000192 }, { L"NV_GPU_ARCH_IMPLEMENTATION_AD103", 0x00000193 }, @@ -547,58 +547,26 @@ static bool FindPhysicalGpuAdapterType(NvPhysicalGpuHandle physicalGpuHandle, NV static void PrintCooperativeVectorProperty(size_t index, const NVAPI_COOPERATIVE_VECTOR_PROPERTIES& props) { - if (g_UseJson) - { - Json::BeginObject(); - } - else - { - PrintIndent(); - wprintf(L"NVAPI_COOPERATIVE_VECTOR_PROPERTIES %zu:\n", index); - ++g_Indent; - } - - Print_hex32(L"version", props.version); - PrintEnum(L"inputType", props.inputType, Enum_NVAPI_COOPERATIVE_VECTOR_COMPONENT_TYPE); - PrintEnum(L"inputInterpretation", props.inputInterpretation, Enum_NVAPI_COOPERATIVE_VECTOR_COMPONENT_TYPE); - PrintEnum(L"matrixInterpretation", props.matrixInterpretation, Enum_NVAPI_COOPERATIVE_VECTOR_COMPONENT_TYPE); - PrintEnum(L"biasInterpretation", props.biasInterpretation, Enum_NVAPI_COOPERATIVE_VECTOR_COMPONENT_TYPE); - PrintEnum(L"resultType", props.resultType, Enum_NVAPI_COOPERATIVE_VECTOR_COMPONENT_TYPE); - Print_BOOL(L"transpose", props.transpose); - - if (g_UseJson) - Json::EndObject(); - else - { - --g_Indent; - } + ReportScopeArrayItem scope; + ReportFormatter& formatter = ReportFormatter::GetInstance(); + + formatter.AddFieldHex32(L"version", props.version); + formatter.AddFieldEnum(L"inputType", props.inputType, Enum_NVAPI_COOPERATIVE_VECTOR_COMPONENT_TYPE); + formatter.AddFieldEnum(L"inputInterpretation", props.inputInterpretation, Enum_NVAPI_COOPERATIVE_VECTOR_COMPONENT_TYPE); + formatter.AddFieldEnum(L"matrixInterpretation", props.matrixInterpretation, Enum_NVAPI_COOPERATIVE_VECTOR_COMPONENT_TYPE); + formatter.AddFieldEnum(L"biasInterpretation", props.biasInterpretation, Enum_NVAPI_COOPERATIVE_VECTOR_COMPONENT_TYPE); + formatter.AddFieldEnum(L"resultType", props.resultType, Enum_NVAPI_COOPERATIVE_VECTOR_COMPONENT_TYPE); + formatter.AddFieldBool(L"transpose", props.transpose); } static void PrintCooperativeVectorProperties(const std::vector& props) { - if (g_UseJson) - { - Json::WriteString(L"NvAPI_D3D12_GetPhysicalDeviceCooperativeVectorProperties"); - Json::BeginArray(); - } - else - { - PrintHeader(L"NvAPI_D3D12_GetPhysicalDeviceCooperativeVectorProperties", 1); - ++g_Indent; - } + ReportScopeArray scope(L"NvAPI_D3D12_GetPhysicalDeviceCooperativeVectorProperties"); for(size_t i = 0; i < props.size(); ++i) { PrintCooperativeVectorProperty(i, props[i]); } - - if (g_UseJson) - Json::EndArray(); - else - { - --g_Indent; - PrintEmptyLine(); - } } //////////////////////////////////////////////////////////////////////////////// @@ -606,12 +574,13 @@ static void PrintCooperativeVectorProperties(const std::vectorm_Name != nullptr; ++ei) { bool supported = false; if(NvAPI_D3D12_IsNvShaderExtnOpCodeSupported(device, ei->m_Value, &supported) == NVAPI_OK) - Print_BOOL(ei->m_Name, supported); + { + scope.Enable(); + formatter.AddFieldBool(ei->m_Name, supported); + } } } @@ -686,18 +660,19 @@ void NvAPI_Inititalize_RAII::PrintD3d12DeviceData(ID3D12Device* device) NvU32 threadCount = 0; if(NvAPI_D3D12_GetOptimalThreadCountForMesh(device, &threadCount) == NVAPI_OK) { - ScopedStructRegion region(L"NvAPI_D3D12_GetOptimalThreadCountForMesh"); - Print_uint32(L"pThreadCount", (uint32_t)threadCount); + ReportScopeObject scope(L"NvAPI_D3D12_GetOptimalThreadCountForMesh"); + formatter.AddFieldUint32(L"pThreadCount", (uint32_t)threadCount); } } { - ScopedStructRegion region(L"NvAPI_D3D12_GetRaytracingCaps"); + ReportScopeObjectConditional scope(L"NvAPI_D3D12_GetRaytracingCaps"); NVAPI_D3D12_RAYTRACING_THREAD_REORDERING_CAPS threadReorderingCaps = {}; if(NvAPI_D3D12_GetRaytracingCaps(device, NVAPI_D3D12_RAYTRACING_CAPS_TYPE_THREAD_REORDERING, &threadReorderingCaps, sizeof threadReorderingCaps) == NVAPI_OK) { - PrintEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_THREAD_REORDERING", (uint32_t)threadReorderingCaps, + scope.Enable(); + formatter.AddFieldEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_THREAD_REORDERING", (uint32_t)threadReorderingCaps, Enum_NVAPI_D3D12_RAYTRACING_THREAD_REORDERING_CAPS); } @@ -705,7 +680,8 @@ void NvAPI_Inititalize_RAII::PrintD3d12DeviceData(ID3D12Device* device) if(NvAPI_D3D12_GetRaytracingCaps(device, NVAPI_D3D12_RAYTRACING_CAPS_TYPE_OPACITY_MICROMAP, &opacityMicromapCaps, sizeof opacityMicromapCaps) == NVAPI_OK) { - PrintEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_OPACITY_MICROMAP", (uint32_t)opacityMicromapCaps, + scope.Enable(); + formatter.AddFieldEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_OPACITY_MICROMAP", (uint32_t)opacityMicromapCaps, Enum_NVAPI_D3D12_RAYTRACING_OPACITY_MICROMAP_CAPS); } @@ -713,7 +689,8 @@ void NvAPI_Inititalize_RAII::PrintD3d12DeviceData(ID3D12Device* device) if(NvAPI_D3D12_GetRaytracingCaps(device, NVAPI_D3D12_RAYTRACING_CAPS_TYPE_DISPLACEMENT_MICROMAP, &displacementMicromapCaps, sizeof displacementMicromapCaps) == NVAPI_OK) { - PrintEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_DISPLACEMENT_MICROMAP", (uint32_t)displacementMicromapCaps, + scope.Enable(); + formatter.AddFieldEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_DISPLACEMENT_MICROMAP", (uint32_t)displacementMicromapCaps, Enum_NVAPI_D3D12_RAYTRACING_DISPLACEMENT_MICROMAP_CAPS); } @@ -721,7 +698,8 @@ void NvAPI_Inititalize_RAII::PrintD3d12DeviceData(ID3D12Device* device) NvAPI_D3D12_GetRaytracingCaps(device, NVAPI_D3D12_RAYTRACING_CAPS_TYPE_CLUSTER_OPERATIONS, &caps, sizeof caps) == NVAPI_OK) { - PrintEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_CLUSTER_OPERATIONS", (uint32_t)caps, + scope.Enable(); + formatter.AddFieldEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_CLUSTER_OPERATIONS", (uint32_t)caps, Enum_NVAPI_D3D12_RAYTRACING_CLUSTER_OPERATIONS_CAPS); } @@ -729,7 +707,8 @@ void NvAPI_Inititalize_RAII::PrintD3d12DeviceData(ID3D12Device* device) NvAPI_D3D12_GetRaytracingCaps(device, NVAPI_D3D12_RAYTRACING_CAPS_TYPE_PARTITIONED_TLAS, &caps, sizeof caps) == NVAPI_OK) { - PrintEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_PARTITIONED_TLAS", (uint32_t)caps, + scope.Enable(); + formatter.AddFieldEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_PARTITIONED_TLAS", (uint32_t)caps, Enum_NVAPI_D3D12_RAYTRACING_PARTITIONED_TLAS_CAPS); } @@ -737,7 +716,8 @@ void NvAPI_Inititalize_RAII::PrintD3d12DeviceData(ID3D12Device* device) NvAPI_D3D12_GetRaytracingCaps(device, NVAPI_D3D12_RAYTRACING_CAPS_TYPE_SPHERES, &caps, sizeof caps) == NVAPI_OK) { - PrintEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_SPHERES", (uint32_t)caps, + scope.Enable(); + formatter.AddFieldEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_SPHERES", (uint32_t)caps, Enum_NVAPI_D3D12_RAYTRACING_SPHERES_CAPS); } @@ -745,30 +725,32 @@ void NvAPI_Inititalize_RAII::PrintD3d12DeviceData(ID3D12Device* device) NvAPI_D3D12_GetRaytracingCaps(device, NVAPI_D3D12_RAYTRACING_CAPS_TYPE_LINEAR_SWEPT_SPHERES, &caps, sizeof caps) == NVAPI_OK) { - PrintEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_LINEAR_SWEPT_SPHERES", (uint32_t)caps, + scope.Enable(); + formatter.AddFieldEnum(L"NVAPI_D3D12_RAYTRACING_CAPS_TYPE_LINEAR_SWEPT_SPHERES", (uint32_t)caps, Enum_NVAPI_D3D12_RAYTRACING_LINEAR_SWEPT_SPHERES_CAPS); } } { - ScopedStructRegion region(L"NvAPI_D3D12_QueryWorkstationFeatureProperties"); + ReportScopeObjectConditional scope(L"NvAPI_D3D12_QueryWorkstationFeatureProperties"); NVAPI_D3D12_WORKSTATION_FEATURE_PROPERTIES_PARAMS params = { .version = NVAPI_D3D12_WORKSTATION_FEATURE_PROPERTIES_PARAMS_VER }; params.workstationFeatureType = NV_D3D12_WORKSTATION_FEATURE_TYPE_PRESENT_BARRIER; if(NvAPI_D3D12_QueryWorkstationFeatureProperties(device, ¶ms) == NVAPI_OK) { - Print_BOOL(L"NV_D3D12_WORKSTATION_FEATURE_TYPE_PRESENT_BARRIER - supported", params.supported); + scope.Enable(); + formatter.AddFieldBool(L"NV_D3D12_WORKSTATION_FEATURE_TYPE_PRESENT_BARRIER - supported", params.supported); } params.workstationFeatureType = NV_D3D12_WORKSTATION_FEATURE_TYPE_RDMA_BAR1_SUPPORT; if(NvAPI_D3D12_QueryWorkstationFeatureProperties(device, ¶ms) == NVAPI_OK) { - Print_BOOL(L"NV_D3D12_WORKSTATION_FEATURE_TYPE_RDMA_BAR1_SUPPORT - supported", params.supported); - if(params.supported) + scope.Enable(); + formatter.AddFieldBool(L"NV_D3D12_WORKSTATION_FEATURE_TYPE_RDMA_BAR1_SUPPORT - supported", params.supported); + if (params.supported) { - Print_uint64(L"NV_D3D12_WORKSTATION_FEATURE_TYPE_RDMA_BAR1_SUPPORT - rdmaHeapSize", params.rdmaInfo.rdmaHeapSize); - + formatter.AddFieldUint64(L"NV_D3D12_WORKSTATION_FEATURE_TYPE_RDMA_BAR1_SUPPORT - rdmaHeapSize", params.rdmaInfo.rdmaHeapSize); } } } @@ -777,8 +759,8 @@ void NvAPI_Inititalize_RAII::PrintD3d12DeviceData(ID3D12Device* device) bool appClampNeeded = false; if(NvAPI_D3D12_GetNeedsAppFPBlendClamping(device, &appClampNeeded) == NVAPI_OK) { - ScopedStructRegion region(L"NvAPI_D3D12_GetNeedsAppFPBlendClamping"); - Print_BOOL(L"pAppClampNeeded", appClampNeeded); + ReportScopeObject scope(L"NvAPI_D3D12_GetNeedsAppFPBlendClamping"); + formatter.AddFieldBool(L"pAppClampNeeded", appClampNeeded); } } @@ -794,25 +776,6 @@ void NvAPI_Inititalize_RAII::PrintD3d12DeviceData(ID3D12Device* device) } } -// Prints only implementationId as the numerical value, but searches enum -// using architectureId + implementationId. -static void PrintNvImplementationId(const wchar_t* name, uint32_t architectureId, uint32_t implementationId) -{ - if(g_UseJson) - Print_uint32(name, implementationId); - else - { - PrintIndent(); - PrintName(name); - const wchar_t* enumItemName = FindEnumItemName(architectureId + implementationId, - Enum_NV_ARCH_plus_IMPLEMENTATION_ID); - if(enumItemName != nullptr) - wprintf(L" = %s (0x%X)\n", enumItemName, implementationId); - else - wprintf(L" = 0x%X\n", implementationId); - } -} - void NvAPI_Inititalize_RAII::PrintPhysicalGpuData(const LUID& adapterLuid) { assert(m_Initialized); @@ -823,71 +786,70 @@ void NvAPI_Inititalize_RAII::PrintPhysicalGpuData(const LUID& adapterLuid) if(!FindPhysicalGpu(adapterLuid, gpu)) return; - ScopedStructRegion region(L"NvPhysicalGpuHandle"); + ReportScopeObject scope(L"NvPhysicalGpuHandle"); + ReportFormatter& formatter = ReportFormatter::GetInstance(); if(NV_ADAPTER_TYPE adapterType; FindPhysicalGpuAdapterType(gpu, adapterType)) { - PrintFlags(L"adapterType", (uint32_t)adapterType, Enum_NV_ADAPTER_TYPE); + formatter.AddFieldFlags(L"adapterType", (uint32_t)adapterType, Enum_NV_ADAPTER_TYPE); } NV_SYSTEM_TYPE systemType = {}; if(NvAPI_GPU_GetSystemType(gpu, &systemType) == NVAPI_OK) - PrintEnum(L"NvAPI_GPU_GetSystemType", systemType, Enum_NV_SYSTEM_TYPE); + formatter.AddFieldEnum(L"NvAPI_GPU_GetSystemType", systemType, Enum_NV_SYSTEM_TYPE); NvAPI_ShortString name = {}; if(NvAPI_GPU_GetFullName(gpu, name) == NVAPI_OK) - Print_string(L"NvAPI_GPU_GetFullName", StrToWstr(name, CP_ACP).c_str()); + formatter.AddFieldString(L"NvAPI_GPU_GetFullName", StrToWstr(name, CP_ACP).c_str()); NvU32 DeviceId = 0, SubSystemId = 0, RevisionId = 0, ExtDeviceId = 0; if(NvAPI_GPU_GetPCIIdentifiers(gpu, &DeviceId, &SubSystemId, &RevisionId, &ExtDeviceId) == NVAPI_OK) { - Print_hex32(L"NvAPI_GPU_GetPCIIdentifiers - pDeviceID", DeviceId); - PrintSubsystemId(L"NvAPI_GPU_GetPCIIdentifiers - pSubSystemId", SubSystemId); - Print_hex32(L"NvAPI_GPU_GetPCIIdentifiers - pRevisionId", RevisionId); - Print_hex32(L"NvAPI_GPU_GetPCIIdentifiers - pExtDeviceId", ExtDeviceId); + formatter.AddFieldHex32(L"NvAPI_GPU_GetPCIIdentifiers - pDeviceID", DeviceId); + formatter.AddFieldSubsystemId(L"NvAPI_GPU_GetPCIIdentifiers - pSubSystemId", SubSystemId); + formatter.AddFieldHex32(L"NvAPI_GPU_GetPCIIdentifiers - pRevisionId", RevisionId); + formatter.AddFieldHex32(L"NvAPI_GPU_GetPCIIdentifiers - pExtDeviceId", ExtDeviceId); } NV_GPU_TYPE gpuType = {}; if(NvAPI_GPU_GetGPUType(gpu, &gpuType) == NVAPI_OK) - PrintEnum(L"NvAPI_GPU_GetGPUType", gpuType, Enum_NV_GPU_TYPE); - + formatter.AddFieldEnum(L"NvAPI_GPU_GetGPUType", gpuType, Enum_NV_GPU_TYPE); + NV_GPU_BUS_TYPE busType = {}; if(NvAPI_GPU_GetBusType(gpu, &busType) == NVAPI_OK) - PrintEnum(L"NvAPI_GPU_GetBusType", busType, Enum_NV_GPU_BUS_TYPE); + formatter.AddFieldEnum(L"NvAPI_GPU_GetBusType", busType, Enum_NV_GPU_BUS_TYPE); NvU32 biosRevision = 0; if(NvAPI_GPU_GetVbiosRevision(gpu, &biosRevision) == NVAPI_OK) - Print_uint32(L"NvAPI_GPU_GetVbiosRevision", biosRevision); + formatter.AddFieldUint32(L"NvAPI_GPU_GetVbiosRevision", biosRevision); NvU32 biosOemRevision = 0; if(NvAPI_GPU_GetVbiosOEMRevision(gpu, &biosOemRevision) == NVAPI_OK) - Print_uint32(L"NvAPI_GPU_GetVbiosOEMRevision", biosOemRevision); + formatter.AddFieldUint32(L"NvAPI_GPU_GetVbiosOEMRevision", biosOemRevision); NvAPI_ShortString biosVersionString = {}; if(NvAPI_GPU_GetVbiosVersionString(gpu, biosVersionString) == NVAPI_OK) - Print_string(L"NvAPI_GPU_GetVbiosVersionString", StrToWstr(biosVersionString, CP_ACP).c_str()); + formatter.AddFieldString(L"NvAPI_GPU_GetVbiosVersionString", StrToWstr(biosVersionString, CP_ACP).c_str()); NvU32 physicalFrameBufferSize = 0; if(NvAPI_GPU_GetPhysicalFrameBufferSize(gpu, &physicalFrameBufferSize) == NVAPI_OK) - Print_sizeKilobytes(L"NvAPI_GPU_GetPhysicalFrameBufferSize", physicalFrameBufferSize); + formatter.AddFieldSizeKilobytes(L"NvAPI_GPU_GetPhysicalFrameBufferSize", physicalFrameBufferSize); NvU32 virtualFrameBufferSize = 0; if(NvAPI_GPU_GetVirtualFrameBufferSize(gpu, &virtualFrameBufferSize) == NVAPI_OK) - Print_sizeKilobytes(L"NvAPI_GPU_GetVirtualFrameBufferSize", virtualFrameBufferSize); + formatter.AddFieldSizeKilobytes(L"NvAPI_GPU_GetVirtualFrameBufferSize", virtualFrameBufferSize); NV_GPU_ARCH_INFO archInfo = {NV_GPU_ARCH_INFO_VER}; if(NvAPI_GPU_GetArchInfo(gpu, &archInfo) == NVAPI_OK) { - PrintEnum(L"NvAPI_GPU_GetArchInfo - NV_GPU_ARCH_INFO::architecture_id", archInfo.architecture_id, Enum_NV_GPU_ARCHITECTURE_ID); - PrintNvImplementationId(L"NvAPI_GPU_GetArchInfo - NV_GPU_ARCH_INFO::implementation_id", - (uint32_t)archInfo.architecture_id, - (uint32_t)archInfo.implementation_id); - PrintEnum(L"NvAPI_GPU_GetArchInfo - NV_GPU_ARCH_INFO::revision_id", archInfo.revision_id, Enum_NV_GPU_CHIP_REVISION); + formatter.AddFieldEnum(L"NvAPI_GPU_GetArchInfo - NV_GPU_ARCH_INFO::architecture_id", archInfo.architecture_id, Enum_NV_GPU_ARCHITECTURE_ID); + formatter.AddFieldNvidiaImplementationID(L"NvAPI_GPU_GetArchInfo - NV_GPU_ARCH_INFO::implementation_id", (uint32_t)archInfo.architecture_id, (uint32_t)archInfo.implementation_id, Enum_NV_ARCH_plus_IMPLEMENTATION_ID); + formatter.AddFieldEnum(L"NvAPI_GPU_GetArchInfo - NV_GPU_ARCH_INFO::revision_id", archInfo.revision_id, Enum_NV_GPU_CHIP_REVISION); } NV_GPU_VR_READY vrReady = {NV_GPU_VR_READY_VER}; if(NvAPI_GPU_GetVRReadyData(gpu, &vrReady) == NVAPI_OK) - Print_BOOL(L"NvAPI_GPU_GetVRReadyData - NV_GPU_VR_READY::isVRReady", vrReady.isVRReady != 0); + formatter.AddFieldBool(L"NvAPI_GPU_GetVRReadyData - NV_GPU_VR_READY::isVRReady", vrReady.isVRReady != 0); NV_GPU_QUERY_ILLUMINATION_SUPPORT_PARM queryIlluminationSupportParm = { .version = NV_GPU_QUERY_ILLUMINATION_SUPPORT_PARM_VER, @@ -897,7 +859,7 @@ void NvAPI_Inititalize_RAII::PrintPhysicalGpuData(const LUID& adapterLuid) queryIlluminationSupportParm.Attribute = (NV_GPU_ILLUMINATION_ATTRIB)ei->m_Value; if(NvAPI_GPU_QueryIlluminationSupport(&queryIlluminationSupportParm) == NVAPI_OK) { - Print_BOOL(std::format(L"NvAPI_GPU_QueryIlluminationSupport({})", ei->m_Name).c_str(), + formatter.AddFieldBool(std::format(L"NvAPI_GPU_QueryIlluminationSupport({})", ei->m_Name).c_str(), queryIlluminationSupportParm.bSupported != 0); } } @@ -905,56 +867,56 @@ void NvAPI_Inititalize_RAII::PrintPhysicalGpuData(const LUID& adapterLuid) for(const EnumItem* ei = Enum_NV_GPU_WORKSTATION_FEATURE_TYPE; ei->m_Name != nullptr; ++ei) { NvAPI_Status status = NvAPI_GPU_QueryWorkstationFeatureSupport(gpu, (NV_GPU_WORKSTATION_FEATURE_TYPE)ei->m_Value); - PrintEnum(std::format(L"NvAPI_GPU_QueryWorkstationFeatureSupport({})", ei->m_Name).c_str(), - status, Enum_NvAPI_Status, true); + formatter.AddFieldEnumSigned(std::format(L"NvAPI_GPU_QueryWorkstationFeatureSupport({})", ei->m_Name).c_str(), + status, Enum_NvAPI_Status); } { NV_GPU_MEMORY_INFO_EX memInfo = {NV_GPU_MEMORY_INFO_EX_VER}; if(NvAPI_GPU_GetMemoryInfoEx(gpu, &memInfo) == NVAPI_OK) { - Print_size(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::dedicatedVideoMemory", memInfo.dedicatedVideoMemory); - Print_size(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::availableDedicatedVideoMemory", memInfo.availableDedicatedVideoMemory); - Print_size(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::systemVideoMemory", memInfo.systemVideoMemory); - Print_size(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::sharedSystemMemory", memInfo.sharedSystemMemory); - Print_size(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::curAvailableDedicatedVideoMemory", memInfo.curAvailableDedicatedVideoMemory); - Print_size(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::dedicatedVideoMemoryEvictionsSize", memInfo.dedicatedVideoMemoryEvictionsSize); - Print_uint64(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::dedicatedVideoMemoryEvictionCount", memInfo.dedicatedVideoMemoryEvictionCount); - Print_size(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::dedicatedVideoMemoryPromotionsSize", memInfo.dedicatedVideoMemoryPromotionsSize); - Print_uint64(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::dedicatedVideoMemoryPromotionCount", memInfo.dedicatedVideoMemoryPromotionCount); + formatter.AddFieldSize(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::dedicatedVideoMemory", memInfo.dedicatedVideoMemory); + formatter.AddFieldSize(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::availableDedicatedVideoMemory", memInfo.availableDedicatedVideoMemory); + formatter.AddFieldSize(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::systemVideoMemory", memInfo.systemVideoMemory); + formatter.AddFieldSize(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::sharedSystemMemory", memInfo.sharedSystemMemory); + formatter.AddFieldSize(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::curAvailableDedicatedVideoMemory", memInfo.curAvailableDedicatedVideoMemory); + formatter.AddFieldSize(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::dedicatedVideoMemoryEvictionsSize", memInfo.dedicatedVideoMemoryEvictionsSize); + formatter.AddFieldUint64(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::dedicatedVideoMemoryEvictionCount", memInfo.dedicatedVideoMemoryEvictionCount); + formatter.AddFieldSize(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::dedicatedVideoMemoryPromotionsSize", memInfo.dedicatedVideoMemoryPromotionsSize); + formatter.AddFieldUint64(L"NvAPI_GPU_GetMemoryInfoEx - NV_GPU_MEMORY_INFO_EX::dedicatedVideoMemoryPromotionCount", memInfo.dedicatedVideoMemoryPromotionCount); } } NvU32 shaderSubPipeCount = 0; if(NvAPI_GPU_GetShaderSubPipeCount(gpu, &shaderSubPipeCount) == NVAPI_OK) - Print_uint32(L"NvAPI_GPU_GetShaderSubPipeCount", shaderSubPipeCount); + formatter.AddFieldUint32(L"NvAPI_GPU_GetShaderSubPipeCount", shaderSubPipeCount); NvU32 gpuCoreCount = 0; if(NvAPI_GPU_GetGpuCoreCount(gpu, &gpuCoreCount) == NVAPI_OK) - Print_uint32(L"NvAPI_GPU_GetGpuCoreCount", gpuCoreCount); + formatter.AddFieldUint32(L"NvAPI_GPU_GetGpuCoreCount", gpuCoreCount); NV_GPU_ECC_STATUS_INFO GPUECCStatusInfo = {NV_GPU_ECC_STATUS_INFO_VER}; if(NvAPI_GPU_GetECCStatusInfo(gpu, &GPUECCStatusInfo) == NVAPI_OK) { - Print_BOOL(L"NvAPI_GPU_GetECCStatusInfo - NV_GPU_ECC_STATUS_INFO::isSupported", GPUECCStatusInfo.isSupported != 0); - PrintEnum(L"NvAPI_GPU_GetECCStatusInfo - NV_GPU_ECC_STATUS_INFO::configurationOptions", GPUECCStatusInfo.configurationOptions, + formatter.AddFieldBool(L"NvAPI_GPU_GetECCStatusInfo - NV_GPU_ECC_STATUS_INFO::isSupported", GPUECCStatusInfo.isSupported != 0); + formatter.AddFieldEnum(L"NvAPI_GPU_GetECCStatusInfo - NV_GPU_ECC_STATUS_INFO::configurationOptions", GPUECCStatusInfo.configurationOptions, Enum_NV_ECC_CONFIGURATION); - Print_BOOL(L"NvAPI_GPU_GetECCStatusInfo - NV_GPU_ECC_STATUS_INFO::isEnabled", GPUECCStatusInfo.isEnabled != 0); + formatter.AddFieldBool(L"NvAPI_GPU_GetECCStatusInfo - NV_GPU_ECC_STATUS_INFO::isEnabled", GPUECCStatusInfo.isEnabled != 0); } { NvU32 busWidth = 0; if(NvAPI_GPU_GetRamBusWidth(gpu, &busWidth) == NVAPI_OK) - Print_uint32(L"NvAPI_GPU_GetRamBusWidth", busWidth); + formatter.AddFieldUint32(L"NvAPI_GPU_GetRamBusWidth", busWidth); } { NV_GPU_INFO gpuInfo = {NV_GPU_INFO_VER}; if(NvAPI_GPU_GetGPUInfo(gpu, &gpuInfo) == NVAPI_OK) { - Print_BOOL(L"NvAPI_GPU_GetGPUInfo - NV_GPU_INFO::bIsExternalGpu", gpuInfo.bIsExternalGpu); - Print_uint32(L"NvAPI_GPU_GetGPUInfo - NV_GPU_INFO::rayTracingCores", gpuInfo.rayTracingCores); - Print_uint32(L"NvAPI_GPU_GetGPUInfo - NV_GPU_INFO::tensorCores", gpuInfo.tensorCores); + formatter.AddFieldBool(L"NvAPI_GPU_GetGPUInfo - NV_GPU_INFO::bIsExternalGpu", gpuInfo.bIsExternalGpu); + formatter.AddFieldUint32(L"NvAPI_GPU_GetGPUInfo - NV_GPU_INFO::rayTracingCores", gpuInfo.rayTracingCores); + formatter.AddFieldUint32(L"NvAPI_GPU_GetGPUInfo - NV_GPU_INFO::tensorCores", gpuInfo.tensorCores); } } @@ -962,7 +924,7 @@ void NvAPI_Inititalize_RAII::PrintPhysicalGpuData(const LUID& adapterLuid) NV_GPU_GSP_INFO gspInfo = {NV_GPU_GSP_INFO_VER}; if(NvAPI_GPU_GetGspFeatures(gpu, &gspInfo) == NVAPI_OK) { - PrintHexBytes(L"NvAPI_GPU_GetGspFeatures - NV_GPU_GSP_INFO::firmwareVersion", + formatter.AddFieldHexBytes(L"NvAPI_GPU_GetGspFeatures - NV_GPU_GSP_INFO::firmwareVersion", gspInfo.firmwareVersion, NVAPI_GPU_MAX_BUILD_VERSION_LENGTH); } } diff --git a/Src/Printer.cpp b/Src/Printer.cpp new file mode 100644 index 0000000..ce6a35f --- /dev/null +++ b/Src/Printer.cpp @@ -0,0 +1,122 @@ +/* +This file is part of D3d12info project: +https://github.com/sawickiap/D3d12info + +Copyright (c) 2018-2025 Adam Sawicki, https://asawicki.info +License: MIT + +For more information, see files README.md, LICENSE.txt. +*/ +#include "Printer.hpp" + +bool Printer::m_IsInitialized = false; +bool Printer::m_WritingToFile = false; +std::wostream* Printer::m_Output = nullptr; + +bool Printer::Initialize(bool writeToFile, std::wstring_view name) +{ + assert(!m_IsInitialized); + if (writeToFile) + { + m_Output = new std::wofstream(name.data(), std::ios_base::out); + if (!m_Output->good()) + { + delete m_Output; + m_Output = nullptr; + return false; + } + } + else + { + m_Output = &std::wcout; + } + m_IsInitialized = true; + return true; +} + +void Printer::Release() +{ + assert(m_IsInitialized); + if (m_WritingToFile) + { + delete m_Output; + } + m_Output = nullptr; + m_WritingToFile = false; + m_IsInitialized = false; +} + +void Printer::PrintNewLine() +{ + assert(m_IsInitialized); + *m_Output << std::endl; +} + +void Printer::PrintString(const std::string& line) +{ + assert(m_IsInitialized); + + *m_Output << line.c_str(); +} + +void Printer::PrintString(std::wstring_view line) +{ + assert(m_IsInitialized); + + *m_Output << line; +} + +void Printer::PrintFormat(std::string_view format, std::format_args&& args) +{ + std::string formatted = std::vformat(format, args); + PrintString(formatted); +} + +void Printer::PrintFormat(std::wstring_view format, std::wformat_args&& args) +{ + std::wstring formatted = std::vformat(format, args); + PrintString(formatted); +} + +PrinterScope::PrinterScope(bool writeToFile, std::wstring_view name) +{ + if (!Printer::Initialize(writeToFile, name)) + { + if (writeToFile) + { + std::string narrowName(name.begin(), name.end()); + throw std::runtime_error(std::format("Could not open {} for writing.", narrowName)); + } + else + { + throw std::runtime_error("Unexpected error during output initialization."); + } + } +} + +PrinterScope::~PrinterScope() +{ + Printer::Release(); +} + +void ErrorPrinter::PrintFormat(std::string_view format, std::format_args&& args) +{ + std::string formatted = std::vformat(format, args); + PrintString(formatted); +} + +void ErrorPrinter::PrintFormat(std::wstring_view format, std::wformat_args&& args) +{ + std::wstring formatted = std::vformat(format, args); + PrintString(formatted); +} + +void ErrorPrinter::PrintString(const std::string& line) +{ + std::cerr << line; +} + +void ErrorPrinter::PrintString(std::wstring_view line) +{ + std::wcerr << line; +} \ No newline at end of file diff --git a/Src/Printer.hpp b/Src/Printer.hpp new file mode 100644 index 0000000..a55df70 --- /dev/null +++ b/Src/Printer.hpp @@ -0,0 +1,50 @@ +/* +This file is part of D3d12info project: +https://github.com/sawickiap/D3d12info + +Copyright (c) 2018-2025 Adam Sawicki, https://asawicki.info +License: MIT + +For more information, see files README.md, LICENSE.txt. +*/ + +#pragma once + +#include + +class Printer +{ +public: + static bool Initialize(bool writeToFile, std::wstring_view name); + static void Release(); + + static void PrintNewLine(); + + static void PrintString(const std::string& line); + static void PrintString(std::wstring_view line); + + static void PrintFormat(std::string_view format, std::format_args&& args); + static void PrintFormat(std::wstring_view format, std::wformat_args&& args); + +private: + static bool m_IsInitialized; + static bool m_WritingToFile; + static std::wostream* m_Output; +}; + +class PrinterScope +{ +public: + PrinterScope(bool writeToFile, std::wstring_view name); + ~PrinterScope(); +}; + +class ErrorPrinter +{ +public: + static void PrintString(const std::string& line); + static void PrintString(std::wstring_view line); + + static void PrintFormat(std::string_view format, std::format_args&& args); + static void PrintFormat(std::wstring_view format, std::wformat_args&& args); +}; diff --git a/Src/Printing.cpp b/Src/Printing.cpp deleted file mode 100644 index 8f8dc48..0000000 --- a/Src/Printing.cpp +++ /dev/null @@ -1,380 +0,0 @@ -/* -This file is part of D3d12info project: -https://github.com/sawickiap/D3d12info - -Copyright (c) 2018-2024 Adam Sawicki, https://asawicki.info -License: MIT - -For more information, see files README.md, LICENSE.txt. -*/ -#include "Printing.hpp" -#include "Json.hpp" -#include "Utils.hpp" -#include "Enums.hpp" - -//////////////////////////////////////////////////////////////////////////////// -// PRIVATE - -//////////////////////////////////////////////////////////////////////////////// -// PUBLIC - -bool g_UseJson = false; -uint32_t g_Indent = 0; - -void PrintEmptyLine() -{ - assert(!g_UseJson); - wprintf(L"\n"); -} - -void PrintHeader(const wchar_t* s, uint8_t headerLevel) -{ - assert(!g_UseJson); - assert(headerLevel < 2); - - const size_t len = wcslen(s); - assert(len > 0 && len < 80); - PrintIndent(); - wprintf(L"%s:\n", s); - static const wchar_t* underline1 = L"================================================================================"; - static const wchar_t* underline2 = L"--------------------------------------------------------------------------------"; - const wchar_t* const currUnderline = headerLevel == 0 ? underline1 : underline2; - PrintIndent(); - wprintf(L"%s\n", currUnderline + 80 - len - 1); -} - -void PrintIndent() -{ - assert(!g_UseJson); - if(g_Indent == 0) - return; - static const wchar_t* maxIndentStr = L" "; - const uint32_t offset = 64u - (g_Indent * 4u); - assert(offset < wcslen(maxIndentStr)); - wprintf(L"%s", maxIndentStr + offset); -} - -void PrintName(const wchar_t* name) -{ - assert(!g_UseJson); - wprintf(L"%s", name); -} - -void Print_string(const wchar_t* name, const wchar_t* value) -{ - if(g_UseJson) - { - Json::WriteNameAndString(name, value); - } - else - { - PrintIndent(); - PrintName(name); - wprintf(L" = %s\n", value); - } -} - -void PrintStructBegin(const wchar_t* structName) -{ - if(g_UseJson) - { - Json::WriteString(structName); - Json::BeginObject(); - } - else - { - PrintHeader(structName, 1); - ++g_Indent; - } -} - -void PrintStructEnd() -{ - if(g_UseJson) - { - Json::EndObject(); - } - else - { - --g_Indent; - PrintEmptyLine(); - } -} - -void Print_BOOL(const wchar_t* name, BOOL value) -{ - if(g_UseJson) - { - Json::WriteNameAndBool(name, value != FALSE); - } - else - { - PrintIndent(); - PrintName(name); - wprintf(L" = %s\n", value ? L"TRUE" : L"FALSE"); - } -} - -void Print_uint32(const wchar_t* name, uint32_t value, const wchar_t* unit) -{ - if(g_UseJson) - { - Json::WriteNameAndNumber(name, value); - } - else - { - PrintIndent(); - PrintName(name); - if(unit && *unit) - wprintf(L" = %u %s\n", value, unit); - else - wprintf(L" = %u\n", value); - } -} - -void Print_uint64(const wchar_t* name, uint64_t value, const wchar_t* unit) -{ - if(g_UseJson) - { - Json::WriteNameAndNumber(name, value); - } - else - { - PrintIndent(); - PrintName(name); - if(unit && *unit) - wprintf(L" = %llu %s\n", value, unit); - else - wprintf(L" = %llu\n", value); - } -} - -void Print_size(const wchar_t* name, uint64_t value) -{ - if(g_UseJson) - { - Json::WriteNameAndNumber(name, value); - } - else - { - PrintIndent(); - PrintName(name); - if(value == 0) - wprintf(L" = 0\n"); - else if(value < 1024) - wprintf(L" = %zu (0x%llx)\n", value, value); - else - wprintf(L" = %zu (0x%llx) (%s)\n", value, value, SizeToStr(value).c_str()); - } -} - -void Print_sizeKilobytes(const wchar_t* name, uint64_t value) -{ - if(g_UseJson) - { - Json::WriteNameAndNumber(name, value); - } - else - { - PrintIndent(); - PrintName(name); - if(value == 0) - wprintf(L" = 0 KB\n"); - else if(value < 1024) - wprintf(L" = %zu (0x%llx) KB\n", value, value); - else - wprintf(L" = %zu (0x%llx) KB (%s)\n", value, value, SizeToStr(value * 1024llu).c_str()); - } -} - -void Print_hex32(const wchar_t* name, uint32_t value) -{ - if(g_UseJson) - { - Json::WriteNameAndNumber(name, value); - } - else - { - PrintIndent(); - PrintName(name); - wprintf(L" = 0x%X\n", value); - } -} - -void Print_int32(const wchar_t* name, int32_t value, const wchar_t* unit) -{ - if(g_UseJson) - { - Json::WriteNameAndNumber(name, value); - } - else - { - PrintIndent(); - PrintName(name); - if(unit && *unit) - wprintf(L" = %i %s\n", value, unit); - else - wprintf(L" = %i\n", value); - } -} - -void Print_float(const wchar_t* name, float value, const wchar_t* unit) -{ - if(g_UseJson) - { - Json::WriteNameAndNumber(name, value); - } - else - { - PrintIndent(); - PrintName(name); - if(unit && *unit) - wprintf(L" = %g %s\n", value, unit); - else - wprintf(L" = %g\n", value); - } -} - -void PrintEnum(const wchar_t* name, uint32_t value, const EnumItem* enumItems, bool isSigned) -{ - if(g_UseJson) - { - Json::WriteString(name); - if(isSigned) - Json::WriteNumber((int32_t)value); - else - Json::WriteNumber(value); - } - else - { - PrintIndent(); - PrintName(name); - const wchar_t* enumItemName = FindEnumItemName(value, enumItems); - if(isSigned) - { - if(enumItemName != nullptr) - wprintf(L" = %s (%d)\n", enumItemName, value); - else - wprintf(L" = %d\n", value); - } - else - { - if(enumItemName != nullptr) - wprintf(L" = %s (0x%X)\n", enumItemName, value); - else - wprintf(L" = 0x%X\n", value); - } - } -} - -void PrintFlags(const wchar_t* name, uint32_t value, const EnumItem* enumItems) -{ - if(g_UseJson) - { - Json::WriteNameAndNumber(name, value); - } - else - { - PrintIndent(); - PrintName(name); - wprintf(L" = 0x%X\n", value); - - ++g_Indent; - size_t zeroFlagIndex = SIZE_MAX; - for(size_t i = 0; enumItems[i].m_Name != nullptr; ++i) - { - if(enumItems[i].m_Value == 0) - { - zeroFlagIndex = i; - } - else - { - if((value & enumItems[i].m_Value) != 0) - { - PrintIndent(); - wprintf(L"%s\n", enumItems[i].m_Name); - } - } - } - if(value == 0 && zeroFlagIndex != SIZE_MAX) - { - PrintIndent(); - wprintf(L"%s\n", enumItems[zeroFlagIndex].m_Name); - } - --g_Indent; - } -} - -void PrintHexBytes(const wchar_t* name, const void* data, size_t byteCount) -{ - wstring valStr; - for(size_t i = 0; i < byteCount; ++i) - valStr += std::format(L"{:02X}", *((const uint8_t*)data + i)); - Print_string(name, valStr.c_str()); -} - -void PrintFormat(const wchar_t* name, const wchar_t* format, ...) { - va_list argList; - va_start(argList, format); - wchar_t buffer[256]; - _vsnwprintf_s(buffer, ARRAYSIZE(buffer), format, argList); - va_end(argList); - Print_string(name, buffer); -} - -static bool DecodeAcpiIdChars(wchar_t out[4], uint32_t value) -{ - for(uint32_t i = 0; i < 4; ++i) - { - const uint8_t charValue = (uint8_t)(value >> (i * 8)); - if(charValue < 32 || charValue > 126) - return false; - out[i] = (wchar_t)charValue; - } - return true; -} - -void PrintVendorId(const wchar_t* name, uint32_t value) -{ - wchar_t chars[5] = {}; - if(!g_UseJson && value <= 0xFFFF && DecodeAcpiIdChars(chars, value)) - { - PrintIndent(); - PrintName(name); - const wchar_t* const enumItemName = FindEnumItemName(value, Enum_VendorId); - if(enumItemName != nullptr) - wprintf(L" = %s \"%s\" (0x%X)\n", enumItemName, chars, value); - else - wprintf(L" = \"%s\" 0x%X\n", chars, value); - } - else - { - PrintEnum(name, value, Enum_VendorId); - } -} - -void PrintSubsystemId(const wchar_t* name, uint32_t value) -{ - if(g_UseJson) - PrintEnum(name, value, Enum_SubsystemVendorId); - else - { - PrintIndent(); - PrintName(name); - const wchar_t* enumItemName = FindEnumItemName(value & 0xFFFF, Enum_SubsystemVendorId); - if(enumItemName != nullptr) - wprintf(L" = %s (0x%X)\n", enumItemName, value); - else - wprintf(L" = 0x%X\n", value); - } -} - -ScopedStructRegion::ScopedStructRegion(const wchar_t* name) -{ - PrintStructBegin(name); -} - -ScopedStructRegion::~ScopedStructRegion() -{ - PrintStructEnd(); -} diff --git a/Src/Printing.hpp b/Src/Printing.hpp deleted file mode 100644 index 38a8caa..0000000 --- a/Src/Printing.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* -This file is part of D3d12info project: -https://github.com/sawickiap/D3d12info - -Copyright (c) 2018-2024 Adam Sawicki, https://asawicki.info -License: MIT - -For more information, see files README.md, LICENSE.txt. -*/ -#pragma once - -struct EnumItem; - -extern bool g_UseJson; -extern uint32_t g_Indent; - -void PrintEmptyLine(); -void PrintHeader(const wchar_t* s, uint8_t headerLevel); -void PrintIndent(); -void PrintName(const wchar_t* name); -void Print_string(const wchar_t* name, const wchar_t* value); -void PrintStructBegin(const wchar_t* structName); -void PrintStructEnd(); -void Print_BOOL(const wchar_t* name, BOOL value); -void Print_uint32(const wchar_t* name, uint32_t value, const wchar_t* unit = nullptr); -void Print_uint64(const wchar_t* name, uint64_t value, const wchar_t* unit = nullptr); -void Print_size(const wchar_t* name, uint64_t value); -void Print_sizeKilobytes(const wchar_t* name, uint64_t value); -void Print_hex32(const wchar_t* name, uint32_t value); -void Print_int32(const wchar_t* name, int32_t value, const wchar_t* unit = nullptr); -void Print_float(const wchar_t* name, float value, const wchar_t* unit = nullptr); -void PrintEnum(const wchar_t* name, uint32_t value, const EnumItem* enumItems, bool isSigned = false); -void PrintFlags(const wchar_t* name, uint32_t value, const EnumItem* enumItems); -void PrintHexBytes(const wchar_t* name, const void* data, size_t byteCount); -void PrintFormat(const wchar_t* name, const wchar_t* format, ...); -void PrintVendorId(const wchar_t* name, uint32_t value); -void PrintSubsystemId(const wchar_t* name, uint32_t value); - -struct ScopedStructRegion -{ -public: - ScopedStructRegion(const wchar_t* name); - ~ScopedStructRegion(); -}; diff --git a/Src/ReportFormatter/JSONReportFormatter.cpp b/Src/ReportFormatter/JSONReportFormatter.cpp new file mode 100644 index 0000000..766747e --- /dev/null +++ b/Src/ReportFormatter/JSONReportFormatter.cpp @@ -0,0 +1,255 @@ +/* +This file is part of D3d12info project: +https://github.com/sawickiap/D3d12info + +Copyright (c) 2018-2025 Adam Sawicki, https://asawicki.info +License: MIT + +For more information, see files README.md, LICENSE.txt. +*/ +#include "JSONReportFormatter.hpp" + +#include "Printer.hpp" + +JSONReportFormatter::JSONReportFormatter(FLAGS flags) + : m_PrettyPrint((flags & FLAGS::FLAG_JSON_PRETTY_PRINT) != FLAGS::FLAG_NONE) +{ + Printer::PrintString(L"{"); + m_ScopeStack.push({ .ElementCount = 0, .Type = ScopeType::Object }); +} + +JSONReportFormatter::~JSONReportFormatter() +{ + PopScope(); + PrintNewLine(); + assert(m_ScopeStack.empty()); +} + +void JSONReportFormatter::PushObject(std::wstring_view name) +{ + assert(!name.empty()); + + PushNewElement(); + + Printer::PrintFormat(m_PrettyPrint ? L"\"{}\": {{" : L"\"{}\":{{", std::make_wformat_args(name)); + + m_ScopeStack.push({ .ElementCount = 0, .Type = ScopeType::Object }); +} + +void JSONReportFormatter::PushArray(std::wstring_view name, ARRAY_SUFFIX suffix /* = ArraySuffix::SquareBrackets */) +{ + assert(!name.empty()); + + PushNewElement(); + + Printer::PrintFormat(m_PrettyPrint ? L"\"{}\": [" : L"\"{}\":[", std::make_wformat_args(name)); + + m_ScopeStack.push({ .ElementCount = 0, .Type = ScopeType::Array }); +} + +void JSONReportFormatter::PushArrayItem() +{ + assert(!m_ScopeStack.empty()); + assert(m_ScopeStack.top().Type == ScopeType::Array); + + PushNewElement(); + + Printer::PrintString(L"{"); + + m_ScopeStack.push({ .ElementCount = 0, .Type = ScopeType::Object }); +} + +void JSONReportFormatter::PopScope() +{ + assert(!m_ScopeStack.empty()); + + ScopeInfo scope = m_ScopeStack.top(); + m_ScopeStack.pop(); + + if (scope.ElementCount != 0) + { + PrintNewLine(); + PrintIndent(); + } + + Printer::PrintString(scope.Type == ScopeType::Object ? L"}" : L"]"); +} + +void JSONReportFormatter::AddFieldString(std::wstring_view name, std::wstring_view value) +{ + assert(!name.empty()); + assert(!value.empty()); + PushNewElement(); + Printer::PrintFormat(m_PrettyPrint ? L"\"{}\": \"{}\"" : L"\"{}\":\"{}\"", std::make_wformat_args(name, value)); +} + +void JSONReportFormatter::AddFieldStringArray(std::wstring_view name, const std::vector& value) +{ + assert(!name.empty()); + PushNewElement(); + Printer::PrintFormat(m_PrettyPrint ? L"\"{}\": [" : L"\"{}\":[", std::make_wformat_args(name)); + for (size_t i = 0; i < value.size(); ++i) + { + if (i > 0) + { + Printer::PrintString(L","); + } + PrintNewLine(); + PrintIndent(1); + Printer::PrintFormat(L"\"{}\"", std::make_wformat_args(value[i])); + } + PrintNewLine(); + PrintIndent(); + Printer::PrintString(L"]"); +} + +void JSONReportFormatter::AddFieldBool(std::wstring_view name, bool value) +{ + assert(!name.empty()); + PushNewElement(); + const wchar_t* boolStr = value ? L"true" : L"false"; + Printer::PrintFormat(m_PrettyPrint ? L"\"{}\": {}" : L"\"{}\":{}", std::make_wformat_args(name, boolStr)); +} + +void JSONReportFormatter::AddFieldUint32(std::wstring_view name, uint32_t value, std::wstring_view unit /* = {}*/) +{ + assert(!name.empty()); + PushNewElement(); + Printer::PrintFormat(m_PrettyPrint ? L"\"{}\": {}" : L"\"{}\":{}", std::make_wformat_args(name, value)); +} + +void JSONReportFormatter::AddFieldUint64(std::wstring_view name, uint64_t value, std::wstring_view unit /* = {}*/) +{ + assert(!name.empty()); + PushNewElement(); + Printer::PrintFormat(m_PrettyPrint ? L"\"{}\": {}" : L"\"{}\":{}", std::make_wformat_args(name, value)); +} + +void JSONReportFormatter::AddFieldSize(std::wstring_view name, uint64_t value) +{ + AddFieldUint64(name, value); +} + +void JSONReportFormatter::AddFieldSizeKilobytes(std::wstring_view name, uint64_t value) +{ + AddFieldUint64(name, value); +} + +void JSONReportFormatter::AddFieldHex32(std::wstring_view name, uint32_t value) +{ + AddFieldUint32(name, value); +} + +void JSONReportFormatter::AddFieldInt32(std::wstring_view name, int32_t value, std::wstring_view unit /* = {}*/) +{ + assert(!name.empty()); + PushNewElement(); + Printer::PrintFormat(m_PrettyPrint ? L"\"{}\": {}" : L"\"{}\":{}", std::make_wformat_args(name, value)); +} + +void JSONReportFormatter::AddFieldFloat(std::wstring_view name, float value, std::wstring_view unit /* = {}*/) +{ + assert(!name.empty()); + PushNewElement(); + Printer::PrintFormat(m_PrettyPrint ? L"\"{}\": {}" : L"\"{}\":{}", std::make_wformat_args(name, value)); +} + +void JSONReportFormatter::AddFieldEnum(std::wstring_view name, uint32_t value, const EnumItem* enumItems) +{ + AddFieldUint32(name, value); +} + +void JSONReportFormatter::AddFieldEnumSigned(std::wstring_view name, int32_t value, const EnumItem* enumItems) +{ + AddFieldInt32(name, value); +} + +void JSONReportFormatter::AddEnumArray(std::wstring_view name, const uint32_t* values, size_t count, const EnumItem* enumItems) +{ + assert(!name.empty()); + PushNewElement(); + Printer::PrintFormat(m_PrettyPrint ? L"\"{}\": [" : L"\"{}\":[", std::make_wformat_args(name)); + for (size_t i = 0; i < count; ++i) + { + if (i > 0) + { + Printer::PrintString(L","); + } + PrintNewLine(); + PrintIndent(1); + Printer::PrintFormat(L"{}", std::make_wformat_args(values[i])); + } + PrintNewLine(); + PrintIndent(); + Printer::PrintString(L"]"); +} + +void JSONReportFormatter::AddFieldFlags(std::wstring_view name, uint32_t value, const EnumItem* enumItems) +{ + AddFieldUint32(name, value); +} + +void JSONReportFormatter::AddFieldHexBytes(std::wstring_view name, const void* data, size_t byteCount) +{ + std::wstring valStr; + for (size_t i = 0; i < byteCount; ++i) + { + valStr += std::format(L"{:02X}", *((const uint8_t*)data + i)); + } + AddFieldString(name, valStr); +} + +void JSONReportFormatter::AddFieldVendorId(std::wstring_view name, uint32_t value) +{ + AddFieldUint32(name, value); +} + +void JSONReportFormatter::AddFieldSubsystemId(std::wstring_view name, uint32_t value) +{ + AddFieldUint32(name, value); +} + +void JSONReportFormatter::AddFieldMicrosoftVersion(std::wstring_view name, uint64_t value) +{ + AddFieldUint64(name, value); +} + +void JSONReportFormatter::AddFieldAMDVersion(std::wstring_view name, uint64_t value) +{ + AddFieldUint64(name, value); +} + +void JSONReportFormatter::AddFieldNvidiaImplementationID(std::wstring_view name, uint32_t architectureId, uint32_t implementationId, const EnumItem* architecturePlusImplementationIDEnum) +{ + AddFieldUint32(name, implementationId); +} + +void JSONReportFormatter::PushNewElement() +{ + if (m_ScopeStack.top().ElementCount > 0) + { + Printer::PrintString(L","); + } + m_ScopeStack.top().ElementCount++; + PrintNewLine(); + PrintIndent(); +} + +void JSONReportFormatter::PrintIndent(size_t additionalIndentation /*= 0*/) +{ + if (!m_PrettyPrint) + { + return; + } + + Printer::PrintString(std::wstring((m_ScopeStack.size() + additionalIndentation) * INDENT_SIZE, INDENT_CHAR)); +} + +void JSONReportFormatter::PrintNewLine() +{ + if (m_PrettyPrint) + { + Printer::PrintNewLine(); + } +} + diff --git a/Src/ReportFormatter/JSONReportFormatter.hpp b/Src/ReportFormatter/JSONReportFormatter.hpp new file mode 100644 index 0000000..a18b890 --- /dev/null +++ b/Src/ReportFormatter/JSONReportFormatter.hpp @@ -0,0 +1,70 @@ +/* +This file is part of D3d12info project: +https://github.com/sawickiap/D3d12info + +Copyright (c) 2018-2025 Adam Sawicki, https://asawicki.info +License: MIT + +For more information, see files README.md, LICENSE.txt. +*/ + +#pragma once + +#include "ReportFormatter.hpp" +#include + +class JSONReportFormatter final : public ReportFormatter +{ +public: + JSONReportFormatter(FLAGS flags); + ~JSONReportFormatter(); + + void PushObject(std::wstring_view name) final; + void PushArray(std::wstring_view name, ARRAY_SUFFIX suffix = ARRAY_SUFFIX_SQUARE_BRACKETS); + void PushArrayItem() final; + void PopScope() final; + + void AddFieldString(std::wstring_view name, std::wstring_view value) final; + void AddFieldStringArray(std::wstring_view name, const std::vector& value) final; + void AddFieldBool(std::wstring_view name, bool value); + void AddFieldUint32(std::wstring_view name, uint32_t value, std::wstring_view unit = {}) final; + void AddFieldUint64(std::wstring_view name, uint64_t value, std::wstring_view unit = {}) final; + void AddFieldSize(std::wstring_view name, uint64_t value) final; + void AddFieldSizeKilobytes(std::wstring_view name, uint64_t value) final; + void AddFieldHex32(std::wstring_view name, uint32_t value) final; + void AddFieldInt32(std::wstring_view name, int32_t value, std::wstring_view unit = {}) final; + void AddFieldFloat(std::wstring_view name, float value, std::wstring_view unit = {}) final; + void AddFieldEnum(std::wstring_view name, uint32_t value, const EnumItem* enumItems) final; + void AddFieldEnumSigned(std::wstring_view name, int32_t value, const EnumItem* enumItems) final; + void AddEnumArray(std::wstring_view name, const uint32_t* values, size_t count, const EnumItem* enumItems) final; + void AddFieldFlags(std::wstring_view name, uint32_t value, const EnumItem* enumItems) final; + void AddFieldHexBytes(std::wstring_view name, const void* data, size_t byteCount) final; + void AddFieldVendorId(std::wstring_view name, uint32_t value) final; + void AddFieldSubsystemId(std::wstring_view name, uint32_t value) final; + void AddFieldMicrosoftVersion(std::wstring_view name, uint64_t value) final; + void AddFieldAMDVersion(std::wstring_view name, uint64_t value) final; + void AddFieldNvidiaImplementationID(std::wstring_view name, uint32_t architectureId, uint32_t implementationId, const EnumItem* architecturePlusImplementationIDEnum) final; + +private: + static constexpr size_t INDENT_SIZE = 4; + static constexpr wchar_t INDENT_CHAR = L' '; + + enum class ScopeType + { + Object, + Array + }; + + struct ScopeInfo + { + size_t ElementCount; + ScopeType Type; + }; + + bool m_PrettyPrint; + std::stack m_ScopeStack = {}; + + void PushNewElement(); + void PrintIndent(size_t additionalIndentation = 0); + void PrintNewLine(); +}; diff --git a/Src/ReportFormatter/ReportFormatter.cpp b/Src/ReportFormatter/ReportFormatter.cpp new file mode 100644 index 0000000..4444af8 --- /dev/null +++ b/Src/ReportFormatter/ReportFormatter.cpp @@ -0,0 +1,181 @@ +/* +This file is part of D3d12info project: +https://github.com/sawickiap/D3d12info + +Copyright (c) 2018-2025 Adam Sawicki, https://asawicki.info +License: MIT + +For more information, see files README.md, LICENSE.txt. +*/ +#include "ReportFormatter.hpp" + +#include "JSONReportFormatter.hpp" +#include "TextReportFormatter.hpp" + +static ReportFormatter* s_Instance = nullptr; +static ReportFormatter::FLAGS s_Flags = ReportFormatter::FLAGS::FLAG_NONE; + +void ReportFormatter::CreateInstance(FLAGS flags) +{ + assert(s_Instance == nullptr); + if ((flags & FLAGS::FLAG_JSON) != FLAGS::FLAG_NONE) + { + s_Instance = new JSONReportFormatter(flags); + } + else + { + s_Instance = new TextReportFormatter(flags); + } + s_Flags = flags; +} + +void ReportFormatter::DestroyInstance() +{ + assert(s_Instance != nullptr); + delete s_Instance; + s_Instance = nullptr; +} + +ReportFormatter& ReportFormatter::GetInstance() +{ + assert(s_Instance != nullptr); + return *s_Instance; +} + +ReportFormatter::FLAGS ReportFormatter::GetFlags() +{ + assert(s_Instance != nullptr); + return s_Flags; +} + +ReportFormatter::FLAGS& operator|=(ReportFormatter::FLAGS& lhs, ReportFormatter::FLAGS rhs) +{ + lhs = static_cast(static_cast(lhs) | static_cast(rhs)); + return lhs; +} + +ReportScopeObjectConditional::ReportScopeObjectConditional(std::wstring_view name) + : m_Name(name) +{ +} + +ReportScopeObjectConditional::ReportScopeObjectConditional(bool enable, std::wstring_view name) + : ReportScopeObjectConditional(name) +{ + if (enable) + { + Enable(); + } +} + +ReportScopeObjectConditional::~ReportScopeObjectConditional() +{ + if (m_Enabled) + { + ReportFormatter::GetInstance().PopScope(); + } +} + +void ReportScopeObjectConditional::Enable() +{ + if (!m_Enabled) + { + ReportFormatter::GetInstance().PushObject(m_Name); + m_Enabled = true; + } +} + +ReportScopeArrayConditional::ReportScopeArrayConditional(std::wstring_view name, ReportFormatter::ARRAY_SUFFIX suffix /*= ReportFormatter::SquareBrackets*/) + : m_Name(name) + , m_Suffix(suffix) +{ +} + +ReportScopeArrayConditional::ReportScopeArrayConditional(bool enable, std::wstring_view name, ReportFormatter::ARRAY_SUFFIX suffix /*= ReportFormatter::SquareBrackets*/) + : ReportScopeArrayConditional(name, suffix) +{ + if (enable) + { + Enable(); + } +} + +ReportScopeArrayConditional::~ReportScopeArrayConditional() +{ + if (m_Enabled) + { + ReportFormatter::GetInstance().PopScope(); + } +} + +void ReportScopeArrayConditional::Enable() +{ + if (!m_Enabled) + { + ReportFormatter::GetInstance().PushArray(m_Name, m_Suffix); + m_Enabled = true; + } +} + +ReportScopeArrayItemConditional::ReportScopeArrayItemConditional() +{ +} + +ReportScopeArrayItemConditional::ReportScopeArrayItemConditional(bool enable) +{ + if (enable) + { + Enable(); + } +} + +ReportScopeArrayItemConditional::~ReportScopeArrayItemConditional() +{ + if (m_Enabled) + { + ReportFormatter::GetInstance().PopScope(); + } +} + +void ReportScopeArrayItemConditional::Enable() +{ + if (!m_Enabled) + { + ReportFormatter::GetInstance().PushArrayItem(); + m_Enabled = true; + } +} + +bool IsTextOutput() +{ + return (ReportFormatter::GetFlags() & ReportFormatter::FLAGS::FLAG_JSON) == ReportFormatter::FLAGS::FLAG_NONE; +} + +bool IsJsonOutput() +{ + return !IsTextOutput(); +} + +std::wstring_view SelectString(std::wstring_view textString, std::wstring_view jsonString) +{ + if (IsJsonOutput()) + { + return jsonString; + } + else + { + return textString; + } +} + +std::string_view SelectString(std::string_view textString, std::string_view jsonString) +{ + if (IsJsonOutput()) + { + return jsonString; + } + else + { + return textString; + } +} diff --git a/Src/ReportFormatter/ReportFormatter.hpp b/Src/ReportFormatter/ReportFormatter.hpp new file mode 100644 index 0000000..ef477e9 --- /dev/null +++ b/Src/ReportFormatter/ReportFormatter.hpp @@ -0,0 +1,172 @@ +/* +This file is part of D3d12info project: +https://github.com/sawickiap/D3d12info + +Copyright (c) 2018-2025 Adam Sawicki, https://asawicki.info +License: MIT + +For more information, see files README.md, LICENSE.txt. +*/ + +#pragma once + +struct EnumItem; + +class ReportFormatter +{ +public: + enum FLAGS : uint32_t + { + FLAG_NONE = 0, + FLAG_JSON = 1 << 0, + FLAG_JSON_PRETTY_PRINT = 1 << 1 + }; + + enum ARRAY_SUFFIX + { + ARRAY_SUFFIX_SQUARE_BRACKETS, + ARRAY_SUFFIX_NONE + }; + + static void CreateInstance(FLAGS flags); + static void DestroyInstance(); + static ReportFormatter& GetInstance(); + static FLAGS GetFlags(); + + virtual ~ReportFormatter() = default; + + virtual void PushObject(std::wstring_view name) = 0; + virtual void PushArray(std::wstring_view name, ARRAY_SUFFIX suffix = ARRAY_SUFFIX_SQUARE_BRACKETS) = 0; + virtual void PushArrayItem() = 0; + virtual void PopScope() = 0; + + // Fields + // Strings + virtual void AddFieldString(std::wstring_view name, std::wstring_view value) = 0; + virtual void AddFieldStringArray(std::wstring_view name, const std::vector& value) = 0; + // Booleans + virtual void AddFieldBool(std::wstring_view name, bool value) = 0; + // Integers + virtual void AddFieldUint32(std::wstring_view name, uint32_t value, std::wstring_view unit = {}) = 0; + virtual void AddFieldUint64(std::wstring_view name, uint64_t value, std::wstring_view unit = {}) = 0; + virtual void AddFieldSize(std::wstring_view name, uint64_t value) = 0; + virtual void AddFieldSizeKilobytes(std::wstring_view name, uint64_t value) = 0; + virtual void AddFieldHex32(std::wstring_view name, uint32_t value) = 0; + virtual void AddFieldInt32(std::wstring_view name, int32_t value, std::wstring_view unit = {}) = 0; + // Floats + virtual void AddFieldFloat(std::wstring_view name, float value, std::wstring_view unit = {}) = 0; + // Enums + virtual void AddFieldEnum(std::wstring_view name, uint32_t value, const EnumItem* enumItems) = 0; + virtual void AddFieldEnumSigned(std::wstring_view name, int32_t value, const EnumItem* enumItems) = 0; + virtual void AddEnumArray(std::wstring_view name, const uint32_t* values, size_t count, const EnumItem* enumItems) = 0; + virtual void AddFieldFlags(std::wstring_view name, uint32_t value, const EnumItem* enumItems) = 0; + // Binary data + virtual void AddFieldHexBytes(std::wstring_view name, const void* data, size_t byteCount) = 0; + // Custom types + virtual void AddFieldVendorId(std::wstring_view name, uint32_t value) = 0; + virtual void AddFieldSubsystemId(std::wstring_view name, uint32_t value) = 0; + virtual void AddFieldMicrosoftVersion(std::wstring_view name, uint64_t value) = 0; + virtual void AddFieldAMDVersion(std::wstring_view name, uint64_t value) = 0; + virtual void AddFieldNvidiaImplementationID(std::wstring_view name, uint32_t architectureId, uint32_t implementationId, const EnumItem* architecturePlusImplementationIDEnum) = 0; +}; + +ReportFormatter::FLAGS& operator|=(ReportFormatter::FLAGS& lhs, ReportFormatter::FLAGS rhs); + +class ReportFormatterScope +{ +public: + ReportFormatterScope(ReportFormatter::FLAGS flags) + { + ReportFormatter::CreateInstance(flags); + } + + ~ReportFormatterScope() + { + ReportFormatter::DestroyInstance(); + } +}; + +class ReportScopeObject +{ +public: + + ReportScopeObject(std::wstring_view name) + { + ReportFormatter::GetInstance().PushObject(name); + } + + ~ReportScopeObject() + { + ReportFormatter::GetInstance().PopScope(); + } +}; + +class ReportScopeArray +{ +public: + + ReportScopeArray(std::wstring_view name, ReportFormatter::ARRAY_SUFFIX suffix = ReportFormatter::ARRAY_SUFFIX_SQUARE_BRACKETS) + { + ReportFormatter::GetInstance().PushArray(name, suffix); + } + + ~ReportScopeArray() + { + ReportFormatter::GetInstance().PopScope(); + } +}; + +class ReportScopeArrayItem +{ +public: + ReportScopeArrayItem() + { + ReportFormatter::GetInstance().PushArrayItem(); + } + + ~ReportScopeArrayItem() + { + ReportFormatter::GetInstance().PopScope(); + } +}; + +class ReportScopeObjectConditional +{ +public: + ReportScopeObjectConditional(std::wstring_view name); + ReportScopeObjectConditional(bool enable, std::wstring_view name); + ~ReportScopeObjectConditional(); + void Enable(); +private: + std::wstring m_Name; + bool m_Enabled = false; +}; + +class ReportScopeArrayConditional +{ +public: + ReportScopeArrayConditional(std::wstring_view name, ReportFormatter::ARRAY_SUFFIX suffix = ReportFormatter::ARRAY_SUFFIX_SQUARE_BRACKETS); + ReportScopeArrayConditional(bool enable, std::wstring_view name, ReportFormatter::ARRAY_SUFFIX suffix = ReportFormatter::ARRAY_SUFFIX_SQUARE_BRACKETS); + ~ReportScopeArrayConditional(); + void Enable(); +private: + std::wstring m_Name; + ReportFormatter::ARRAY_SUFFIX m_Suffix; + bool m_Enabled = false; +}; + +class ReportScopeArrayItemConditional +{ +public: + ReportScopeArrayItemConditional(); + ReportScopeArrayItemConditional(bool enable); + ~ReportScopeArrayItemConditional(); + void Enable(); +private: + bool m_Enabled = false; +}; + +bool IsTextOutput(); +bool IsJsonOutput(); +std::wstring_view SelectString(std::wstring_view textString, std::wstring_view jsonString); +std::string_view SelectString(std::string_view textString, std::string_view jsonString); diff --git a/Src/ReportFormatter/TextReportFormatter.cpp b/Src/ReportFormatter/TextReportFormatter.cpp new file mode 100644 index 0000000..7d540c6 --- /dev/null +++ b/Src/ReportFormatter/TextReportFormatter.cpp @@ -0,0 +1,463 @@ +/* +This file is part of D3d12info project: +https://github.com/sawickiap/D3d12info + +Copyright (c) 2018-2025 Adam Sawicki, https://asawicki.info +License: MIT + +For more information, see files README.md, LICENSE.txt. +*/ +#include "TextReportFormatter.hpp" + +#include "Printer.hpp" +#include "Enums.hpp" + +TextReportFormatter::TextReportFormatter(FLAGS flags) +{ +} + +TextReportFormatter::~TextReportFormatter() +{ + assert(m_ScopeStack.empty()); + Printer::PrintNewLine(); +} + +void TextReportFormatter::PushObject(std::wstring_view name) +{ + assert(!name.empty()); + + // Need to skip new line when outputting first object + if (!m_SkipNewLine) + { + Printer::PrintNewLine(); + Printer::PrintNewLine(); + } + else + { + m_SkipNewLine = false; + } + + PrintIndent(); + + Printer::PrintString(name); + Printer::PrintString(L":"); + + PrintDivider(name.size() + 1); + + m_ScopeStack.push({ .Type = ScopeType::Object }); + ++m_IndentLevel; +} + +void TextReportFormatter::PushArray(std::wstring_view name, ARRAY_SUFFIX suffix /* = ArraySuffix::SquareBrackets */) +{ + assert(!name.empty()); + + m_ScopeStack.push({ .ArrayName = std::wstring(name), .Type = ScopeType::Array, .Suffix = suffix }); +} + +void TextReportFormatter::PushArrayItem() +{ + assert(!m_ScopeStack.empty()); + + ScopeInfo& arrayScope = m_ScopeStack.top(); + + assert(arrayScope.Type == ScopeType::Array); + + Printer::PrintNewLine(); + Printer::PrintNewLine(); + PrintIndent(); + + std::wstring header; + switch (arrayScope.Suffix) + { + case ARRAY_SUFFIX_SQUARE_BRACKETS: + header = std::format(L"{}[{}]:", arrayScope.ArrayName, arrayScope.ElementCount++); + break; + default: + assert(0); + [[fallthrough]]; + case ARRAY_SUFFIX_NONE: + header = std::format(L"{} {}:", arrayScope.ArrayName, arrayScope.ElementCount++); + break; + } + + Printer::PrintString(header); + + PrintDivider(header.size()); + + m_ScopeStack.push({ .ElementCount = 0, .Type = ScopeType::Object }); + ++m_IndentLevel; +} + +void TextReportFormatter::PopScope() +{ + assert(!m_ScopeStack.empty()); + ScopeInfo scope = m_ScopeStack.top(); + m_ScopeStack.pop(); + if (scope.Type != ScopeType::Array) + { + --m_IndentLevel; + } +} + +void TextReportFormatter::AddFieldString(std::wstring_view name, std::wstring_view value) +{ + assert(!name.empty()); + assert(!value.empty()); + PushElement(); + Printer::PrintFormat(L"{} = {}", std::make_wformat_args(name, value)); +} + +void TextReportFormatter::AddFieldStringArray(std::wstring_view name, const std::vector& value) +{ + assert(!name.empty()); + + Printer::PrintNewLine(); + PushElement(); + Printer::PrintString(name); + Printer::PrintString(L":"); + PrintDivider(name.size() + 1); + + ++m_IndentLevel; + for (const auto& element : value) + { + Printer::PrintNewLine(); + PrintIndent(); + Printer::PrintString(element); + } + --m_IndentLevel; +} + +void TextReportFormatter::AddFieldBool(std::wstring_view name, bool value) +{ + assert(!name.empty()); + PushElement(); + const wchar_t* boolStr = value ? L"TRUE" : L"FALSE"; + Printer::PrintFormat(L"{} = {}", std::make_wformat_args(name, boolStr)); +} + +void TextReportFormatter::AddFieldUint32(std::wstring_view name, uint32_t value, std::wstring_view unit /*= {}*/) +{ + assert(!name.empty()); + PushElement(); + Printer::PrintFormat(L"{} = {}", std::make_wformat_args(name, value)); +} + +void TextReportFormatter::AddFieldUint64(std::wstring_view name, uint64_t value, std::wstring_view unit /*= {}*/) +{ + assert(!name.empty()); + PushElement(); + if (unit.empty()) + { + Printer::PrintFormat(L"{} = {}", std::make_wformat_args(name, value)); + } + else + { + Printer::PrintFormat(L"{} = {} {}", std::make_wformat_args(name, value, unit)); + } +} + +void TextReportFormatter::AddFieldSize(std::wstring_view name, uint64_t value) +{ + assert(!name.empty()); + PushElement(); + + const wchar_t* units[] = { L"B", L"KiB", L"MiB", L"GiB", L"TiB" }; + + int selectedUnit = 0; + uint64_t scale = 1; + for (; selectedUnit < ARRAYSIZE(units) - 1; ++selectedUnit) + { + if (value / scale < 1024) + { + break; + } + scale = scale << 10; + } + + if (selectedUnit == 0) + { + Printer::PrintFormat(L"{} = {} {}", std::make_wformat_args(name, value, units[selectedUnit])); + return; + } + else + { + double valueScaled = double(value) / scale; + Printer::PrintFormat(L"{} = {:.2f} {} ({} B)", std::make_wformat_args(name, valueScaled, units[selectedUnit], value)); + } +} + +void TextReportFormatter::AddFieldSizeKilobytes(std::wstring_view name, uint64_t value) +{ + AddFieldSize(name, value * 1024); +} + +void TextReportFormatter::AddFieldHex32(std::wstring_view name, uint32_t value) +{ + assert(!name.empty()); + PushElement(); + Printer::PrintFormat(L"{} = 0x{:X}", std::make_wformat_args(name, value)); +} + +void TextReportFormatter::AddFieldInt32(std::wstring_view name, int32_t value, std::wstring_view unit /*= {}*/) +{ + assert(!name.empty()); + PushElement(); + if (unit.empty()) + { + Printer::PrintFormat(L"{} = {}", std::make_wformat_args(name, value)); + } + else + { + Printer::PrintFormat(L"{} = {} {}", std::make_wformat_args(name, value, unit)); + } +} + +void TextReportFormatter::AddFieldFloat(std::wstring_view name, float value, std::wstring_view unit /*= {}*/) +{ + assert(!name.empty()); + PushElement(); + if (unit.empty()) + { + Printer::PrintFormat(L"{} = {}", std::make_wformat_args(name, value)); + } + else + { + Printer::PrintFormat(L"{} = {} {}", std::make_wformat_args(name, value, unit)); + } +} + +void TextReportFormatter::AddFieldEnum(std::wstring_view name, uint32_t value, const EnumItem* enumItems) +{ + assert(!name.empty()); + PushElement(); + const wchar_t* enumItemName = FindEnumItemName(value, enumItems); + if (enumItemName != nullptr) + { + Printer::PrintFormat(L"{} = {} (0x{:X})", std::make_wformat_args(name, enumItemName, value)); + } + else + { + Printer::PrintFormat(L"{} = 0x{:X}", std::make_wformat_args(name, value)); + } +} + +void TextReportFormatter::AddFieldEnumSigned(std::wstring_view name, int32_t value, const EnumItem* enumItems) +{ + assert(!name.empty()); + PushElement(); + const wchar_t* enumItemName = FindEnumItemName(value, enumItems); + if (enumItemName != nullptr) + { + Printer::PrintFormat(L"{} = {} ({})", std::make_wformat_args(name, enumItemName, value)); + } + else + { + Printer::PrintFormat(L"{} = {}", std::make_wformat_args(name, value)); + } + +} + +void TextReportFormatter::AddEnumArray(std::wstring_view name, const uint32_t* values, size_t count, const EnumItem* enumItems) +{ + assert(!name.empty()); + + Printer::PrintNewLine(); + PushElement(); + Printer::PrintString(name); + Printer::PrintString(L":"); + PrintDivider(name.size() + 1); + + ++m_IndentLevel; + for (size_t i = 0; i < count; ++i) + { + Printer::PrintNewLine(); + PrintIndent(); + const wchar_t* enumItemName = FindEnumItemName(values[i], enumItems); + if (enumItemName != nullptr) + { + Printer::PrintFormat(L"[{}] = {} (0x{:X})", std::make_wformat_args(i, enumItemName, values[i])); + } + else + { + Printer::PrintFormat(L"[{}] = 0x{:X}", std::make_wformat_args(i, values[i])); + } + } + --m_IndentLevel; +} + +void TextReportFormatter::AddFieldFlags(std::wstring_view name, uint32_t value, const EnumItem* enumItems) +{ + assert(!name.empty()); + PushElement(); + Printer::PrintFormat(L"{} = 0x{:X}", std::make_wformat_args(name, value)); + + ++m_IndentLevel; + size_t zeroFlagIndex = SIZE_MAX; + for (size_t i = 0; enumItems[i].m_Name != nullptr; ++i) + { + if (enumItems[i].m_Value == 0) + { + zeroFlagIndex = i; + } + else + { + if ((value & enumItems[i].m_Value) != 0) + { + Printer::PrintNewLine(); + PrintIndent(); + Printer::PrintString(enumItems[i].m_Name); + } + } + } + if (value == 0 && zeroFlagIndex != SIZE_MAX) + { + Printer::PrintNewLine(); + PrintIndent(); + Printer::PrintString(enumItems[zeroFlagIndex].m_Name); + } + --m_IndentLevel; +} + +void TextReportFormatter::AddFieldHexBytes(std::wstring_view name, const void* data, size_t byteCount) +{ + std::wstring valStr; + for (size_t i = 0; i < byteCount; ++i) + { + valStr += std::format(L"{:02X}", *((const uint8_t*)data + i)); + } + AddFieldString(name, valStr); +} + +void TextReportFormatter::AddFieldVendorId(std::wstring_view name, uint32_t value) +{ + assert(!name.empty()); + + auto ACPIIDOpt = DecodeACPIID(value); + + if (ACPIIDOpt.has_value()) + { + PushElement(); + auto& ACPIID = ACPIIDOpt.value(); + const wchar_t* enumItemName = FindEnumItemName(value, Enum_VendorId); + if (enumItemName == nullptr) + { + enumItemName = L"Unknown"; + } + + Printer::PrintFormat(L"{} = {} \"{}\" (0x{:X})", std::make_wformat_args(name, enumItemName, ACPIID, value)); + } + else + { + AddFieldEnum(name, value, Enum_VendorId); + } + +} + +void TextReportFormatter::AddFieldSubsystemId(std::wstring_view name, uint32_t value) +{ + assert(!name.empty()); + PushElement(); + + const wchar_t* enumItemName = FindEnumItemName(value & 0xFFFF, Enum_SubsystemVendorId); + if (enumItemName != nullptr) + { + Printer::PrintFormat(L"{} = {} (0x{:X})", std::make_wformat_args(name, enumItemName, value)); + } + else + { + Printer::PrintFormat(L"{} = 0x{:X}", std::make_wformat_args(name, value)); + } + +} + +void TextReportFormatter::AddFieldMicrosoftVersion(std::wstring_view name, uint64_t value) +{ + assert(!name.empty()); + PushElement(); + uint64_t major = value >> 48; + uint64_t minor = (value >> 32) & 0xFFFF; + uint64_t build = (value >> 16) & 0xFFFF; + uint64_t revision = value & 0xFFFF; + Printer::PrintFormat(L"{} = {}.{}.{}.{}", std::make_wformat_args(name, major, minor, build, revision)); +} + +void TextReportFormatter::AddFieldAMDVersion(std::wstring_view name, uint64_t value) +{ + assert(!name.empty()); + PushElement(); + uint64_t major = value >> 22; + uint64_t minor = (value >> 12) & 0b11'1111'1111; + uint64_t patch = value & 0b1111'1111'1111; + Printer::PrintFormat(L"{} = {}.{}.{}", std::make_wformat_args(name, major, minor, patch)); +} + +void TextReportFormatter::AddFieldNvidiaImplementationID(std::wstring_view name, uint32_t architectureId, uint32_t implementationId, const EnumItem* architecturePlusImplementationIDEnum) +{ + // Prints only implementationId as the numerical value, but searches enum + // using architectureId + implementationId. + + assert(!name.empty()); + PushElement(); + + const wchar_t* enumItemName = FindEnumItemName(architectureId + implementationId, + architecturePlusImplementationIDEnum); + if (enumItemName == nullptr) + { + enumItemName = L"Unknown"; + } + + Printer::PrintFormat(L"{} = {} (0x{:X})", std::make_wformat_args(name, enumItemName, implementationId)); +} + +void TextReportFormatter::PrintIndent() const +{ + int effectiveIndentLevel = std::max(m_IndentLevel - 1, 0); + Printer::PrintString(std::wstring(INDENT_SIZE * effectiveIndentLevel, INDENT_CHAR)); +} + +void TextReportFormatter::PushElement() +{ + m_ScopeStack.top().ElementCount++; + Printer::PrintNewLine(); + PrintIndent(); +} + +void TextReportFormatter::PrintDivider(size_t size) +{ + Printer::PrintNewLine(); + PrintIndent(); + wchar_t dividerChar; + + switch (m_IndentLevel) + { + case 0: + dividerChar = L'='; + break; + default: + dividerChar = L'-'; + break; + } + + Printer::PrintString(std::wstring(size, dividerChar)); +} + +std::optional TextReportFormatter::DecodeACPIID(uint32_t value) +{ + if (value <= 0xFFFF) + { + return std::nullopt; + } + + std::wstring result; + result.resize(4); + + for (uint32_t i = 0; i < 4; ++i) + { + const uint8_t charValue = (uint8_t)(value >> (i * 8)); + if (charValue < 32 || charValue > 126) + return std::nullopt; + result[i] = (wchar_t)charValue; + } + return result; +} diff --git a/Src/ReportFormatter/TextReportFormatter.hpp b/Src/ReportFormatter/TextReportFormatter.hpp new file mode 100644 index 0000000..28c14db --- /dev/null +++ b/Src/ReportFormatter/TextReportFormatter.hpp @@ -0,0 +1,72 @@ +/* +This file is part of D3d12info project: +https://github.com/sawickiap/D3d12info + +Copyright (c) 2018-2025 Adam Sawicki, https://asawicki.info +License: MIT + +For more information, see files README.md, LICENSE.txt. +*/ + +#pragma once + +#include "ReportFormatter.hpp" + +class TextReportFormatter final : public ReportFormatter +{ +public: + TextReportFormatter(FLAGS flags); + ~TextReportFormatter(); + + void PushObject(std::wstring_view name) final; + void PushArray(std::wstring_view name, ARRAY_SUFFIX suffix = ARRAY_SUFFIX_SQUARE_BRACKETS); + void PushArrayItem() final; + void PopScope() final; + + void AddFieldString(std::wstring_view name, std::wstring_view value) final; + void AddFieldStringArray(std::wstring_view name, const std::vector& value) final; + void AddFieldBool(std::wstring_view name, bool value); + void AddFieldUint32(std::wstring_view name, uint32_t value, std::wstring_view unit = {}) final; + void AddFieldUint64(std::wstring_view name, uint64_t value, std::wstring_view unit = {}) final; + void AddFieldSize(std::wstring_view name, uint64_t value) final; + void AddFieldSizeKilobytes(std::wstring_view name, uint64_t value) final; + void AddFieldHex32(std::wstring_view name, uint32_t value) final; + void AddFieldInt32(std::wstring_view name, int32_t value, std::wstring_view unit = {}) final; + void AddFieldFloat(std::wstring_view name, float value, std::wstring_view unit = {}) final; + void AddFieldEnum(std::wstring_view name, uint32_t value, const EnumItem* enumItems) final; + void AddFieldEnumSigned(std::wstring_view name, int32_t value, const EnumItem* enumItems) final; + void AddEnumArray(std::wstring_view name, const uint32_t* values, size_t count, const EnumItem* enumItems) final; + void AddFieldFlags(std::wstring_view name, uint32_t value, const EnumItem* enumItems) final; + void AddFieldHexBytes(std::wstring_view name, const void* data, size_t byteCount) final; + void AddFieldVendorId(std::wstring_view name, uint32_t value) final; + void AddFieldSubsystemId(std::wstring_view name, uint32_t value) final; + void AddFieldMicrosoftVersion(std::wstring_view name, uint64_t value) final; + void AddFieldAMDVersion(std::wstring_view name, uint64_t value) final; + void AddFieldNvidiaImplementationID(std::wstring_view name, uint32_t architectureId, uint32_t implementationId, const EnumItem* architecturePlusImplementationIDEnum) final; + +private: + static constexpr size_t INDENT_SIZE = 4; + static constexpr wchar_t INDENT_CHAR = L' '; + + enum class ScopeType + { + Object, + Array + }; + struct ScopeInfo + { + std::wstring ArrayName; + size_t ElementCount = 0; + ScopeType Type; + ARRAY_SUFFIX Suffix; + }; + std::stack m_ScopeStack; + int m_IndentLevel = 0; + bool m_SkipNewLine = true; + + void PrintIndent() const; + void PushElement(); + void PrintDivider(size_t size); + + static std::optional DecodeACPIID(uint32_t value); +}; diff --git a/Src/ThirdParty/rapidjson b/Src/ThirdParty/rapidjson deleted file mode 160000 index 24b5e7a..0000000 --- a/Src/ThirdParty/rapidjson +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 24b5e7a8b27f42fa16b96fc70aade9106cf7102f diff --git a/Src/VulkanData.cpp b/Src/VulkanData.cpp index 6719577..5ff53ed 100644 --- a/Src/VulkanData.cpp +++ b/Src/VulkanData.cpp @@ -8,10 +8,9 @@ License: MIT For more information, see files README.md, LICENSE.txt. */ #include "VulkanData.hpp" -#include "Printing.hpp" #include "Utils.hpp" -#include "Json.hpp" #include "Enums.hpp" +#include "ReportFormatter/ReportFormatter.hpp" // Macro set by Cmake. #if USE_VULKAN @@ -188,6 +187,7 @@ Vulkan_Initialize_RAII::~Vulkan_Initialize_RAII() void Vulkan_Initialize_RAII::PrintData(const DXGI_ADAPTER_DESC& adapterDesc) { assert(IsInitialized()); + ReportFormatter& formatter = ReportFormatter::GetInstance(); size_t physDevIndex = SIZE_MAX; if(!FindPhysicalDevice(adapterDesc, physDevIndex)) @@ -196,32 +196,32 @@ void Vulkan_Initialize_RAII::PrintData(const DXGI_ADAPTER_DESC& adapterDesc) { const VkPhysicalDeviceProperties& props = propSet.properties2.properties; - ScopedStructRegion region(L"VkPhysicalDeviceProperties"); - Print_string(L"apiVersion", std::format(L"{}.{}.{}", + ReportScopeObject region(L"VkPhysicalDeviceProperties"); + formatter.AddFieldString(L"apiVersion", std::format(L"{}.{}.{}", VK_API_VERSION_MAJOR(props.apiVersion), VK_API_VERSION_MINOR(props.apiVersion), VK_API_VERSION_PATCH(props.apiVersion)).c_str()); - Print_uint32(L"driverVersion", props.driverVersion); - PrintVendorId(L"vendorID", props.vendorID); - Print_hex32(L"deviceID", props.deviceID); - PrintEnum(L"deviceType", props.deviceType, Enum_VkPhysicalDeviceType); - Print_string(L"deviceName", StrToWstr(props.deviceName, CP_UTF8).c_str()); + formatter.AddFieldUint32(L"driverVersion", props.driverVersion); + formatter.AddFieldVendorId(L"vendorID", props.vendorID); + formatter.AddFieldHex32(L"deviceID", props.deviceID); + formatter.AddFieldEnum(L"deviceType", props.deviceType, Enum_VkPhysicalDeviceType); + formatter.AddFieldString(L"deviceName", StrToWstr(props.deviceName, CP_UTF8).c_str()); } { const VkPhysicalDeviceIDProperties& IDProps = propSet.IDProperties; - ScopedStructRegion region(L"VkPhysicalDeviceIDProperties"); - PrintHexBytes(L"deviceUUID", IDProps.deviceUUID, VK_UUID_SIZE); - PrintHexBytes(L"driverUUID", IDProps.driverUUID, VK_UUID_SIZE); + ReportScopeObject region(L"VkPhysicalDeviceIDProperties"); + formatter.AddFieldHexBytes(L"deviceUUID", IDProps.deviceUUID, VK_UUID_SIZE); + formatter.AddFieldHexBytes(L"driverUUID", IDProps.driverUUID, VK_UUID_SIZE); if(IDProps.deviceLUIDValid) - PrintHexBytes(L"deviceLUID", IDProps.deviceLUID, VK_LUID_SIZE); + formatter.AddFieldHexBytes(L"deviceLUID", IDProps.deviceLUID, VK_LUID_SIZE); } if(g_ApiVersion >= VK_API_VERSION_1_2) { const VkPhysicalDeviceVulkan12Properties& vulkan12Props = propSet.vulkan12Properties; - ScopedStructRegion region(L"VkPhysicalDeviceVulkan12Properties"); - PrintEnum(L"driverID", vulkan12Props.driverID, Enum_VkDriverId); - Print_string(L"driverName", StrToWstr(vulkan12Props.driverName, CP_UTF8).c_str()); - Print_string(L"driverInfo", StrToWstr(vulkan12Props.driverInfo, CP_UTF8).c_str()); + ReportScopeObject region(L"VkPhysicalDeviceVulkan12Properties"); + formatter.AddFieldEnum(L"driverID", vulkan12Props.driverID, Enum_VkDriverId); + formatter.AddFieldString(L"driverName", StrToWstr(vulkan12Props.driverName, CP_UTF8).c_str()); + formatter.AddFieldString(L"driverInfo", StrToWstr(vulkan12Props.driverInfo, CP_UTF8).c_str()); } } diff --git a/Src/pch.hpp b/Src/pch.hpp index 2253968..84faa00 100644 --- a/Src/pch.hpp +++ b/Src/pch.hpp @@ -31,22 +31,29 @@ For more information, see files README.md, LICENSE.txt. #include // For StringFromGUID2 #include // for ComPtr -#include +#include #include -#include -#include #include #include +#include +#include +#include +#include +#include +#include #include -#include -#include +#include +#include +#include +#include -#include #include +#include +#include #include #include -#include #include +#include using std::string; using std::wstring;