├── .clang-format ├── .editorconfig ├── .gitattributes ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── cmake ├── FindSDL2.cmake └── ucm.cmake ├── com.github.gpuvis.Gpuvis.desktop ├── com.github.gpuvis.Gpuvis.metainfo.xml ├── com.github.gpuvis.Gpuvis.svg ├── images └── gpuvis.jpg ├── meson.build ├── meson_options.txt ├── patches └── 0001-perf-data-Add-JSON-export.patch ├── qtcreator └── update_files.sh ├── sample ├── Makefile ├── glxgears.c ├── gpuvis_trace_utils.h ├── trace-cmd-capture.sh ├── trace-cmd-command.sh ├── trace-cmd-setup.sh ├── trace-cmd-start-tracing.sh ├── trace-cmd-status.sh └── trace-cmd-stop-tracing.sh ├── src ├── Droid_Sans.cpp ├── GL │ ├── gl3w.c │ ├── gl3w.h │ └── glcorearb.h ├── MurmurHash3.cpp ├── MurmurHash3.h ├── RobotoCondensed_Regular.cpp ├── Roboto_Regular.cpp ├── etl_utils.cpp ├── etl_utils.h ├── fnv.h ├── gpuvis.cpp ├── gpuvis.h ├── gpuvis_colors.inl ├── gpuvis_etl.cpp ├── gpuvis_etl.h ├── gpuvis_framemarkers.cpp ├── gpuvis_ftrace_print.cpp ├── gpuvis_graph.cpp ├── gpuvis_graphrows.cpp ├── gpuvis_i915_perfcounters.cpp ├── gpuvis_icon.c ├── gpuvis_macros.h ├── gpuvis_plots.cpp ├── gpuvis_utils.cpp ├── gpuvis_utils.h ├── hook_gtk3.h ├── hook_gtk3_funcs.inl ├── i915-perf │ ├── i915-perf-read.cpp │ └── i915-perf-read.h ├── imgui │ ├── imconfig.h │ ├── imgui.cpp │ ├── imgui.h │ ├── imgui_demo.cpp │ ├── imgui_draw.cpp │ ├── imgui_freetype.cpp │ ├── imgui_freetype.h │ ├── imgui_impl_sdl_gl3.cpp │ ├── imgui_impl_sdl_gl3.h │ ├── imgui_internal.h │ ├── stb_rect_pack.h │ ├── stb_textedit.h │ └── stb_truetype.h ├── libtraceevent │ ├── README │ ├── include │ │ ├── asm │ │ │ └── bug.h │ │ └── linux │ │ │ ├── compiler-gcc.h │ │ │ ├── compiler.h │ │ │ └── time64.h │ └── src │ │ ├── event-parse-api.c │ │ ├── event-parse-local.h │ │ ├── event-parse.c │ │ ├── event-parse.h │ │ ├── event-plugin.c │ │ ├── event-utils.h │ │ ├── kbuffer-parse.c │ │ ├── kbuffer.h │ │ ├── parse-filter.c │ │ ├── parse-utils.c │ │ ├── tep_strerror.c │ │ ├── trace-seq.c │ │ └── trace-seq.h ├── miniz.c ├── miniz.h ├── noc_file_dialog.h ├── noc_file_dialog_osx.mm ├── proggy_tiny.cpp ├── stb_image_write.h ├── stlini.cpp ├── stlini.h ├── tdopexpr.cpp ├── tdopexpr.h ├── trace-cmd │ ├── COPYING │ ├── COPYING.LIB │ ├── trace-read.cpp │ └── trace-read.h ├── ya_getopt.c └── ya_getopt.h └── traces ├── amdgpu_trace.zip └── windows_etl.zip /.clang-format: -------------------------------------------------------------------------------- 1 | # 2 | # http://clang.llvm.org/docs/ClangFormatStyleOptions.html 3 | # Configurator: http://zed0.co.uk/clang-format-configurator/ 4 | # 5 | AccessModifierOffset: -4 6 | ConstructorInitializerIndentWidth: 4 7 | AlignEscapedNewlinesLeft: false 8 | AlignTrailingComments: true 9 | AllowAllParametersOfDeclarationOnNextLine: true 10 | AllowShortIfStatementsOnASingleLine: false 11 | AllowShortLoopsOnASingleLine: false 12 | AlwaysBreakTemplateDeclarations: false 13 | AlwaysBreakBeforeMultilineStrings: false 14 | BreakBeforeBinaryOperators: false 15 | BreakBeforeTernaryOperators: false 16 | BreakConstructorInitializersBeforeComma: false 17 | BinPackParameters: true 18 | ColumnLimit: 0 19 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 20 | DerivePointerBinding: false 21 | ExperimentalAutoDetectBinPacking: false 22 | IndentCaseLabels: false 23 | MaxEmptyLinesToKeep: 1 24 | NamespaceIndentation: All 25 | ObjCSpaceBeforeProtocolList: true 26 | PenaltyBreakBeforeFirstCallParameter: 19 27 | PenaltyBreakComment: 60 28 | PenaltyBreakString: 1000 29 | PenaltyBreakFirstLessLess: 120 30 | PenaltyExcessCharacter: 1000000 31 | PenaltyReturnTypeOnItsOwnLine: 60 32 | PointerBindsToType: false 33 | SpacesBeforeTrailingComments: 1 34 | Cpp11BracedListStyle: false 35 | Standard: Cpp03 36 | IndentWidth: 4 37 | TabWidth: 4 38 | UseTab: Never 39 | BreakBeforeBraces: Allman 40 | IndentFunctionDeclarationAfterType: false 41 | # SortIncludes: false 42 | SpacesInParentheses: true 43 | SpacesInSquareBrackets: true 44 | SpacesInAngles: true 45 | SpaceInEmptyParentheses: false 46 | SpacesInCStyleCastParentheses: true 47 | SpaceAfterCStyleCast: false 48 | SpaceAfterControlStatementKeyword: true 49 | SpaceBeforeAssignmentOperators: true 50 | ContinuationIndentWidth: 4 51 | PointerAlignment: Right 52 | SpaceBeforeParens: ControlStatements 53 | # ForEachMacros: RB_FOREACH, sbforeach 54 | AlignOperands: true 55 | # AlignConsecutiveAssignments: true 56 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | 9 | [*.{c,h,cpp,hpp}] 10 | indent_style = space 11 | indent_size = 4 12 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sh text eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/* 2 | _release/* 3 | _debug/* 4 | build/* 5 | traces_x/* 6 | traces_intel/* 7 | lib/ 8 | 9 | sample/_release/* 10 | sample/_debug/* 11 | 12 | qtcreator/gpuvis.creator.user* 13 | qtcreator/gpuvis.config 14 | qtcreator/gpuvis.creator 15 | qtcreator/gpuvis.files 16 | qtcreator/gpuvis.includes 17 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeLists.txt for gpuvis 2 | 3 | # To build on Windows: 4 | # 5 | # Download SDL2 development libraries and runtime binary: 6 | # https://www.libsdl.org/download-2.0.php 7 | # 8 | # set SDL2DIR=c:\dev\SDL2-2.0.5 9 | # 10 | # git clone https://github.com/mikesart/gpuvis 11 | # mkdir gpuvis\build 12 | # cd gpuvis\build 13 | # ; copy SDL2.dll here... 14 | # 15 | # cmake -G "NMake Makefiles JOM" -DCMAKE_BUILD_TYPE=RelWithDebInfo .. 16 | # jom 17 | # 18 | 19 | cmake_minimum_required( VERSION 2.8 FATAL_ERROR ) 20 | 21 | project( "gpuvis" ) 22 | 23 | option(USE_FREETYPE "USE_FREETYPE" ON) 24 | option(USE_I915_PERF "USE_I915_PERF" OFF) 25 | option(USE_RAPIDJSON "USE_RAPIDJSON" ON) 26 | 27 | set( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ) 28 | 29 | # bring in useful cmake macros 30 | # https://github.com/onqtam/ucm 31 | include( "cmake/ucm.cmake" ) 32 | 33 | find_package( SDL2 REQUIRED ) 34 | 35 | if ( USE_FREETYPE ) 36 | find_package( Freetype REQUIRED ) 37 | ucm_add_flags( -DUSE_FREETYPE ) 38 | endif() 39 | 40 | # https://github.com/mikesart/gpuvis/issues/17 41 | # From Pierre-Loup: Static is better for our usecase, since we do ad-hoc builds 42 | # that we distribute in SteamVR. 43 | ucm_set_runtime( STATIC ) 44 | 45 | # https://codingnest.com/basic-cmake/#fnref6 46 | # also: CMAKE_CXX_COMPILER_VERSION 47 | ## if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" ) 48 | ## message("foo") 49 | ## # target_compile_options( vector-test PRIVATE -Wall -Wextra -Wunreachable-code -Wpedantic) 50 | ## endif() 51 | ## if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) 52 | ## message("foo2") 53 | ## # target_compile_options( vector-test PRIVATE -Wweak-vtables -Wexit-time-destructors -Wglobal-constructors -Wmissing-noreturn ) 54 | ## endif() 55 | ## if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" ) 56 | ## message("foo3") 57 | ## # target_compile_options( vector-test PRIVATE /W4 /w44265 /w44061 /w44062 ) 58 | ## endif() 59 | 60 | ucm_add_flags( -O0 -DDEBUG CONFIG Debug ) 61 | ucm_add_flags( -O2 -DNDEBUG CONFIG Release ) 62 | 63 | if ( CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang" ) 64 | ucm_add_flags( CXX -std=c++11 ) 65 | endif() 66 | 67 | if ( APPLE ) 68 | ucm_add_flags( CXX -stdlib=libc++ ) 69 | ucm_add_linker_flags( -stdlib=libc++ ) 70 | endif() 71 | 72 | if ( WIN32 ) 73 | ucm_add_flags( -D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4244 /wd4090 /wd4018 /wd4267 ) 74 | 75 | LINK_LIBRARIES( shlwapi opengl32 comctl32 tdh ) 76 | elseif ( UNIX AND NOT APPLE ) 77 | find_package( PkgConfig REQUIRED ) 78 | pkg_check_modules( GTK3 REQUIRED gtk+-3.0 ) 79 | 80 | ucm_add_flags( -DUSE_GTK3 ) 81 | if(CMAKE_SYSTEM_NAME MATCHES "Linux|SunOS" OR MINGW) 82 | ucm_add_flags( -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 ) 83 | endif() 84 | 85 | set( GTK3_LIBRARIES "" ) 86 | 87 | LINK_LIBRARIES( ${CMAKE_DL_LIBS} ) 88 | endif() 89 | 90 | if ( USE_I915_PERF ) 91 | pkg_check_modules( I915_PERF REQUIRED i915-perf>=1.5.0) 92 | pkg_check_modules( I915_PERF REQUIRED xe-oa ) 93 | ucm_add_flags( -DUSE_I915_PERF ) 94 | endif() 95 | 96 | if ( USE_RAPIDJSON ) 97 | find_package( RapidJSON REQUIRED ) 98 | ucm_add_flags( -DHAVE_RAPIDJSON ) 99 | endif() 100 | 101 | ucm_print_flags() 102 | 103 | # Main source list 104 | set ( SRC_LIST 105 | src/gpuvis.cpp 106 | src/gpuvis_graph.cpp 107 | src/gpuvis_framemarkers.cpp 108 | src/gpuvis_plots.cpp 109 | src/gpuvis_graphrows.cpp 110 | src/gpuvis_ftrace_print.cpp 111 | src/gpuvis_i915_perfcounters.cpp 112 | src/gpuvis_utils.cpp 113 | src/gpuvis_etl.cpp 114 | src/etl_utils.cpp 115 | src/tdopexpr.cpp 116 | src/ya_getopt.c 117 | src/MurmurHash3.cpp 118 | src/miniz.c 119 | src/stlini.cpp 120 | src/imgui/imgui_impl_sdl_gl3.cpp 121 | src/imgui/imgui.cpp 122 | src/imgui/imgui_demo.cpp 123 | src/imgui/imgui_draw.cpp 124 | src/imgui/imgui_freetype.cpp 125 | src/GL/gl3w.c 126 | src/i915-perf/i915-perf-read.cpp 127 | src/libtraceevent/src/event-parse.c 128 | src/libtraceevent/src/event-parse-api.c 129 | src/libtraceevent/src/event-plugin.c 130 | src/libtraceevent/src/kbuffer-parse.c 131 | src/libtraceevent/src/parse-utils.c 132 | src/libtraceevent/src/trace-seq.c 133 | src/trace-cmd/trace-read.cpp 134 | ) 135 | 136 | if ( APPLE ) 137 | list ( APPEND SRC_LIST src/noc_file_dialog_osx.mm ) 138 | endif() 139 | 140 | include_directories( 141 | ${CMAKE_CURRENT_LIST_DIR}/src 142 | ${CMAKE_CURRENT_LIST_DIR}/src/libtraceevent/include 143 | ${FREETYPE_INCLUDE_DIRS} 144 | ${GTK3_INCLUDE_DIRS} 145 | ${SDL2_INCLUDE_DIR} 146 | ${RAPIDJSON_INCLUDE_DIRS} 147 | ${I915_PERF_INCLUDE_DIRS} 148 | ) 149 | 150 | ucm_add_target( NAME gpuvis TYPE EXECUTABLE SOURCES ${SRC_LIST} ) 151 | 152 | target_link_libraries( 153 | ${PROJECT_NAME} 154 | ${LIBRARY_LIST} 155 | ${SDL2_LIBRARY} 156 | ${FREETYPE_LIBRARIES} 157 | ${GTK3_LIBRARIES} 158 | ${I915_PERF_LIBRARIES} 159 | ) 160 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2018 Valve Software 4 | 5 | All Rights Reserved. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # $@: name of the target file (one before colon) 2 | # $<: name of first prerequisite file (first one after colon) 3 | # $^: names of all prerequisite files (space separated) 4 | # $*: stem (bit which matches the % wildcard in rule definition) 5 | # 6 | # VAR = val: Normal setting - values within are recursively expand when var used. 7 | # VAR := val: Setting of var with simple expansion of values inside - values are expanded at decl time. 8 | # VAR ?= val: Set var only if it doesn't have a value. 9 | # VAR += val: Append val to existing value (or set if var didn't exist). 10 | 11 | # To use static analyzer: 12 | # http://clang-analyzer.llvm.org/scan-build.html 13 | # Ie: 14 | # scan-build -k -V --use-analyzer ~/bin/clang make 15 | 16 | .PHONY: all 17 | all: 18 | 19 | NAME = gpuvis 20 | 21 | USE_GTK3 ?= 1 22 | USE_I915_PERF ?= 0 23 | USE_RAPIDJSON ?= 1 24 | CFG ?= release 25 | ifeq ($(CFG), debug) 26 | ASAN ?= 1 27 | endif 28 | 29 | LD = $(CC) 30 | RM = rm -f 31 | MKDIR = mkdir -p 32 | VERBOSE ?= 0 33 | 34 | COMPILER = $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc) 35 | 36 | WARNINGS = -Wall -Wextra -Wpedantic -Wmissing-include-dirs -Wformat=2 -Wshadow \ 37 | -Wno-unused-parameter -Wno-missing-field-initializers -Wno-variadic-macros 38 | CXXWARNINGS = 39 | 40 | ifneq ($(COMPILER),clang) 41 | # https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html 42 | WARNINGS += -Wsuggest-attribute=format -Wimplicit-fallthrough=2 43 | CXXWARNINGS += -Wno-class-memaccess 44 | 45 | NO_MAYBE_UNINITIALIZED = -Wno-maybe-uninitialized 46 | NO_OLD_STYLE_DECLARATION = -Wno-old-style-declaration 47 | NO_STRINGOP_TRUNCATION = -Wno-stringop-truncation 48 | NO_COMPARE_DISTINCT_POINTER_TYPES = 49 | NO_FORMAT_NONLITERAL = 50 | NO_POINTER_SIGN = 51 | NO_CLOBBERED = -Wno-clobbered 52 | NO_SUGGEST_ATTRIBUTE_FORMAT = -Wno-suggest-attribute=format 53 | else 54 | NO_MAYBE_UNINITIALIZED = 55 | NO_OLD_STYLE_DECLARATION = 56 | NO_STRINGOP_TRUNCATION = 57 | NO_COMPARE_DISTINCT_POINTER_TYPES = -Wno-compare-distinct-pointer-types 58 | NO_FORMAT_NONLITERAL = -Wno-format-nonliteral 59 | NO_POINTER_SIGN = -Wno-pointer-sign 60 | NO_CLOBBERED = 61 | NO_SUGGEST_ATTRIBUTE_FORMAT = 62 | endif 63 | 64 | # Investigate: Improving C++ Builds with Split DWARF 65 | # http://www.productive-cpp.com/improving-cpp-builds-with-split-dwarf/ 66 | 67 | CFLAGS = $(WARNINGS) -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames -gsplit-dwarf 68 | CFLAGS += -DUSE_FREETYPE 69 | CXXFLAGS = -fno-rtti -Woverloaded-virtual $(CXXWARNINGS) 70 | LDFLAGS = -gdwarf-4 -g2 -Wl,--build-id=sha1 71 | LIBS = -Wl,--no-as-needed -lm -lpthread -lstdc++ 72 | 73 | CFLAGS += $(shell sdl2-config --cflags) 74 | LIBS += $(shell sdl2-config --libs) 75 | 76 | ifeq (, $(filter-out Linux SunOS,$(shell uname -s))) 77 | CFLAGS += -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 78 | LIBS += -ldl 79 | endif 80 | 81 | ifeq ($(USE_GTK3), 1) 82 | CFLAGS += $(shell pkg-config --cflags gtk+-3.0) -DUSE_GTK3 83 | endif 84 | 85 | ifeq ($(USE_I915_PERF), 1) 86 | CFLAGS += $(shell pkg-config --cflags i915-perf) -DUSE_I915_PERF 87 | LIBS += $(shell pkg-config --libs i915-perf) 88 | endif 89 | 90 | ifeq ($(USE_RAPIDJSON), 1) 91 | CFLAGS += $(shell pkg-config --cflags RapidJSON) -DHAVE_RAPIDJSON 92 | endif 93 | 94 | CFLAGS += $(shell pkg-config --cflags freetype2) 95 | LIBS += $(shell pkg-config --libs freetype2) 96 | 97 | CFLAGS += -Isrc/libtraceevent/include 98 | 99 | ifneq ("$(wildcard /usr/bin/ld.gold)","") 100 | $(info Using gold linker...) 101 | LDFLAGS += -fuse-ld=gold -Wl,--gdb-index 102 | endif 103 | 104 | # https://gcc.gnu.org/onlinedocs/libstdc++/manual/profile_mode.html#manual.ext.profile_mode.intro 105 | # To resolve addresses from libstdcxx-profile.conf.out: addr2line -C -f -e _debug/gpuvis 0x42cc6a 0x43630a 0x46654d 106 | # CFLAGS += -D_GLIBCXX_PROFILE -D_GLIBCXX_PROFILE_CONTAINERS 107 | 108 | CFILES = \ 109 | src/gpuvis.cpp \ 110 | src/gpuvis_etl.cpp \ 111 | src/gpuvis_graph.cpp \ 112 | src/gpuvis_framemarkers.cpp \ 113 | src/gpuvis_plots.cpp \ 114 | src/gpuvis_graphrows.cpp \ 115 | src/gpuvis_ftrace_print.cpp \ 116 | src/gpuvis_utils.cpp \ 117 | src/tdopexpr.cpp \ 118 | src/ya_getopt.c \ 119 | src/MurmurHash3.cpp \ 120 | src/miniz.c \ 121 | src/stlini.cpp \ 122 | src/imgui/imgui_impl_sdl_gl3.cpp \ 123 | src/imgui/imgui.cpp \ 124 | src/imgui/imgui_demo.cpp \ 125 | src/imgui/imgui_draw.cpp \ 126 | src/GL/gl3w.c \ 127 | src/i915-perf/i915-perf-read.cpp \ 128 | src/libtraceevent/src/event-parse.c \ 129 | src/libtraceevent/src/event-parse-api.c \ 130 | src/libtraceevent/src/event-plugin.c \ 131 | src/libtraceevent/src/kbuffer-parse.c \ 132 | src/libtraceevent/src/parse-utils.c \ 133 | src/libtraceevent/src/trace-seq.c \ 134 | src/trace-cmd/trace-read.cpp \ 135 | src/imgui/imgui_freetype.cpp \ 136 | src/gpuvis_i915_perfcounters.cpp 137 | 138 | ifeq ($(PROF), 1) 139 | # To profile with google perftools: 140 | # http://htmlpreview.github.io/?https://github.com/gperftools/gperftools/blob/master/doc/cpuprofile.html 141 | # PROF=1 make -j 30 && CPUPROFILE_FREQUENCY=10000 _release/gpuvis && pprof --stack --text _release/gpuvis ./gpuvis.prof | vi - 142 | # PROF=1 make -j 30 && CPUPROFILE_FREQUENCY=10000 _release/gpuvis && pprof --web _release/gpuvis ./gpuvis.prof 143 | ASAN = 0 144 | CFLAGS += -DGPROFILER 145 | LDFLAGS += -Wl,--no-as-needed -lprofiler 146 | endif 147 | 148 | # Useful GCC address sanitizer checks not enabled by default 149 | # https://kristerw.blogspot.com/2018/06/useful-gcc-address-sanitizer-checks-not.html 150 | 151 | ifeq ($(ASAN), 1) 152 | # https://gcc.gnu.org/gcc-5/changes.html 153 | # -fsanitize=float-cast-overflow: check that the result of floating-point type to integer conversions do not overflow; 154 | # -fsanitize=alignment: enable alignment checking, detect various misaligned objects; 155 | # -fsanitize=vptr: enable checking of C++ member function calls, member accesses and some conversions between pointers to base and derived classes, detect if the referenced object does not have the correct dynamic type. 156 | ASAN_FLAGS = -fno-omit-frame-pointer -fno-optimize-sibling-calls 157 | ASAN_FLAGS += -fsanitize=address # fast memory error detector (heap, stack, global buffer overflow, and use-after free) 158 | ASAN_FLAGS += -fsanitize=leak # detect leaks 159 | ASAN_FLAGS += -fsanitize=float-divide-by-zero # detect floating-point division by zero; 160 | ASAN_FLAGS += -fsanitize=bounds # enable instrumentation of array bounds and detect out-of-bounds accesses; 161 | ifneq ($(COMPILER),clang) 162 | ASAN_FLAGS += -fsanitize=undefined # fast undefined behavior detector 163 | ASAN_FLAGS += -fsanitize=object-size # enable object size checking, detect various out-of-bounds accesses. 164 | endif 165 | CFLAGS += $(ASAN_FLAGS) 166 | LDFLAGS += $(ASAN_FLAGS) 167 | endif 168 | 169 | ifeq ($(CFG), debug) 170 | ODIR=_debug 171 | CFLAGS += -O0 -DDEBUG 172 | CFLAGS += -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -D_GLIBCXX_SANITIZE_VECTOR -D_LIBCPP_DEBUG=1 173 | else 174 | ODIR=_release 175 | CFLAGS += -O2 -DNDEBUG 176 | endif 177 | 178 | ifeq ($(VERBOSE), 1) 179 | VERBOSE_PREFIX= 180 | else 181 | VERBOSE_PREFIX=@ 182 | endif 183 | 184 | PROJ = $(ODIR)/$(NAME) 185 | $(info Building $(ODIR)/$(NAME)...) 186 | 187 | C_OBJS = ${CFILES:%.c=${ODIR}/%.o} 188 | OBJS = ${C_OBJS:%.cpp=${ODIR}/%.o} 189 | 190 | all: $(PROJ) 191 | 192 | $(ODIR)/$(NAME): $(OBJS) 193 | @echo "Linking $@..."; 194 | $(VERBOSE_PREFIX)$(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 195 | 196 | -include $(OBJS:.o=.d) 197 | 198 | ifneq ($(COMPILER),clang) 199 | $(ODIR)/src/imgui/imgui.o: CFLAGS += -Wno-stringop-truncation 200 | endif 201 | 202 | $(ODIR)/src/libtraceevent/src/event-parse.o: CFLAGS += -Wno-pedantic -Wno-format-nonliteral -Wno-sign-compare \ 203 | -Wno-shadow -Wno-implicit-function-declaration \ 204 | $(NO_MAYBE_UNINITIALIZED) $(NO_OLD_STYLE_DECLARATION) \ 205 | $(NO_FORMAT_NONLITERAL) $(NO_POINTER_SIGN) $(NO_COMPARE_DISTINCT_POINTER_TYPES) 206 | $(ODIR)/src/libtraceevent/src/trace-seq.o: CFLAGS += -Wno-pedantic 207 | $(ODIR)/src/libtraceevent/src/event-plugin.o: CFLAGS += -Wno-pedantic -Wno-shadow -Wno-implicit-function-declaration 208 | $(ODIR)/src/libtraceevent/src/trace-seq.o: CFLAGS += -Wno-pedantic -Wno-sign-compare 209 | $(ODIR)/src/libtraceevent/src/kbuffer-parse.o: CFLAGS += -Wno-pedantic -Wno-sign-compare $(NO_COMPARE_DISTINCT_POINTER_TYPES) 210 | $(ODIR)/src/libtraceevent/src/parse-utils.o: CFLAGS += -Wno-pedantic -Wno-implicit-function-declaration \ 211 | $(NO_FORMAT_NONLITERAL) $(NO_SUGGEST_ATTRIBUTE_FORMAT) 212 | $(ODIR)/src/libtraceevent/src/event-parse-api.o: CFLAGS += -Wno-pedantic 213 | $(ODIR)/src/imgui/imgui.o: CXXFLAGS += $(NO_STRINGOP_TRUNCATION) 214 | $(ODIR)/src/trace-cmd/trace-read.o: CXXFLAGS += $(NO_CLOBBERED) 215 | 216 | $(ODIR)/%.o: %.c Makefile 217 | $(VERBOSE_PREFIX)echo "---- $< ----"; 218 | @$(MKDIR) $(dir $@) 219 | $(VERBOSE_PREFIX)$(CC) -MMD -MP -std=gnu99 $(CFLAGS) -o $@ -c $< 220 | 221 | $(ODIR)/%.o: %.cpp Makefile 222 | $(VERBOSE_PREFIX)echo "---- $< ----"; 223 | @$(MKDIR) $(dir $@) 224 | $(VERBOSE_PREFIX)$(CXX) -MMD -MP -std=c++11 $(CFLAGS) $(CXXFLAGS) -o $@ -c $< 225 | 226 | .PHONY: clean 227 | 228 | clean: 229 | @echo Cleaning... 230 | $(VERBOSE_PREFIX)$(RM) $(PROJ) 231 | $(VERBOSE_PREFIX)$(RM) $(OBJS) 232 | $(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.d) 233 | $(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.dwo) 234 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GPUVis 2 | ====== 3 | 4 | Documentation 5 | ------------- 6 | https://github.com/mikesart/gpuvis/wiki 7 | 8 | Screenshot 9 | ---------- 10 | ![Alt text](images/gpuvis.jpg?raw=true "gpuvis") 11 | 12 | Credits 13 | ------- 14 | gpuvis code is [MIT](http://opensource.org/licenses/MIT) licensed. 15 | 16 | ``` 17 | Copyright 2019 Valve Software 18 | 19 | All Rights Reserved. 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in 29 | all copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 37 | THE SOFTWARE. 38 | ``` 39 | 40 | Simple DirectMedia Layer is [zlib licensed](https://www.libsdl.org/license.php) 41 | 42 | gl3w is [public domain](https://github.com/skaslev/gl3w) 43 | 44 | Dear ImGui was developed by [Omar Cornut](http://www.miracleworld.net) and every direct or indirect contributors to the GitHub. The early version of this library was developed with the support of [Media Molecule](http://www.mediamolecule.com) and first used internally on the game [Tearaway](http://tearaway.mediamolecule.com). 45 | 46 | Dear ImGui is licensed under the [MIT License](https://github.com/ocornut/imgui/blob/master/LICENSE) 47 | 48 | Uses [imgui_freetype](https://github.com/Vuhdo/imgui_freetype.git) by Vuhdo (Aleksei Skriabin) 49 | 50 | Embeds [ProggyClean.ttf and ProggyTiny.ttf](http://upperbounds.net) font by Tristan Grimmer (MIT license). 51 | 52 | Embeds [Roboto-Regular.ttf](https://fonts.google.com/specimen/Roboto) font by Christian Robertson (Apache License 2.0). 53 | Embeds [RobotoCondensed-Regular.ttf](https://fonts.google.com/specimen/Roboto+Condensed) font by Christian Robertson (Apache License 2.0). 54 | 55 | Embeds [DroidSans.ttf](http://www.google.com/fonts/specimen/Droid+Sans) font by Steve Matteson (Apache License 2.0). 56 | 57 | Uses [stb_textedit.h, stb_truetype.h, stb_rectpack.h](https://github.com/nothings/stb/) by Sean Barrett (public domain). 58 | 59 | trace-cmd is [GNU GPL v2](https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git) 60 | 61 | miniz is MIT licensed: [miniz](https://github.com/richgel999/miniz) 62 | 63 | stlini has e-mail author & credit license: [stlini](http://source.robertk.com/) 64 | 65 | ya_getopt is 2-clause BSD-style licensed: [ya_getopt](https://github.com/kubo/ya_getopt/blob/master/README.md) 66 | 67 | noc_file_dialog.h is MIT licensed: [noc](https://github.com/guillaumechereau/noc) 68 | 69 | ucm cmake macros are MIT licensed: [ucm](https://github.com/onqtam/ucm) 70 | 71 | SMHasher is MIT licensed: [SMHasher](https://github.com/aappleby/smhasher) 72 | 73 | {fmt} is 2-clause BSD licensed small, safe and fast formatting library: [fmt](http://fmtlib.net/latest/index.html) 74 | 75 | RapidJSON is MIT licensed: [RapidJSON](https://github.com/Tencent/rapidjson) 76 | -------------------------------------------------------------------------------- /cmake/FindSDL2.cmake: -------------------------------------------------------------------------------- 1 | 2 | # This module defines 3 | # SDL2_LIBRARY, the name of the library to link against 4 | # SDL2_FOUND, if false, do not try to link to SDL2 5 | # SDL2_INCLUDE_DIR, where to find SDL.h 6 | # 7 | # This module responds to the the flag: 8 | # SDL2_BUILDING_LIBRARY 9 | # If this is defined, then no SDL2main will be linked in because 10 | # only applications need main(). 11 | # Otherwise, it is assumed you are building an application and this 12 | # module will attempt to locate and set the the proper link flags 13 | # as part of the returned SDL2_LIBRARY variable. 14 | # 15 | # Don't forget to include SDLmain.h and SDLmain.m your project for the 16 | # OS X framework based version. (Other versions link to -lSDL2main which 17 | # this module will try to find on your behalf.) Also for OS X, this 18 | # module will automatically add the -framework Cocoa on your behalf. 19 | # 20 | # 21 | # Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration 22 | # and no SDL2_LIBRARY, it means CMake did not find your SDL2 library 23 | # (SDL2.dll, libsdl2.so, SDL2.framework, etc). 24 | # Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again. 25 | # Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value 26 | # as appropriate. These values are used to generate the final SDL2_LIBRARY 27 | # variable, but when these values are unset, SDL2_LIBRARY does not get created. 28 | # 29 | # 30 | # $SDL2DIR is an environment variable that would 31 | # correspond to the ./configure --prefix=$SDL2DIR 32 | # used in building SDL2. 33 | # l.e.galup 9-20-02 34 | # 35 | # Modified by Eric Wing. 36 | # Added code to assist with automated building by using environmental variables 37 | # and providing a more controlled/consistent search behavior. 38 | # Added new modifications to recognize OS X frameworks and 39 | # additional Unix paths (FreeBSD, etc). 40 | # Also corrected the header search path to follow "proper" SDL guidelines. 41 | # Added a search for SDL2main which is needed by some platforms. 42 | # Added a search for threads which is needed by some platforms. 43 | # Added needed compile switches for MinGW. 44 | # 45 | # On OSX, this will prefer the Framework version (if found) over others. 46 | # People will have to manually change the cache values of 47 | # SDL2_LIBRARY to override this selection or set the CMake environment 48 | # CMAKE_INCLUDE_PATH to modify the search paths. 49 | # 50 | # Note that the header path has changed from SDL2/SDL.h to just SDL.h 51 | # This needed to change because "proper" SDL convention 52 | # is #include "SDL.h", not . This is done for portability 53 | # reasons because not all systems place things in SDL2/ (see FreeBSD). 54 | 55 | #============================================================================= 56 | # Copyright 2003-2009 Kitware, Inc. 57 | # 58 | # Distributed under the OSI-approved BSD License (the "License"); 59 | # see accompanying file Copyright.txt for details. 60 | # 61 | # This software is distributed WITHOUT ANY WARRANTY; without even the 62 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 63 | # See the License for more information. 64 | #============================================================================= 65 | # (To distribute this file outside of CMake, substitute the full 66 | # License text for the above reference.) 67 | 68 | message("") 69 | 70 | SET(SDL2_SEARCH_PATHS 71 | ~/Library/Frameworks 72 | /Library/Frameworks 73 | /usr/local 74 | /usr 75 | /sw # Fink 76 | /opt/local # DarwinPorts 77 | /opt/csw # Blastwave 78 | /opt 79 | ${SDL2_PATH} 80 | ) 81 | 82 | FIND_PATH(SDL2_INCLUDE_DIR SDL.h 83 | HINTS 84 | $ENV{SDL2DIR} 85 | PATH_SUFFIXES include/SDL2 include 86 | PATHS ${SDL2_SEARCH_PATHS} 87 | ) 88 | 89 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 90 | set(PATH_SUFFIXES lib64 lib/x64 lib) 91 | else() 92 | set(PATH_SUFFIXES lib/x86 lib) 93 | endif() 94 | 95 | FIND_LIBRARY(SDL2_LIBRARY_TEMP 96 | NAMES SDL2 97 | HINTS 98 | $ENV{SDL2DIR} 99 | PATH_SUFFIXES ${PATH_SUFFIXES} 100 | PATHS ${SDL2_SEARCH_PATHS} 101 | ) 102 | 103 | IF(NOT SDL2_BUILDING_LIBRARY) 104 | IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") 105 | # Non-OS X framework versions expect you to also dynamically link to 106 | # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms 107 | # seem to provide SDL2main for compatibility even though they don't 108 | # necessarily need it. 109 | FIND_LIBRARY(SDL2MAIN_LIBRARY 110 | NAMES SDL2main 111 | HINTS 112 | $ENV{SDL2DIR} 113 | PATH_SUFFIXES ${PATH_SUFFIXES} 114 | PATHS ${SDL2_SEARCH_PATHS} 115 | ) 116 | ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") 117 | ENDIF(NOT SDL2_BUILDING_LIBRARY) 118 | 119 | # SDL2 may require threads on your system. 120 | # The Apple build may not need an explicit flag because one of the 121 | # frameworks may already provide it. 122 | # But for non-OSX systems, I will use the CMake Threads package. 123 | IF(NOT APPLE) 124 | FIND_PACKAGE(Threads) 125 | ENDIF(NOT APPLE) 126 | 127 | # MinGW needs an additional link flag, -mwindows 128 | # It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -mwindows 129 | IF(MINGW) 130 | SET(MINGW32_LIBRARY mingw32 "-mwindows" CACHE STRING "mwindows for MinGW") 131 | ENDIF(MINGW) 132 | 133 | IF(SDL2_LIBRARY_TEMP) 134 | # For SDL2main 135 | IF(NOT SDL2_BUILDING_LIBRARY) 136 | IF(SDL2MAIN_LIBRARY) 137 | SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP}) 138 | ENDIF(SDL2MAIN_LIBRARY) 139 | ENDIF(NOT SDL2_BUILDING_LIBRARY) 140 | 141 | # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. 142 | # CMake doesn't display the -framework Cocoa string in the UI even 143 | # though it actually is there if I modify a pre-used variable. 144 | # I think it has something to do with the CACHE STRING. 145 | # So I use a temporary variable until the end so I can set the 146 | # "real" variable in one-shot. 147 | IF(APPLE) 148 | SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa") 149 | ENDIF(APPLE) 150 | 151 | # For threads, as mentioned Apple doesn't need this. 152 | # In fact, there seems to be a problem if I used the Threads package 153 | # and try using this line, so I'm just skipping it entirely for OS X. 154 | IF(NOT APPLE) 155 | SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) 156 | ENDIF(NOT APPLE) 157 | 158 | # For MinGW library 159 | IF(MINGW) 160 | SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP}) 161 | ENDIF(MINGW) 162 | 163 | # Set the final string here so the GUI reflects the final state. 164 | SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found") 165 | # Set the temp variable to INTERNAL so it is not seen in the CMake GUI 166 | SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "") 167 | ENDIF(SDL2_LIBRARY_TEMP) 168 | 169 | message("") 170 | 171 | INCLUDE(FindPackageHandleStandardArgs) 172 | 173 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR) 174 | -------------------------------------------------------------------------------- /com.github.gpuvis.Gpuvis.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=gpuvis 3 | GenericName=GPU Trace Visualizer 4 | Comment=gpuvis desktop application 5 | Exec=gpuvis 6 | Icon=com.github.gpuvis.Gpuvis 7 | Terminal=false 8 | Type=Application 9 | Categories=Graphics; 10 | -------------------------------------------------------------------------------- /com.github.gpuvis.Gpuvis.metainfo.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | com.github.gpuvis.Gpuvis 4 | CC0-1.0 5 | MIT 6 | 7 | 8 | 9 | gpuvis 10 | A GPU Trace Visualizer 11 | 12 |

13 | Gpuvis is a Linux GPU profiler similar to GPUView on Windows. 14 | It is designed to work with trace-cmd captures and help track 15 | down Linux gpu and application performance issues. 16 |

17 |

18 | Gpuvis is open-source, so feel free to contribute new features! 19 |

20 |
21 | 22 | 23 | https://raw.githubusercontent.com/mikesart/gpuvis/master/images/gpuvis.jpg 24 | 25 | 26 | 27 | intense 28 | intense 29 | intense 30 | 31 | https://github.com/mikesart/gpuvis/wiki 32 | Michael Sartain 33 | mikesart@fastmail.com 34 |
35 | -------------------------------------------------------------------------------- /com.github.gpuvis.Gpuvis.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/gpuvis.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikesart/gpuvis/a1a1e173fd5cdca57a4b1085c1b1ee47dc9669c9/images/gpuvis.jpg -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('gpuvis', 'c', 'cpp', 2 | version : '1.0.0', 3 | default_options : [ 4 | 'warning_level=2', 5 | 'c_std=gnu99', 6 | 'cpp_std=c++11', 7 | 'default_library=static', 8 | ], 9 | license : 'MIT', 10 | meson_version : '>= 0.44.0') 11 | 12 | add_project_arguments(['-Wno-unused-parameter', 13 | '-Wno-sign-compare'], 14 | language: ['cpp']) 15 | 16 | if ['linux', 'sunos'].contains(host_machine.system()) 17 | add_project_arguments(['-D_LARGEFILE64_SOURCE=1', '-D_FILE_OFFSET_BITS=64'], 18 | language: ['c', 'cpp']) 19 | endif 20 | 21 | c = meson.get_compiler('c') 22 | cc = meson.get_compiler('cpp') 23 | 24 | all_deps = [ 25 | cc.find_library('dl', required: false), 26 | dependency('sdl2'), 27 | ] 28 | compile_flags = [ 29 | '-Wno-unused-parameter' 30 | ] 31 | 32 | if get_option('use_freetype') 33 | compile_flags += '-DUSE_FREETYPE=1' 34 | all_deps += dependency('freetype2') 35 | endif 36 | 37 | if get_option('use_gtk3') 38 | compile_flags += '-DUSE_GTK3=1' 39 | all_deps += dependency('gtk+-3.0') 40 | endif 41 | 42 | if get_option('use_i915_perf') 43 | compile_flags += '-DUSE_I915_PERF=1' 44 | all_deps += dependency('i915-perf', 45 | version : '>= 1.5.0') 46 | all_deps += dependency('xe-oa') 47 | endif 48 | 49 | if get_option('have_rapidjson') 50 | compile_flags += '-DHAVE_RAPIDJSON=1' 51 | all_deps += dependency('RapidJSON') 52 | endif 53 | 54 | gpuvis_files = files( 55 | 'src/gpuvis.cpp', 56 | 'src/gpuvis_graph.cpp', 57 | 'src/gpuvis_framemarkers.cpp', 58 | 'src/gpuvis_plots.cpp', 59 | 'src/gpuvis_graphrows.cpp', 60 | 'src/gpuvis_ftrace_print.cpp', 61 | 'src/gpuvis_i915_perfcounters.cpp', 62 | 'src/gpuvis_utils.cpp', 63 | 'src/gpuvis_etl.cpp', 64 | 'src/etl_utils.cpp', 65 | 'src/tdopexpr.cpp', 66 | 'src/ya_getopt.c', 67 | 'src/MurmurHash3.cpp', 68 | 'src/miniz.c', 69 | 'src/stlini.cpp', 70 | 'src/imgui/imgui_impl_sdl_gl3.cpp', 71 | 'src/imgui/imgui.cpp', 72 | 'src/imgui/imgui_demo.cpp', 73 | 'src/imgui/imgui_draw.cpp', 74 | 'src/imgui/imgui_freetype.cpp', 75 | 'src/GL/gl3w.c', 76 | 'src/i915-perf/i915-perf-read.cpp', 77 | 'src/libtraceevent/src/event-parse.c', 78 | 'src/libtraceevent/src/event-parse-api.c', 79 | 'src/libtraceevent/src/event-plugin.c', 80 | 'src/libtraceevent/src/kbuffer-parse.c', 81 | 'src/libtraceevent/src/parse-utils.c', 82 | 'src/libtraceevent/src/trace-seq.c', 83 | 'src/trace-cmd/trace-read.cpp', 84 | ) 85 | 86 | incdir = include_directories('src/libtraceevent/include') 87 | 88 | executable('gpuvis', gpuvis_files, 89 | c_args : compile_flags, 90 | cpp_args : compile_flags, 91 | dependencies : all_deps, 92 | install : true, 93 | include_directories : incdir) 94 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('use_freetype', type : 'boolean', value : 'true') 2 | option('use_gtk3', type : 'boolean', value : 'true') 3 | option('use_i915_perf', type : 'boolean', value : 'false') 4 | option('have_rapidjson', type : 'boolean', value : 'true') 5 | -------------------------------------------------------------------------------- /qtcreator/update_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PROJNAME=gpuvis 4 | 5 | BASEDIR=$(dirname $0) 6 | cd $BASEDIR 7 | 8 | DIRS=(..) 9 | 10 | # Create blah.creator file if it doesn't exist 11 | if [[ ! -f ${PROJNAME}.creator ]]; then echo -e "[General]\n" > ${PROJNAME}.creator; fi 12 | 13 | # Create our defines file 14 | DEFINES=$(cat <<'END_HEREDOC' 15 | #define __LINUX__ 1 16 | #define _GNU_SOURCE 1 17 | #define USE_FREETYPE 1 18 | #define GPUVIS_TRACE_IMPLEMENTATION 19 | #define NOC_FILE_DIALOG_IMPLEMENTATION 20 | #define NOC_FILE_DIALOG_GTK 21 | END_HEREDOC 22 | ) 23 | echo "${DEFINES}" > ${PROJNAME}.config 24 | 25 | > ${PROJNAME}.files 26 | for i in ${DIRS[@]}; do 27 | echo Checking ${i} 28 | 29 | find ${i} -type f -iregex '.*\.\(c\|cxx\|cpp\|h\|lpp\|ypp\|sh\|inl\|txt\|scons\|py\)$' -or -iname Makefile -or -iname SConstruct >> ${PROJNAME}.files 30 | done 31 | 32 | 33 | if [ -d /usr/include/SDL2 ]; then 34 | find /usr/include/SDL2 -iname "*.h" >> ${PROJNAME}.files 35 | fi 36 | 37 | fgrep -i --color=never ".h" *.files | xargs -I{} readlink -f {} | xargs -I{} dirname {} | sort | uniq > ${PROJNAME}.includes 38 | 39 | wc -l ${PROJNAME}.files 40 | wc -l ${PROJNAME}.includes 41 | -------------------------------------------------------------------------------- /sample/Makefile: -------------------------------------------------------------------------------- 1 | NAME = glxgears 2 | 3 | CFG ?= release 4 | ifeq ($(CFG), debug) 5 | ASAN ?= 1 6 | endif 7 | 8 | LD = $(CC) 9 | RM = rm -f 10 | MKDIR = mkdir -p 11 | VERBOSE ?= 0 12 | 13 | COMPILER = $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc) 14 | 15 | WARNINGS = -Wall -Wextra -Wpedantic -Wmissing-include-dirs -Wformat=2 -Wshadow -Wno-unused-parameter -Wno-missing-field-initializers 16 | ifneq ($(COMPILER),clang) 17 | WARNINGS += -Wsuggest-attribute=format 18 | endif 19 | 20 | CFLAGS = $(WARNINGS) -march=native -fno-exceptions -gdwarf-4 -g2 21 | CXXFLAGS = -fno-rtti -Woverloaded-virtual 22 | LDFLAGS = -march=native -gdwarf-4 -g2 -Wl,--build-id=sha1 23 | LIBS = -Wl,--no-as-needed -lGL -lX11 -lm -lpthread -lstdc++ 24 | 25 | ifeq (, $(filter-out Linux SunOS,$(shell uname -s))) 26 | CFLAGS += -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 27 | LIBS += -ldl 28 | endif 29 | 30 | CFILES = \ 31 | glxgears.c 32 | 33 | ifeq ($(ASAN), 1) 34 | # https://gcc.gnu.org/gcc-5/changes.html 35 | # -fsanitize=float-cast-overflow: check that the result of floating-point type to integer conversions do not overflow; 36 | # -fsanitize=alignment: enable alignment checking, detect various misaligned objects; 37 | # -fsanitize=vptr: enable checking of C++ member function calls, member accesses and some conversions between pointers to base and derived classes, detect if the referenced object does not have the correct dynamic type. 38 | ASAN_FLAGS = -fno-omit-frame-pointer -fno-optimize-sibling-calls 39 | ASAN_FLAGS += -fsanitize=address # fast memory error detector (heap, stack, global buffer overflow, and use-after free) 40 | ASAN_FLAGS += -fsanitize=leak # detect leaks 41 | ASAN_FLAGS += -fsanitize=undefined # fast undefined behavior detector 42 | ASAN_FLAGS += -fsanitize=float-divide-by-zero # detect floating-point division by zero; 43 | ASAN_FLAGS += -fsanitize=bounds # enable instrumentation of array bounds and detect out-of-bounds accesses; 44 | ASAN_FLAGS += -fsanitize=object-size # enable object size checking, detect various out-of-bounds accesses. 45 | CFLAGS += $(ASAN_FLAGS) 46 | LDFLAGS += $(ASAN_FLAGS) 47 | endif 48 | 49 | ifeq ($(CFG), debug) 50 | ODIR=_debug 51 | CFLAGS += -O0 -DDEBUG 52 | CFLAGS += -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC 53 | else 54 | ODIR=_release 55 | CFLAGS += -O2 -DNDEBUG 56 | endif 57 | 58 | ifeq ($(VERBOSE), 1) 59 | VERBOSE_PREFIX= 60 | else 61 | VERBOSE_PREFIX=@ 62 | endif 63 | 64 | PROJ = $(ODIR)/$(NAME) 65 | $(info Building $(ODIR)/$(NAME)...) 66 | 67 | C_OBJS = ${CFILES:%.c=${ODIR}/%.o} 68 | OBJS = ${C_OBJS:%.cpp=${ODIR}/%.o} 69 | 70 | all: $(PROJ) 71 | 72 | $(ODIR)/$(NAME): $(OBJS) 73 | @echo "Linking $@..."; 74 | $(VERBOSE_PREFIX)$(LD) $(LDFLAGS) $^ $(LIBS) -o $@ 75 | 76 | -include $(OBJS:.o=.d) 77 | 78 | $(ODIR)/%.o: %.c Makefile 79 | $(VERBOSE_PREFIX)echo "---- $< ----"; 80 | @$(MKDIR) $(dir $@) 81 | $(VERBOSE_PREFIX)$(CC) -MMD -MP -std=gnu99 $(CFLAGS) -o $@ -c $< 82 | 83 | $(ODIR)/%.o: %.cpp Makefile 84 | $(VERBOSE_PREFIX)echo "---- $< ----"; 85 | @$(MKDIR) $(dir $@) 86 | $(VERBOSE_PREFIX)$(CXX) -MMD -MP -std=c++11 $(CFLAGS) $(CXXFLAGS) -o $@ -c $< 87 | 88 | .PHONY: clean 89 | 90 | clean: 91 | @echo Cleaning... 92 | $(VERBOSE_PREFIX)$(RM) $(PROJ) 93 | $(VERBOSE_PREFIX)$(RM) $(OBJS) 94 | $(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.d) 95 | -------------------------------------------------------------------------------- /sample/trace-cmd-capture.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TRACE_ENABLED=0 4 | 5 | if [ -r /sys/kernel/tracing/tracing_on ]; then 6 | read -N 1 TRACE_ENABLED < /sys/kernel/tracing/tracing_on 7 | fi 8 | 9 | if [ ${TRACE_ENABLED} -eq 0 ]; then 10 | echo -e "ERROR: Tracing is disabled\n" 11 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 12 | ${SCRIPT_DIR}/trace-cmd-status.sh 13 | exit -1 14 | fi 15 | 16 | DATE=$(date +%m-%d-%Y_%H-%M-%S) 17 | 18 | # Stop tracer from recording more data 19 | CMD="trace-cmd stop" 20 | echo ${CMD} 21 | $CMD 22 | 23 | # Extract i915-perf trace 24 | CMD="i915-perf-control -d trace_${DATE}.i915-dat" 25 | echo ${CMD} 26 | $CMD 27 | 28 | # Extract xe-perf trace 29 | CMD="xe-perf-control -d trace_${DATE}.xe-dat" 30 | echo ${CMD} 31 | $CMD 32 | 33 | # Extract trace 34 | CMD="trace-cmd extract -k -o trace_${DATE}.dat" 35 | echo ${CMD} 36 | $CMD 37 | 38 | # Restart recording 39 | CMD="trace-cmd restart" 40 | echo ${CMD} 41 | $CMD 42 | -------------------------------------------------------------------------------- /sample/trace-cmd-command.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get path our script is running in 4 | SCRIPT=$(realpath -s $0) 5 | SCRIPTPATH=$(dirname $SCRIPT) 6 | 7 | # Dirs to search for gpuvis binary in 8 | GPUVISDIRS=(../_release ../_debug ../build) 9 | 10 | COMMAND="$@" 11 | if [ -z "${COMMAND}" ]; then 12 | echo "USAGE: ./trace-cmd-trace-command.sh [command ...]" 13 | exit 0 14 | fi 15 | 16 | TRACECMD=$(which trace-cmd) 17 | if [ -z "${TRACECMD}" ]; then 18 | echo "ERROR: Could not locate trace-cmd binary" 19 | exit -1 20 | fi 21 | 22 | if [ ! -u "${TRACECMD}" ]; then 23 | echo "ERROR: ${TRACECMD} setuid bit not set. Run trace-cmd-setup.sh?" 24 | exit -1 25 | fi 26 | 27 | # Try to find a gpuvis binary 28 | GPUVISBIN=$(which gpuvis) 29 | if [ -z "${GPUVISBIN}" ]; then 30 | for i in ${GPUVISDIRS[@]}; do 31 | if [ -x "${SCRIPTPATH}/${i}/gpuvis" ]; then 32 | GPUVISBIN="${SCRIPTPATH}/${i}/gpuvis" 33 | break 34 | fi 35 | done 36 | fi 37 | 38 | EVENTS= 39 | 40 | # https://github.com/mikesart/gpuvis/wiki/TechDocs-Linux-Scheduler 41 | EVENTS+=" -e sched:sched_switch" 42 | EVENTS+=" -e sched:sched_process_fork" 43 | EVENTS+=" -e sched:sched_process_exec" 44 | EVENTS+=" -e sched:sched_process_exit" 45 | 46 | EVENTS+=" -e drm:drm_vblank_event" 47 | EVENTS+=" -e drm:drm_vblank_event_queued" 48 | EVENTS+=" -e drm:drm_vblank_event_delivered" 49 | 50 | # https://github.com/mikesart/gpuvis/wiki/TechDocs-AMDGpu 51 | EVENTS+=" -e amdgpu:amdgpu_vm_flush" 52 | EVENTS+=" -e amdgpu:amdgpu_cs_ioctl" 53 | EVENTS+=" -e amdgpu:amdgpu_sched_run_job" 54 | EVENTS+=" -e *fence:*fence_signaled" 55 | 56 | # https://github.com/mikesart/gpuvis/wiki/TechDocs-Intel 57 | # 58 | # NOTE: the i915_gem_request_submit, i915_gem_request_in, i915_gem_request_out 59 | # tracepoints require the CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS Kconfig option to 60 | # be enabled. 61 | EVENTS+=" -e i915:i915_flip_request" 62 | EVENTS+=" -e i915:i915_flip_complete" 63 | EVENTS+=" -e i915:intel_gpu_freq_change" 64 | EVENTS+=" -e i915:i915_gem_request_add" 65 | EVENTS+=" -e i915:i915_gem_request_submit" 66 | EVENTS+=" -e i915:i915_gem_request_in" 67 | EVENTS+=" -e i915:i915_gem_request_out" 68 | EVENTS+=" -e i915:i915_gem_request_queue" 69 | EVENTS+=" -e i915:intel_engine_notify" 70 | EVENTS+=" -e i915:i915_gem_request_wait_begin" 71 | EVENTS+=" -e i915:i915_gem_request_wait_end" 72 | 73 | EVENTS+=" -e i915:i915_request_add" 74 | EVENTS+=" -e i915:i915_request_submit" 75 | EVENTS+=" -e i915:i915_request_in" 76 | EVENTS+=" -e i915:i915_request_out" 77 | EVENTS+=" -e i915:i915_request_queue" 78 | EVENTS+=" -e i915:i915_request_wait_begin" 79 | EVENTS+=" -e i915:i915_request_wait_end" 80 | EVENTS+=" -e i915:i915_request_retire" 81 | EVENTS+=" -e i915:i915_request_execute" 82 | 83 | EVENTS+=" -e i915:i915_pipe_update_vblank_evaded" 84 | 85 | DATE=$(date +%m-%d-%Y_%H-%M-%S) 86 | TRACEFILE=trace_${DATE}.dat 87 | 88 | echo 89 | CMD="trace-cmd record -C mono -b 8000 -D -o ${TRACEFILE} -i ${EVENTS} ${COMMAND}" 90 | echo $CMD 91 | $CMD 92 | 93 | # Open trace in gpuvis if we found it, otherwise trace-cmd report 94 | if [ -x "${GPUVISBIN}" ]; then 95 | CMD="${GPUVISBIN} ${TRACEFILE}" 96 | else 97 | CMD="trace-cmd report -l ${TRACEFILE} | less" 98 | fi 99 | 100 | echo 101 | echo $CMD 102 | $CMD 103 | -------------------------------------------------------------------------------- /sample/trace-cmd-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | ESC="$(printf '\033')" 6 | NORMAL="${ESC}[0m" 7 | YELLOW="${ESC}[1;33m" 8 | GREEN="${ESC}[32;1m" 9 | 10 | function spewTraceStatus() { 11 | echo "Tracing status:" 12 | 13 | OWNER="$(stat -c %U ${TRACECMD})" 14 | 15 | if [ -u "${TRACECMD}" ]; then 16 | echo " ${TRACECMD} ${GREEN}(setuid set for '${OWNER}')${NORMAL}" 17 | else 18 | echo " ${TRACECMD} ${YELLOW}(setuid not set)${NORMAL}" 19 | fi 20 | 21 | if egrep -q "${TRACEFS} .*tracefs" /proc/mounts; then 22 | echo " ${TRACEFS} ${GREEN}(mounted)${NORMAL}" 23 | else 24 | echo " ${TRACEFS} ${YELLOW}(not mounted)${NORMAL}" 25 | fi 26 | 27 | if [ -w "${TRACEFS}/trace_marker" ]; then 28 | echo " ${TRACEFS}/trace_marker ${GREEN}(writable)${NORMAL}" 29 | else 30 | echo " ${TRACEFS}/trace_marker ${YELLOW}(not writable)${NORMAL}" 31 | fi 32 | } 33 | 34 | ROOT_CMDS= 35 | 36 | # note: trace-cmd mounts tracefs on /sys/kernel/tracing IFF it's not already mounted elsewhere; 37 | # these scripts assume it's always /sys/kernel/tracing so we explicitly try to mount it 38 | # there (it's safe to have it mounted in multiple places) 39 | # from /proc/mounts: 40 | # nodev /sys/kernel/tracing tracefs rw,relatime 0 0 41 | TRACEFS="/sys/kernel/tracing" 42 | 43 | TRACECMD= 44 | 45 | # Using command -v to get trace-cmd path: 46 | # https://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script 47 | if [ -x "$(command -v trace-cmd)" ]; then 48 | TRACECMD=$(readlink -f "$(command -v trace-cmd)") 49 | fi 50 | 51 | if [ -z "${TRACECMD}" ]; then 52 | echo "ERROR: Could not locate trace-cmd binary" 53 | exit -1 54 | fi 55 | 56 | if [ -u "${TRACECMD}" ] && [ "$(stat -c %U ${TRACECMD})" == "root" ] ; then 57 | # trace-cmd owner and setuid set 58 | : 59 | else 60 | # trace-cmd owner or setuid not set 61 | ROOT_CMDS+="# Make sure root owns trace-cmd\n" 62 | ROOT_CMDS+="chown root:root ${TRACECMD}\n\n" 63 | 64 | ROOT_CMDS+="# Add setuid bit to trace-cmd binary\n" 65 | ROOT_CMDS+="chmod u+s ${TRACECMD}\n\n" 66 | fi 67 | 68 | # Check if tracefs dir is mounted 69 | if ! egrep -q " ${TRACEFS} .*tracefs" /proc/mounts; then 70 | ROOT_CMDS+="# Mounting ${TRACEFS}...\n" 71 | ROOT_CMDS+="mount -t tracefs nodev ${TRACEFS}\n\n" 72 | fi 73 | 74 | if [ -w "${TRACEFS}/trace_marker" ]; then 75 | # trace_marker exists and is writable 76 | : 77 | else 78 | # trace_marker not writable or tracefs still to be mounted 79 | ROOT_CMDS+="# Add tracefs execute/search permissions\n" 80 | ROOT_CMDS+="chmod 0755 \"${TRACEFS}\"\n\n" 81 | 82 | ROOT_CMDS+="# Add trace_marker write permissions \n" 83 | ROOT_CMDS+="chmod 0222 \"${TRACEFS}/trace_marker\"\n" 84 | fi 85 | 86 | # Enable i915/xe perf to collect GPU data. 87 | ROOT_CMDS+="sysctl --ignore dev.i915.perf_stream_paranoid=0" 88 | ROOT_CMDS+="sysctl --ignore dev.xe.perf_stream_paranoid=0" 89 | 90 | if [ -z "${ROOT_CMDS}" ]; then 91 | : 92 | else 93 | ROOT_CMDS_FILE="$(mktemp)" 94 | 95 | echo "if ! [ \"\$UID\" -eq 0 ]; then" > ${ROOT_CMDS_FILE} 96 | echo " echo Enter your password to setup trace-cmd permissions:" >> ${ROOT_CMDS_FILE} 97 | echo " echo sudo bash \"\$0\"" >> ${ROOT_CMDS_FILE} 98 | echo " exec sudo bash \"\$0\"" >> ${ROOT_CMDS_FILE} 99 | echo "fi" >> ${ROOT_CMDS_FILE} 100 | echo "" >> ${ROOT_CMDS_FILE} 101 | 102 | echo -e ${ROOT_CMDS} >> ${ROOT_CMDS_FILE} 103 | 104 | echo "" 105 | echo "trace-cmd root initialization file (${ROOT_CMDS_FILE}):" 106 | echo "---------------------------------" 107 | cat -s -n "${ROOT_CMDS_FILE}" 108 | echo "" 109 | 110 | if [ "$UID" -eq 0 ]; then 111 | echo "bash ${ROOT_CMDS_FILE}" 112 | bash ${ROOT_CMDS_FILE} 113 | else 114 | # Do something ~ Baldur does in RenderDoc 115 | # https://github.com/baldurk/renderdoc/blob/v0.x/qrenderdoc/Code/QRDUtils.cpp#L826 116 | if [ -x "$(command -v pkexec)" ]; then 117 | echo "pkexec bash ${ROOT_CMDS_FILE}" 118 | pkexec bash ${ROOT_CMDS_FILE} 119 | elif [ -x "$(command -v kdesudo)" ]; then 120 | echo "kdesudo bash ${ROOT_CMDS_FILE}" 121 | kdesudo -c "bash ${ROOT_CMDS_FILE}" 122 | elif [ -x "$(command -v gksudo)" ]; then 123 | echo gksudo --message \"Setup trace-cmd permissions\" \"bash ${ROOT_CMDS_FILE}\" 124 | gksudo --message "Setup trace-cmd permissions" "bash ${ROOT_CMDS_FILE}" 125 | elif [ -x "$(command -v beesu)" ]; then 126 | echo beesu bash ${ROOT_CMDS_FILE} 127 | beesu bash ${ROOT_CMDS_FILE} 128 | elif [ -x "$(command -v xterm)" ]; then 129 | echo xterm -e "bash ${ROOT_CMDS_FILE}" 130 | xterm -e "bash ${ROOT_CMDS_FILE}; sleep 5" 131 | else 132 | echo "ERROR: Can't execute initilization file as root." 133 | fi 134 | fi 135 | 136 | echo 137 | rm ${ROOT_CMDS_FILE} 138 | fi 139 | 140 | spewTraceStatus 141 | -------------------------------------------------------------------------------- /sample/trace-cmd-start-tracing.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TRACECMD=$(which trace-cmd) 4 | 5 | if [ -z "${TRACECMD}" ]; then 6 | echo "ERROR: Could not locate trace-cmd binary" 7 | exit -1 8 | fi 9 | 10 | if [ ! -u "${TRACECMD}" ]; then 11 | echo "ERROR: ${TRACECMD} setuid bit not set. Run trace-cmd-setup.sh?" 12 | exit -1 13 | fi 14 | 15 | if [ "${USE_I915_PERF}" ]; then 16 | if [ -z "${I915_PERF_METRIC}" ]; then 17 | echo "WARNING: Missing I915_PERF_METRIC value. Using default value 'RenderBasic'." 18 | I915_PERF_METRIC="RenderBasic" 19 | fi 20 | 21 | if [ -z "${I915_PERF_ENGINE_CLASS}" ]; then 22 | echo "WARNING: Missing I915_PERF_ENGINE_CLASS value. Using default value 0 (Render Class)." 23 | I915_PERF_ENGINE_CLASS=0 24 | fi 25 | 26 | if [ -z "${I915_PERF_ENGINE_INSTANCE}" ]; then 27 | echo "WARNING: Missing I915_PERF_ENGINE_INSTANCE value. Using default instance 0." 28 | I915_PERF_ENGINE_INSTANCE=0 29 | fi 30 | fi 31 | 32 | if [ "${USE_XE_PERF}" ]; then 33 | if [ -z "${XE_PERF_METRIC}" ]; then 34 | echo "WARNING: Missing XE_PERF_METRIC value. Using default value 'RenderBasic'." 35 | XE_PERF_METRIC="RenderBasic" 36 | fi 37 | 38 | if [ -z "${XE_PERF_ENGINE_CLASS}" ]; then 39 | echo "WARNING: Missing XE_PERF_ENGINE_CLASS value. Using default value 0 (Render Class)." 40 | XE_PERF_ENGINE_CLASS=0 41 | fi 42 | 43 | if [ -z "${XE_PERF_ENGINE_INSTANCE}" ]; then 44 | echo "WARNING: Missing XE_PERF_ENGINE_INSTANCE value. Using default instance 0." 45 | XE_PERF_ENGINE_INSTANCE=0 46 | fi 47 | fi 48 | 49 | EVENTS= 50 | 51 | # https://github.com/mikesart/gpuvis/wiki/TechDocs-Linux-Scheduler 52 | EVENTS+=" -e sched:sched_switch" 53 | EVENTS+=" -e sched:sched_process_fork" 54 | EVENTS+=" -e sched:sched_process_exec" 55 | EVENTS+=" -e sched:sched_process_exit" 56 | 57 | EVENTS+=" -e drm:drm_vblank_event" 58 | EVENTS+=" -e drm:drm_vblank_event_queued" 59 | EVENTS+=" -e drm:drm_vblank_event_delivered" 60 | 61 | # https://github.com/mikesart/gpuvis/wiki/TechDocs-AMDGpu 62 | EVENTS+=" -e amdgpu:amdgpu_vm_flush" 63 | EVENTS+=" -e amdgpu:amdgpu_cs_ioctl" 64 | EVENTS+=" -e amdgpu:amdgpu_sched_run_job" 65 | EVENTS+=" -e *fence:*fence_signaled" 66 | 67 | # https://github.com/mikesart/gpuvis/wiki/TechDocs-Intel 68 | # 69 | # NOTE: the i915_gem_request_submit, i915_gem_request_in, i915_gem_request_out 70 | # tracepoints require the CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS Kconfig option to 71 | # be enabled. 72 | EVENTS+=" -e i915:i915_flip_request" 73 | EVENTS+=" -e i915:i915_flip_complete" 74 | EVENTS+=" -e i915:intel_gpu_freq_change" 75 | EVENTS+=" -e i915:i915_gem_request_add" 76 | EVENTS+=" -e i915:i915_gem_request_submit" 77 | EVENTS+=" -e i915:i915_gem_request_in" 78 | EVENTS+=" -e i915:i915_gem_request_out" 79 | EVENTS+=" -e i915:i915_gem_request_queue" 80 | EVENTS+=" -e i915:intel_engine_notify" 81 | EVENTS+=" -e i915:i915_gem_request_wait_begin" 82 | EVENTS+=" -e i915:i915_gem_request_wait_end" 83 | 84 | EVENTS+=" -e i915:i915_request_add" 85 | EVENTS+=" -e i915:i915_request_submit" 86 | EVENTS+=" -e i915:i915_request_in" 87 | EVENTS+=" -e i915:i915_request_out" 88 | EVENTS+=" -e i915:i915_request_queue" 89 | EVENTS+=" -e i915:i915_request_wait_begin" 90 | EVENTS+=" -e i915:i915_request_wait_end" 91 | EVENTS+=" -e i915:i915_request_retire" 92 | EVENTS+=" -e i915:i915_request_execute" 93 | 94 | EVENTS+=" -e i915:i915_pipe_update_vblank_evaded" 95 | 96 | CMD="trace-cmd reset" 97 | echo $CMD 98 | $CMD 99 | 100 | CLOCK=mono 101 | 102 | echo 103 | CMD="trace-cmd start -C ${CLOCK} -b 8000 -D -i ${EVENTS}" 104 | echo $CMD 105 | $CMD 106 | 107 | if [ -e /tmp/.i915-perf-record ]; then 108 | CMD="i915-perf-control -q" 109 | echo $CMD 110 | $CMD 111 | fi 112 | 113 | if [ -e /tmp/.xe-perf-record ]; then 114 | CMD="xe-perf-control -q" 115 | echo $CMD 116 | $CMD 117 | fi 118 | 119 | if [ "${USE_I915_PERF}" ]; then 120 | CMD="i915-perf-recorder -m ${I915_PERF_METRIC} -s 8000 -k ${CLOCK} -e ${I915_PERF_ENGINE_CLASS} -i ${I915_PERF_ENGINE_INSTANCE}" 121 | echo $CMD 122 | $CMD & 123 | fi 124 | 125 | if [ "${USE_XE_PERF}" ]; then 126 | CMD="xe-perf-recorder -m ${XE_PERF_METRIC} -s 8000 -k ${CLOCK} -e ${XE_PERF_ENGINE_CLASS} -i ${XE_PERF_ENGINE_INSTANCE}" 127 | echo $CMD 128 | $CMD & 129 | fi 130 | 131 | echo 132 | 133 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 134 | ${SCRIPT_DIR}/trace-cmd-status.sh 135 | -------------------------------------------------------------------------------- /sample/trace-cmd-status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CMD="trace-cmd stat" 4 | echo $CMD 5 | $CMD 6 | 7 | # 8 | # cat /sys/kernel/tracing/per_cpu/cpu0/stats 9 | # entries: 5 10 | # overrun: 0 11 | # commit overrun: 0 12 | # bytes: 224 13 | # oldest event ts: 96955.082688 14 | # now ts: 97157.747457 15 | # dropped events: 0 16 | # read events: 0 17 | # 18 | # Ring buffer stats: 19 | # Entries: The number of events that are still in the buffer. 20 | # Overrun: The number of lost events due to overwriting when the buffer was full. 21 | # Commit overrun: Should always be zero. 22 | # This gets set if so many events happened within a nested event (ring buffer is re-entrant), 23 | # that it fills the buffer and starts dropping events. 24 | # Bytes: Bytes actually read (not overwritten). 25 | # Oldest event ts: The oldest timestamp in the buffer. 26 | # Now ts: The current timestamp. 27 | # Dropped events: Events lost due to overwrite option being off. 28 | # Read events: The number of events read. 29 | # 30 | if [ -r "/sys/kernel/tracing/per_cpu/cpu0/stats" ]; then 31 | 32 | STAT_FILES=() 33 | 34 | for (( i = 0 ; i <= 256 ; i++ )) ; do 35 | FILE="/sys/kernel/tracing/per_cpu/cpu${i}/stats" 36 | if [ ! -r ${FILE} ]; then 37 | break 38 | fi 39 | 40 | STAT_FILES+=($FILE) 41 | done 42 | 43 | awk 'BEGIN { time = 0; entries = 0; overrun = 0 } 44 | { 45 | if ( $0 ~ '/^entries\:/' ) 46 | entries = $2 47 | if ( $0 ~ '/^overrun\:/' ) 48 | overrun = $2 49 | if ( $0 ~ '/^oldest\ event\ ts\:/' ) 50 | time = (float)$4 51 | if ( $0 ~ '/^now\ ts\:/' ) { 52 | time = (float)$3 - time 53 | if ( entries == 0 ) 54 | printf "%s entries:%u\n", FILENAME, entries 55 | else 56 | printf "%s entries:%u overrun:%u time:%f sec\n", FILENAME, entries, overrun, time 57 | time = 0; 58 | entries = 0; 59 | overrun = 0; 60 | } 61 | }' ${STAT_FILES[@]} 62 | 63 | fi 64 | -------------------------------------------------------------------------------- /sample/trace-cmd-stop-tracing.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CMD="trace-cmd reset" 4 | echo $CMD 5 | $CMD 6 | 7 | CMD="trace-cmd snapshot -f" 8 | echo $CMD 9 | $CMD 10 | 11 | if [ "${USE_I915_PERF} " ]; then 12 | CMD="i915-perf-control -q" 13 | echo $CMD 14 | $CMD 15 | fi 16 | 17 | if [ "${USE_XE_PERF} " ]; then 18 | CMD="xe-perf-control -q" 19 | echo $CMD 20 | $CMD 21 | fi 22 | 23 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 24 | ${SCRIPT_DIR}/trace-cmd-status.sh 25 | -------------------------------------------------------------------------------- /src/MurmurHash3.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // MurmurHash3 was written by Austin Appleby, and is placed in the public 3 | // domain. The author hereby disclaims copyright to this source code. 4 | 5 | // From: https://github.com/aappleby/smhasher/wiki 6 | 7 | #ifndef _MURMURHASH3_H_ 8 | #define _MURMURHASH3_H_ 9 | 10 | //----------------------------------------------------------------------------- 11 | // Platform-specific functions and macros 12 | 13 | // Microsoft Visual Studio 14 | 15 | #if defined(_MSC_VER) && (_MSC_VER < 1600) 16 | 17 | typedef unsigned char uint8_t; 18 | typedef unsigned int uint32_t; 19 | typedef unsigned __int64 uint64_t; 20 | 21 | // Other compilers 22 | 23 | #else // defined(_MSC_VER) 24 | 25 | #include 26 | 27 | #endif // !defined(_MSC_VER) 28 | 29 | //----------------------------------------------------------------------------- 30 | uint32_t MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed ); 31 | 32 | void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out ); 33 | 34 | void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out ); 35 | //----------------------------------------------------------------------------- 36 | 37 | #endif // _MURMURHASH3_H_ 38 | -------------------------------------------------------------------------------- /src/etl_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Valve Software 3 | * 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef ETL_UTILS_H_ 26 | #define ETL_UTILS_H_ 27 | 28 | #ifdef _WIN32 29 | 30 | #include 31 | #include 32 | 33 | // This enum is in the MS docs that references a header called Dxetwevt.h, 34 | // but that header is nowhere to be found. 35 | typedef enum _DXGKETW_QUEUE_PACKET_TYPE { 36 | DXGKETW_RENDER_COMMAND_BUFFER = 0, 37 | DXGKETW_DEFERRED_COMMAND_BUFFER = 1, 38 | DXGKETW_SYSTEM_COMMAND_BUFFER = 2, 39 | DXGKETW_MMIOFLIP_COMMAND_BUFFER = 3, 40 | DXGKETW_WAIT_COMMAND_BUFFER = 4, 41 | DXGKETW_SIGNAL_COMMAND_BUFFER = 5, 42 | DXGKETW_DEVICE_COMMAND_BUFFER = 6, 43 | DXGKETW_SOFTWARE_COMMAND_BUFFER = 7 44 | } DXGKETW_QUEUE_PACKET_TYPE; 45 | 46 | DWORD DumpEventMetadataField( TRACE_EVENT_INFO* pinfo, DWORD i, USHORT indent ); 47 | DWORD DumpEventMetadata( PTRACE_EVENT_INFO info ); 48 | DWORD DumpEvent( PEVENT_RECORD pEvent, PTRACE_EVENT_INFO pInfo ); 49 | DWORD DumpPropertiesIndex( PEVENT_RECORD pEvent, PTRACE_EVENT_INFO pInfo, USHORT i, LPWSTR pStructureName, USHORT StructIndex ); 50 | DWORD DumpProperties( PEVENT_RECORD pEvent, PTRACE_EVENT_INFO pInfo ); 51 | DWORD FormatAndPrintData( PEVENT_RECORD pEvent, USHORT InType, USHORT OutType, PBYTE pData, DWORD DataSize, PEVENT_MAP_INFO pMapInfo ); 52 | void PrintMapString( PEVENT_MAP_INFO pMapInfo, PBYTE pData ); 53 | DWORD GetPropertyLength( PEVENT_RECORD pEvent, PTRACE_EVENT_INFO pInfo, USHORT i, PUSHORT PropertyLength ); 54 | DWORD GetArraySize( PEVENT_RECORD pEvent, PTRACE_EVENT_INFO pInfo, USHORT i, PUSHORT ArraySize ); 55 | DWORD GetMapInfo( PEVENT_RECORD pEvent, LPWSTR pMapName, DWORD DecodingSource, PEVENT_MAP_INFO & pMapInfo ); 56 | void RemoveTrailingSpace( PEVENT_MAP_INFO pMapInfo ); 57 | #endif //_WIN32 58 | 59 | #endif // ETL_UTILS_H_ 60 | -------------------------------------------------------------------------------- /src/fnv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fnv - Fowler/Noll/Vo- hash code 3 | * 4 | * The basis of this hash algorithm was taken from an idea sent 5 | * as reviewer comments to the IEEE POSIX P1003.2 committee by: 6 | * 7 | * Phong Vo (http://www.research.att.com/info/kpv/) 8 | * Glenn Fowler (http://www.research.att.com/~gsf/) 9 | * 10 | * In a subsequent ballot round: 11 | * 12 | * Landon Curt Noll (http://www.isthe.com/chongo/) 13 | * 14 | * improved on their algorithm. Some people tried this hash 15 | * and found that it worked rather well. In an EMail message 16 | * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash. 17 | * 18 | * FNV hashes are designed to be fast while maintaining a low 19 | * collision rate. The FNV speed allows one to quickly hash lots 20 | * of data while maintaining a reasonable collision rate. See: 21 | * 22 | * http://www.isthe.com/chongo/tech/comp/fnv/index.html 23 | * 24 | * for more details as well as other forms of the FNV hash. 25 | * 26 | *** 27 | * 28 | * To use the recommended 32 bit FNV-1 hash, pass FNV1_32_INIT as the 29 | * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str(). 30 | * 31 | * To use the recommended 64 bit FNV-1 hash, pass FNV1_64_INIT as the 32 | * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str(). 33 | * 34 | * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the 35 | * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str(). 36 | * 37 | * To use the recommended 64 bit FNV-1a hash, pass FNV1A_64_INIT as the 38 | * Fnv64_t hashval argument to fnv_64a_buf() or fnv_64a_str(). 39 | * 40 | *** 41 | * 42 | * Please do not copyright this code. This code is in the public domain. 43 | * 44 | * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 45 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 46 | * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR 47 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 48 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 49 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 50 | * PERFORMANCE OF THIS SOFTWARE. 51 | * 52 | * By: 53 | * chongo /\oo/\ 54 | * http://www.isthe.com/chongo/ 55 | * 56 | * Share and Enjoy! :-) 57 | */ 58 | 59 | #if !defined(__FNV_H__) 60 | #define __FNV_H__ 61 | 62 | #include 63 | 64 | #define FNV_VERSION "5.0.2" /* @(#) FNV Version */ 65 | 66 | 67 | typedef u_int32_t Fnv32_t; 68 | 69 | /* 70 | * 32 bit FNV-1 and FNV-1a non-zero initial basis 71 | * NOTE: The FNV-1a initial basis is the same value as FNV-1 by definition. 72 | */ 73 | #define FNV1_32_INIT ((Fnv32_t)0x811c9dc5) 74 | #define FNV1_32A_INIT FNV1_32_INIT 75 | 76 | extern Fnv32_t fnv_32_buf(void *buf, size_t len, Fnv32_t hashval); 77 | extern Fnv32_t fnv_32_str(char *buf, Fnv32_t hashval); 78 | 79 | extern Fnv32_t fnv_32a_buf(void *buf, size_t len, Fnv32_t hashval); 80 | extern Fnv32_t fnv_32a_str(char *buf, Fnv32_t hashval); 81 | 82 | 83 | typedef u_int64_t Fnv64_t; 84 | 85 | /* 86 | * 64 bit FNV-1 non-zero initial basis 87 | * NOTE: The FNV-1a initial basis is the same value as FNV-1 by definition. 88 | */ 89 | #define FNV1_64_INIT ((Fnv64_t)0xcbf29ce484222325ULL) 90 | #define FNV1A_64_INIT FNV1_64_INIT 91 | 92 | extern Fnv64_t fnv_64_buf(void *buf, size_t len, Fnv64_t hashval); 93 | extern Fnv64_t fnv_64_str(char *buf, Fnv64_t hashval); 94 | 95 | extern Fnv64_t fnv_64a_buf(void *buf, size_t len, Fnv64_t hashval); 96 | extern Fnv64_t fnv_64a_str(char *buf, Fnv64_t hashval); 97 | 98 | #endif /* __FNV_H__ */ 99 | -------------------------------------------------------------------------------- /src/gpuvis_colors.inl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Valve Software 3 | * 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | _XTAG( col_ThemeAlpha, IM_COL32( 255, 255, 255, 255 ), "Global alpha value" ) 26 | _XTAG( col_ClearColor, IM_COL32( 114, 144, 154, 255 ), "Window background clear color" ) 27 | 28 | _XTAG( col_VBlank0, 0xd9ff00db, "VBlank crtc0" ) 29 | _XTAG( col_VBlank1, 0x80fff300, "VBlank crtc1" ) 30 | _XTAG( col_VBlank2, 0x8015cece, "VBlank crtc2" ) 31 | _XTAG( col_FtracePrintText, 0xffcca014, "Ftrace print text color" ) 32 | _XTAG( col_BrightText, 0xffcca014, "Gpuvis bright text color" ) 33 | 34 | // Event list colors 35 | _XTAG( col_EventList_Text, 0xffe6e6e6, "Event list text" ) 36 | _XTAG( col_EventList_Sel, 0xff7a1822, "Event list selected text" ) 37 | _XTAG( col_EventList_Hov, 0xff78490b, "Event list hovered graph events" ) 38 | 39 | // Graph colors 40 | _XTAG( col_Graph_Bk, IM_COL32( 0x2F, 0x4F, 0x4F, 255 ), "Graph Background" ) 41 | _XTAG( col_Graph_RowBk, 0xff141414, "Graph row background" ) 42 | _XTAG( col_Graph_RowLabelText, IM_COL32( 0xFF, 0xFF, 0xE0, 255 ), "Graph row label text" ) 43 | _XTAG( col_Graph_RowLabelTextBk, 0x94242424, "Graph row label text background" ) 44 | _XTAG( col_Graph_1Event, 0xd9fff300, "1 event in graph" ) 45 | _XTAG( col_Graph_2Event, 0xd9ffc200, "2 events grouped in graph" ) 46 | _XTAG( col_Graph_3Event, 0xd9ffaa00, "3 events grouped in graph" ) 47 | _XTAG( col_Graph_4Event, 0xd9ff7900, "3 events grouped in graph" ) 48 | _XTAG( col_Graph_5Event, 0xd9ff6100, "3 events grouped in graph" ) 49 | _XTAG( col_Graph_6Event, 0xd9ff4900, "3 events grouped in graph" ) 50 | _XTAG( col_Graph_HovEvent, IM_COL32( 0xc8, 0x1a, 0xff, 255 ), "Graph hovered event" ) 51 | _XTAG( col_Graph_SelEvent , IM_COL32( 0x17, 0xe6, 0x8d, 255 ), "Graph selected event" ) 52 | _XTAG( col_Graph_TimeTick, 0xd992ff00, "Graph ms time ticks" ) 53 | _XTAG( col_Graph_MousePos, 0x94fff300, "Graph mouse location line" ) 54 | _XTAG( col_Graph_MarkerA, IM_COL32( 0xEE, 0x82, 0xEE, 255 ), "Graph marker A" ) 55 | _XTAG( col_Graph_MarkerB, IM_COL32( 0xEE, 0xEE, 0x82, 255 ), "Graph marker B" ) 56 | _XTAG( col_Graph_ZoomSel, IM_COL32( 0xFF, 0xFF, 0xFF, 80 ), "Graph mouse zoom selection" ) 57 | _XTAG( col_Graph_PrintLabelSat, IM_COL32( 230, 230, 230, 230 ), "Graph print row label saturation" ) 58 | _XTAG( col_Graph_PrintLabelAlpha, IM_COL32( 255, 255, 255, 255 ), "Graph print row label text alpha" ) 59 | _XTAG( col_Graph_PrintBarAlpha, IM_COL32( 80, 80, 80, 80 ), "Graph print row bar alpha" ) 60 | _XTAG( col_Graph_TimelineLabelSat, IM_COL32( 230, 230, 230, 230 ), "Graph timeline row label saturation" ) 61 | _XTAG( col_Graph_TimelineLabelAlpha, IM_COL32( 255, 255, 255, 255 ), "Graph timeline row label text alpha" ) 62 | _XTAG( col_Graph_BarUserspace, 0xff555555, "Graph timeline userspace bar" ) 63 | _XTAG( col_Graph_BarUserspaceHovered, 0xd9fff300, "Graph timeline userspace bar" ) 64 | _XTAG( col_Graph_BarHwQueue, 0x80613030, "Graph timeline hw queue bar" ) 65 | _XTAG( col_Graph_BarHwRunning, 0xd9ffaa00, "Graph timeline hw running bar" ) 66 | _XTAG( col_Graph_BarSelRect, 0xd9fff300, "Graph timeline selected bar rectangle" ) 67 | _XTAG( col_Graph_BarText, IM_COL32( 0xff, 0xff, 0xff, 255 ), "Graph timeline bar text" ) 68 | _XTAG( col_Graph_TaskRunning, 0x4fff00ff, "Sched_switch task running block" ) 69 | _XTAG( col_Graph_TaskSleeping, 0x4fffff00, "Sched_switch task sleeping block" ) 70 | 71 | _XTAG( col_Graph_Bari915ReqWait, 0x4f0000ff, "i915 reqwait bar" ) 72 | 73 | _XTAG( col_Graph_Bari915Queue, 0xc81d740c, "Request queued waiting to be added" ) 74 | _XTAG( col_Graph_Bari915SubmitDelay, 0xc8f8552e, "Requests waiting on fences and dependencies before they are runnable" ) 75 | _XTAG( col_Graph_Bari915ExecuteDelay, 0xc89e9e9e, "Runnable requests waiting for a slot on GPU" ) 76 | _XTAG( col_Graph_Bari915Execute, 0xc8aa149a, "Requests executing on the GPU" ) 77 | _XTAG( col_Graph_Bari915CtxCompleteDelay, 0xc800a5ff, "User interrupt to context complete" ) 78 | 79 | _XTAG( col_FrameMarkerBk0, 0x32323232, "Frame Marker Background #0" ) 80 | _XTAG( col_FrameMarkerBk1, 0x64646464, "Frame Marker Background #1" ) 81 | _XTAG( col_FrameMarkerSelected, 0x0000ff31, "Selected Frame Marker Background" ) 82 | 83 | // ImGui colors 84 | _XTAG( col_ImGui_Text, 0xffe6e6e6, "ImGui text" ) 85 | _XTAG( col_ImGui_TextDisabled, 0xff666666, "ImGui disabled text" ) 86 | _XTAG( col_ImGui_TextSelectedBg, 0x59fa9642, "ImGui selected text background" ) 87 | _XTAG( col_ImGui_TitleBg, 0xff303030, "ImGui title background" ) 88 | _XTAG( col_ImGui_TitleBgActive, 0xff2e2e2e, "ImGui active title background" ) 89 | _XTAG( col_ImGui_TitleBgCollapsed, 0x82000000, "ImGui active collapsed title background" ) 90 | _XTAG( col_ImGui_WindowBg, 0xfc0f0f0f, "ImGui background of normal windows" ) 91 | _XTAG( col_ImGui_Border, 0x30ffffff, "ImGui border" ) 92 | _XTAG( col_ImGui_BorderShadow, 0x1a000000, "ImGui border Shadow" ) 93 | _XTAG( col_ImGui_Button, 0xff333333, "ImGui button" ) 94 | _XTAG( col_ImGui_ButtonActive, 0xfffa870f, "ImGui active Button" ) 95 | _XTAG( col_ImGui_ButtonHovered, 0xfffa9642, "ImGui hovered Button" ) 96 | _XTAG( col_ImGui_CheckMark, 0xfffa9642, "ImGui check mark" ) 97 | _XTAG( col_ImGui_ChildBg, 0xffffff, "ImGui background of child windows" ) 98 | _XTAG( col_ImGui_CloseButton, 0x80696969, "ImGui closed button" ) 99 | _XTAG( col_ImGui_CloseButtonActive, 0xff5c63fa, "ImGui active close button" ) 100 | _XTAG( col_ImGui_CloseButtonHovered, 0xff5c63fa, "ImGui hovered close button" ) 101 | _XTAG( col_ImGui_Separator, 0xff9c9c9c, "ImGui column" ) 102 | _XTAG( col_ImGui_SeparatorActive, 0xfffa9642, "ImGui active column" ) 103 | _XTAG( col_ImGui_SeparatorHovered, 0xc7fa9642, "ImGui hovered column" ) 104 | _XTAG( col_ImGui_FrameBg, 0xff262626, "ImGui background of checkbox, radio button, plot, slider, text input" ) 105 | _XTAG( col_ImGui_FrameBgActive, 0xabfa9642, "ImGui active frame background" ) 106 | _XTAG( col_ImGui_FrameBgHovered, 0x66fa9642, "ImGui hovered frame background" ) 107 | _XTAG( col_ImGui_Header, 0xff1c1c1c, "ImGui header" ) 108 | _XTAG( col_ImGui_HeaderActive, 0xfffa9642, "ImGui active hader" ) 109 | _XTAG( col_ImGui_HeaderHovered, 0xccfa9642, "ImGui hovered header" ) 110 | _XTAG( col_ImGui_MenuBarBg, 0xff303030, "ImGui background menu bar" ) 111 | _XTAG( col_ImGui_ModalWindowDarkening, 0x59cccccc, "ImGui darken entire screen when a modal window is active" ) 112 | _XTAG( col_ImGui_PopupBg, 0xf0000000, "ImGui background of popups, menus, tooltips windows" ) 113 | _XTAG( col_ImGui_ResizeGrip, 0x40fa9642, "ImGui resize grip" ) 114 | _XTAG( col_ImGui_ResizeGripActive, 0xf2fa9642, "ImGui active resize grip" ) 115 | _XTAG( col_ImGui_ResizeGripHovered, 0xabfa9642, "ImGui hovered resize grip" ) 116 | _XTAG( col_ImGui_ScrollbarBg, 0x87050505, "ImGui scrollbar background" ) 117 | _XTAG( col_ImGui_ScrollbarGrab, 0xff4f4f4f, "ImGui scrollbar grab" ) 118 | _XTAG( col_ImGui_ScrollbarGrabActive, 0xff828282, "ImGui active scrollbar grab" ) 119 | _XTAG( col_ImGui_ScrollbarGrabHovered, 0xff696969, "ImGui hovered scrollbar grab" ) 120 | _XTAG( col_ImGui_SliderGrab, 0xffe0853d, "ImGui slider grab" ) 121 | _XTAG( col_ImGui_SliderGrabActive, 0xfffa9642, "ImGui active slider grab" ) 122 | -------------------------------------------------------------------------------- /src/gpuvis_etl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Valve Software 3 | * 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef GPUVIS_ETL_H_ 26 | #define GPUVIS_ETL_H_ 27 | 28 | int read_etl_file( const char *file, StrPool &strpool, trace_info_t &trace_info, EventCallback &cb ); 29 | 30 | #endif // GPUVIS_ETL_H_ 31 | -------------------------------------------------------------------------------- /src/gpuvis_framemarkers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Valve Software 3 | * 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | 37 | #include "imgui/imgui.h" 38 | #include "imgui/imgui_internal.h" // BeginColumns(), EndColumns() WIP 39 | #include "gpuvis_macros.h" 40 | #include "stlini.h" 41 | #include "trace-cmd/trace-read.h" 42 | #include "gpuvis_utils.h" 43 | #include "gpuvis.h" 44 | 45 | void FrameMarkers::init() 46 | { 47 | std::vector< INIEntry > entries = s_ini().GetSectionEntries( "$framemarkers_filters$" ); 48 | 49 | for ( const INIEntry &entry : entries ) 50 | { 51 | const std::vector< std::string > filter = string_explode( entry.second, '\t' ); 52 | 53 | if ( filter.size() == 1 ) 54 | m_previous_filters.push_back( { filter[ 0 ], "" } ); 55 | else if ( filter.size() == 2 ) 56 | m_previous_filters.push_back( { filter[ 0 ], filter[ 1 ] } ); 57 | } 58 | 59 | if ( m_previous_filters.empty() ) 60 | { 61 | // Add some default filters 62 | m_previous_filters.push_back( { "$name = drm_vblank_event && $crtc = 0", "" } ); 63 | m_previous_filters.push_back( { "$name = drm_vblank_event && $crtc = 1", "" } ); 64 | m_previous_filters.push_back( { "$buf =~ \"[Compositor] Before wait query\"", 65 | "$buf =~ \"[Compositor] After wait query\"" } ); 66 | } 67 | 68 | strcpy_safe( dlg.m_left_marker_buf, m_previous_filters[ 0 ].first.c_str() ); 69 | strcpy_safe( dlg.m_right_marker_buf, m_previous_filters[ 0 ].second.c_str() ); 70 | } 71 | 72 | void FrameMarkers::shutdown() 73 | { 74 | for ( size_t i = 0; i < m_previous_filters.size(); i++ ) 75 | { 76 | char key[ 32 ]; 77 | std::string value = m_previous_filters[ i ].first; 78 | 79 | value += "\t"; 80 | value += m_previous_filters[ i ].second; 81 | 82 | snprintf_safe( key, "%02lu", i ); 83 | 84 | s_ini().PutStr( key, value.c_str(), "$framemarkers_filters$" ); 85 | } 86 | } 87 | 88 | void FrameMarkers::clear_dlg() 89 | { 90 | dlg.m_checked = false; 91 | 92 | dlg.m_left_filter_err_str.clear(); 93 | dlg.m_right_filter_err_str.clear(); 94 | 95 | dlg.m_left_plocs = NULL; 96 | dlg.m_right_plocs = NULL; 97 | } 98 | 99 | void FrameMarkers::set_tooltip() 100 | { 101 | std::string tooltip; 102 | 103 | tooltip += s_textclrs().bright_str( "Frame marker filters\n\n" ); 104 | 105 | tooltip += "Examples:\n"; 106 | 107 | tooltip += " Left frame: $name = drm_vblank_event && $crtc = 0\n"; 108 | tooltip += " Right frame: $name = drm_vblank_event && $crtc = 0\n\n"; 109 | 110 | tooltip += " Left frame: $buf =~ \"[Compositor] Sleep - begin\"\n"; 111 | tooltip += " Right frame: $buf =~ \"[Compositor] Sleep - end\"\n"; 112 | 113 | ImGui::SetTooltip( "%s", tooltip.c_str() ); 114 | } 115 | 116 | bool FrameMarkers::show_dlg( TraceEvents &trace_events, uint32_t eventid ) 117 | { 118 | clear_dlg(); 119 | 120 | if ( is_valid_id( eventid ) && ( eventid < trace_events.m_events.size() ) ) 121 | { 122 | const trace_event_t &event = trace_events.m_events[ eventid ]; 123 | 124 | dlg.m_left_marker_buf[ 0 ] = 0; 125 | dlg.m_right_marker_buf[ 0 ] = 0; 126 | 127 | if ( event.is_vblank() ) 128 | { 129 | snprintf_safe( dlg.m_left_marker_buf, "$name = %s && $crtc == %d", event.name, event.crtc ); 130 | } 131 | else if ( event.is_ftrace_print() ) 132 | { 133 | const char *buf = get_event_field_val( event, "buf" ); 134 | 135 | if ( buf[ 0 ] ) 136 | snprintf_safe( dlg.m_left_marker_buf, "$buf =~ \"%s\"", buf ); 137 | } 138 | 139 | if ( !dlg.m_left_marker_buf[ 0 ] ) 140 | snprintf_safe( dlg.m_left_marker_buf, "$name = %s", event.name ); 141 | } 142 | 143 | if ( !dlg.m_left_marker_buf[ 0 ] ) 144 | strcpy_safe( dlg.m_left_marker_buf, "$name = drm_vblank_event && $crtc = 0" ); 145 | 146 | ImGui::OpenPopup( "Set Frame Markers" ); 147 | return true; 148 | } 149 | 150 | bool FrameMarkers::render_dlg( TraceEvents &trace_events ) 151 | { 152 | bool item_hovered = false; 153 | char right_marker_buf[ 512 ]; 154 | float w = imgui_scale( 450.0f ); 155 | const char left_text[] = "Left Frame: "; 156 | const char right_text[] = "Right Frame: "; 157 | const ImVec2 button_size = { imgui_scale( 250.0f ), 0.0f }; 158 | float x = ImGui::GetCursorPos().x + ImGui::CalcTextSize( right_text ).x; 159 | 160 | if ( !ImGui::BeginPopupModal( "Set Frame Markers", NULL, ImGuiWindowFlags_AlwaysAutoResize ) ) 161 | return false; 162 | 163 | ImGui::Text( "%s", "Frame marker filters" ); 164 | 165 | // Left Frame Filter 166 | { 167 | if ( imgui_input_text( left_text, dlg.m_left_marker_buf, x, w ) ) 168 | clear_dlg(); 169 | 170 | if ( ImGui::IsWindowAppearing() ) 171 | ImGui::SetKeyboardFocusHere( -1 ); 172 | 173 | item_hovered |= ImGui::IsItemHovered(); 174 | 175 | if ( !dlg.m_left_filter_err_str.empty() ) 176 | ImGui::TextColored( ImVec4( 1, 0, 0, 1 ), "%s", dlg.m_left_filter_err_str.c_str() ); 177 | else if ( dlg.m_left_plocs ) 178 | ImGui::TextColored( ImVec4( 0, 1, 0, 1 ), "%lu events found", dlg.m_left_plocs->size() ); 179 | } 180 | 181 | // Right Frame Filter 182 | { 183 | strcpy_safe( right_marker_buf, !dlg.m_right_marker_buf[ 0 ] ? dlg.m_left_marker_buf : dlg.m_right_marker_buf ); 184 | 185 | if ( imgui_input_text( right_text, right_marker_buf, x, w ) ) 186 | { 187 | clear_dlg(); 188 | strcpy_safe( dlg.m_right_marker_buf, right_marker_buf ); 189 | } 190 | 191 | item_hovered |= ImGui::IsItemHovered(); 192 | 193 | if ( !dlg.m_right_filter_err_str.empty() ) 194 | ImGui::TextColored( ImVec4( 1, 0, 0, 1 ), "%s", dlg.m_right_filter_err_str.c_str() ); 195 | else if ( dlg.m_right_plocs ) 196 | ImGui::TextColored( ImVec4( 0, 1, 0, 1 ), "%lu events found", dlg.m_right_plocs->size() ); 197 | } 198 | 199 | if ( item_hovered ) 200 | set_tooltip(); 201 | 202 | ImGui::Separator(); 203 | 204 | if ( dlg.m_checked && dlg.m_count ) 205 | { 206 | ImGui::TextColored( ImVec4( 0, 1, 0, 1 ), "%u frames found", dlg.m_count ); 207 | ImGui::Indent(); 208 | ImGui::Text( "Min frame time: %s", ts_to_timestr( dlg.m_min_ts, 4 ).c_str() ); 209 | ImGui::Text( "Max frame time: %s", ts_to_timestr( dlg.m_max_ts, 4 ).c_str() ); 210 | ImGui::Text( "Avg frame time: %s", ts_to_timestr( dlg.m_tot_ts / dlg.m_count, 4 ).c_str() ); 211 | ImGui::Unindent(); 212 | 213 | ImGui::Separator(); 214 | } 215 | 216 | if ( ImGui::CollapsingHeader( "Previous Filters", ImGuiTreeNodeFlags_DefaultOpen ) ) 217 | { 218 | ImGui::BeginChild( "previous_filters", ImVec2( 0.0f, imgui_scale( 150.0f ) ) ); 219 | ImGui::Indent(); 220 | 221 | ImGuiSelectableFlags flags = ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_DontClosePopups; 222 | 223 | imgui_begin_columns( "framemarker_presets", { left_text, right_text } ); 224 | 225 | for ( auto i : m_previous_filters ) 226 | { 227 | const char *str0 = i.first.c_str(); 228 | const char *str1 = i.second.c_str(); 229 | 230 | ImGui::PushID( str0 ); 231 | 232 | if ( ImGui::Selectable( str0, false, flags ) ) 233 | { 234 | clear_dlg(); 235 | 236 | strcpy_safe( dlg.m_left_marker_buf, str0 ); 237 | strcpy_safe( dlg.m_right_marker_buf, str1 ); 238 | } 239 | ImGui::NextColumn(); 240 | 241 | ImGui::Text( "%s", str1[ 0 ] ? str1 : str0 ); 242 | ImGui::NextColumn(); 243 | ImGui::Separator(); 244 | 245 | ImGui::PopID(); 246 | } 247 | 248 | ImGui::EndColumns(); 249 | 250 | ImGui::Unindent(); 251 | ImGui::EndChild(); 252 | } 253 | 254 | // "Check filters" or "Set Frame Markers" buttons 255 | if ( !dlg.m_checked ) 256 | { 257 | if ( ImGui::Button( "Check filters", button_size ) || s_actions().get( action_return ) ) 258 | { 259 | dlg.m_left_plocs = trace_events.get_tdopexpr_locs( dlg.m_left_marker_buf, &dlg.m_left_filter_err_str ); 260 | dlg.m_right_plocs = trace_events.get_tdopexpr_locs( right_marker_buf, &dlg.m_right_filter_err_str ); 261 | 262 | if ( !dlg.m_left_plocs ) 263 | { 264 | if ( dlg.m_left_filter_err_str.empty() ) 265 | dlg.m_left_filter_err_str = "WARNING: No events found."; 266 | } 267 | if ( !dlg.m_right_plocs ) 268 | { 269 | if ( dlg.m_right_filter_err_str.empty() ) 270 | dlg.m_right_filter_err_str = "WARNING: No events found."; 271 | } 272 | 273 | if ( dlg.m_left_plocs && dlg.m_right_plocs ) 274 | { 275 | setup_frames( trace_events, false ); 276 | dlg.m_checked = true; 277 | } 278 | } 279 | } 280 | else if ( ImGui::Button( "Set Frame Markers", button_size ) || s_actions().get( action_return ) ) 281 | { 282 | // If left filter == right filter, zero out right filter 283 | if ( !strcmp( dlg.m_left_marker_buf, dlg.m_right_marker_buf ) ) 284 | dlg.m_right_marker_buf[ 0 ] = 0; 285 | 286 | // Try to find this filter pair in our previous filters array 287 | std::pair< std::string, std::string > filter = { dlg.m_left_marker_buf, dlg.m_right_marker_buf }; 288 | auto idx = std::find( m_previous_filters.begin(), m_previous_filters.end(), filter ); 289 | 290 | // Erase the one we found 291 | if ( idx != m_previous_filters.end() ) 292 | m_previous_filters.erase( idx ); 293 | 294 | // Insert it at the beginning 295 | m_previous_filters.insert( m_previous_filters.begin(), filter ); 296 | 297 | // Make sure we don't go over ~ 20 filters 298 | if ( m_previous_filters.size() > 20 ) 299 | m_previous_filters.resize( 20 ); 300 | 301 | setup_frames( trace_events, true ); 302 | 303 | ImGui::CloseCurrentPopup(); 304 | } 305 | 306 | // Cancel button 307 | ImGui::SameLine(); 308 | if ( ImGui::Button( "Cancel", button_size ) || s_actions().get( action_escape ) ) 309 | ImGui::CloseCurrentPopup(); 310 | 311 | ImGui::EndPopup(); 312 | 313 | return false; 314 | } 315 | 316 | int64_t FrameMarkers::get_frame_len( TraceEvents &trace_events, int frame ) 317 | { 318 | if ( ( size_t )frame < m_left_frames.size() ) 319 | { 320 | uint32_t left_idx = m_left_frames[ frame ]; 321 | uint32_t right_idx = m_right_frames[ frame ]; 322 | const trace_event_t &left_event = trace_events.m_events[ left_idx ]; 323 | const trace_event_t &right_event = trace_events.m_events[ right_idx ]; 324 | 325 | return right_event.ts - left_event.ts; 326 | } 327 | 328 | return 0; 329 | } 330 | 331 | void FrameMarkers::setup_frames( TraceEvents &trace_events, bool set_frames ) 332 | { 333 | uint32_t idx = 0; 334 | const std::vector< uint32_t > &locs_left = *dlg.m_left_plocs; 335 | const std::vector< uint32_t > &locs_right = *dlg.m_right_plocs; 336 | 337 | dlg.m_count = 0; 338 | dlg.m_tot_ts = 0; 339 | dlg.m_min_ts = INT64_MAX; 340 | dlg.m_max_ts = INT64_MIN; 341 | 342 | if ( set_frames ) 343 | { 344 | m_left_frames.clear(); 345 | m_right_frames.clear(); 346 | } 347 | 348 | // Go through all the right eventids... 349 | for ( uint32_t right_eventid : locs_right ) 350 | { 351 | // Find entryid in left which is < this right eventid 352 | while ( locs_left[ idx ] < right_eventid ) 353 | { 354 | // Check if this is our last left event or the next event is greater. 355 | if ( ( idx + 1 >= locs_left.size() ) || 356 | ( locs_left[ idx + 1 ] >= right_eventid ) ) 357 | { 358 | const trace_event_t &left_event = trace_events.m_events[ locs_left[ idx ] ]; 359 | const trace_event_t &right_event = trace_events.m_events[ right_eventid ]; 360 | int64_t ts = right_event.ts - left_event.ts; 361 | 362 | dlg.m_count++; 363 | dlg.m_tot_ts += ts; 364 | dlg.m_min_ts = std::min< int64_t >( dlg.m_min_ts, ts ); 365 | dlg.m_max_ts = std::max< int64_t >( dlg.m_max_ts, ts ); 366 | 367 | if ( set_frames ) 368 | { 369 | m_left_frames.push_back( locs_left[ idx ] ); 370 | m_right_frames.push_back( right_eventid ); 371 | } 372 | 373 | if ( ++idx >= locs_left.size() ) 374 | return; 375 | break; 376 | } 377 | 378 | idx++; 379 | } 380 | } 381 | } 382 | -------------------------------------------------------------------------------- /src/gpuvis_macros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Valve Software 3 | * 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef GPUVIS_MACROS_H_ 25 | #define GPUVIS_MACROS_H_ 26 | 27 | // Disable gpuvis ftrace tracing by default 28 | #define GPUVIS_TRACE_UTILS_DISABLE 29 | #include "../sample/gpuvis_trace_utils.h" 30 | 31 | #if !defined( __ANDROID__ ) && !defined( __GLIBC__ ) 32 | // https://android.googlesource.com/platform/system/core/+/master/base/include/android-base/macros.h 33 | #ifndef TEMP_FAILURE_RETRY 34 | #define TEMP_FAILURE_RETRY(exp) \ 35 | ({ \ 36 | decltype(exp) _rc; \ 37 | do { \ 38 | _rc = (exp); \ 39 | } while (_rc == -1 && errno == EINTR); \ 40 | _rc; \ 41 | }) 42 | #endif 43 | #endif 44 | 45 | // Super handy macros from Jonathan Wakely / Patrick Horgan: 46 | // http://dbp-consulting.com/tutorials/SuppressingGCCWarnings.html 47 | #if defined( __GNUC__ ) 48 | 49 | #define ATTRIBUTE_PRINTF( _x, _y ) __attribute__( ( __format__( __printf__, _x, _y ) ) ) 50 | 51 | #define GCC_DIAG_STR( s ) #s 52 | #define GCC_DIAG_JOINSTR( x, y ) GCC_DIAG_STR( x##y ) 53 | #define GCC_DIAG_DO_PRAGMA( x ) _Pragma( #x ) 54 | #define GCC_DIAG_PRAGMA( x ) GCC_DIAG_DO_PRAGMA( GCC diagnostic x ) 55 | 56 | #define GCC_DIAG_PUSH_OFF( x ) \ 57 | GCC_DIAG_PRAGMA( push ) \ 58 | GCC_DIAG_PRAGMA( ignored GCC_DIAG_JOINSTR( -W, x ) ) 59 | #define GCC_DIAG_POP() GCC_DIAG_PRAGMA( pop ) 60 | 61 | #else 62 | 63 | #define TEMP_FAILURE_RETRY( _x ) _x 64 | 65 | #define ATTRIBUTE_PRINTF( _x, _y ) 66 | 67 | #define GCC_DIAG_PUSH_OFF( x ) 68 | #define GCC_DIAG_POP() 69 | 70 | #endif 71 | 72 | #ifndef PATH_MAX 73 | #ifndef MAX_PATH 74 | #define MAX_PATH 260 75 | #endif 76 | 77 | #define PATH_MAX ( MAX_PATH + 1 ) 78 | #endif 79 | 80 | #if defined( WIN32 ) 81 | 82 | typedef __int64 ssize_t; 83 | typedef __int64 off64_t; 84 | 85 | #if defined( __cplusplus ) 86 | extern "C" { 87 | #endif 88 | 89 | int strcasecmp( const char *s1, const char *s2 ); 90 | int strncasecmp( const char *s1, const char *s2, size_t n ); 91 | 92 | char *strcasestr( const char *haystack, const char *needle ); 93 | 94 | int asprintf(char **strp, const char *fmt, ...); 95 | int vasprintf( char **strp, const char *fmt, va_list ap ); 96 | 97 | char *strtok_r( char *str, const char *delim, char **saveptr ); 98 | 99 | #if defined( __cplusplus ) 100 | } 101 | #endif 102 | 103 | #endif 104 | 105 | #if defined( __cplusplus ) 106 | 107 | #include 108 | 109 | template < typename K, typename V > 110 | class util_umap 111 | { 112 | public: 113 | util_umap() {} 114 | ~util_umap() {} 115 | 116 | V *get_val( const K key, const V &defval ) 117 | { 118 | auto res = m_map.emplace( key, defval ); 119 | return &res.first->second; 120 | } 121 | 122 | V *get_val_create( const K key ) 123 | { 124 | auto i = m_map.find( key ); 125 | if ( i != m_map.end() ) 126 | return &i->second; 127 | return get_val( key, V() ); 128 | } 129 | V *get_val( const K key ) 130 | { 131 | auto i = m_map.find( key ); 132 | if ( i != m_map.end() ) 133 | return &i->second; 134 | return NULL; 135 | } 136 | const V *get_val( const K key ) const 137 | { 138 | auto i = m_map.find( key ); 139 | if ( i != m_map.end() ) 140 | return &i->second; 141 | return NULL; 142 | } 143 | 144 | void set_val( const K key, const V &val ) 145 | { 146 | auto res = m_map.emplace( key, val ); 147 | 148 | /* 149 | * If the insertion takes place (because no other element existed with the 150 | * same key), the function returns a pair object, whose first component is an 151 | * iterator to the inserted element, and whose second component is true. 152 | * 153 | * Otherwise, the pair object returned has as first component an iterator 154 | * pointing to the element in the container with the same key, and false as its 155 | * second component. 156 | */ 157 | if ( !res.second ) 158 | res.first->second = val; 159 | } 160 | 161 | bool erase_key( const K key ) 162 | { 163 | auto i = m_map.find( key ); 164 | 165 | if ( i != m_map.end() ) 166 | { 167 | m_map.erase( i ); 168 | return true; 169 | } 170 | return false; 171 | } 172 | 173 | public: 174 | typedef std::unordered_map< K, V > map_t; 175 | map_t m_map; 176 | }; 177 | 178 | class StrAlloc 179 | { 180 | public: 181 | StrAlloc() {} 182 | ~StrAlloc(); 183 | 184 | char *allocmem( size_t len ); 185 | char *dupestr( const char *str, size_t len ); 186 | 187 | public: 188 | char *m_ptr = nullptr; 189 | size_t m_avail = 0; 190 | size_t m_totsize = 0; 191 | std::vector< char * > m_chunks; 192 | }; 193 | 194 | class StrPool 195 | { 196 | public: 197 | StrPool() {} 198 | ~StrPool() {} 199 | 200 | const char *getstr( const char *str, size_t len = ( size_t )-1 ); 201 | const char *getstrf( const char *fmt, ... ) ATTRIBUTE_PRINTF( 2, 3 ); 202 | const char *findstr( uint64_t hashval ); 203 | 204 | uint64_t getu64( const char *str, size_t len = ( size_t )-1 ); 205 | uint64_t getu64f( const char *fmt, ... ) ATTRIBUTE_PRINTF( 2, 3 ); 206 | 207 | public: 208 | StrAlloc m_alloc; 209 | util_umap< uint64_t, const char * > m_pool; 210 | }; 211 | 212 | class BitVec 213 | { 214 | public: 215 | explicit BitVec( size_t size ) 216 | { 217 | m_size = size; 218 | m_bits = ( uint8_t * )calloc( ( m_size + 7 ) / 8, 1 ); 219 | } 220 | ~BitVec() { free( m_bits ); } 221 | 222 | void set( size_t index ) { m_bits[ index >> 3 ] |= mask( index ); } 223 | void unset( size_t index ) { m_bits[ index >> 3 ] &= ~mask( index ); } 224 | void toggle( size_t index ) { m_bits[ index >> 3 ] ^= mask( index ); } 225 | 226 | bool get( size_t index ) const { return !!( m_bits[ index >> 3 ] & mask( index ) ); } 227 | 228 | size_t size() const { return m_size; }; 229 | 230 | protected: 231 | static uint32_t mask( size_t index ) { return 1U << ( index & 7 ); } 232 | 233 | private: 234 | size_t m_size = 0; 235 | uint8_t *m_bits = nullptr; 236 | }; 237 | 238 | uint32_t hashstr32( const char *str, size_t len = ( size_t )-1, uint32_t hval = 0xB0F57EE3 ); 239 | uint32_t hashstr32( const std::string &str, uint32_t hval = 0xB0F57EE3 ); 240 | 241 | uint64_t hashstr64( const char *str, size_t len = ( size_t )-1 ); 242 | uint64_t hashstr64( const std::string &str ); 243 | 244 | size_t get_file_size( const char *filename ); 245 | const char *get_path_filename( const char *filename ); 246 | 247 | std::string get_realpath( const char *filename ); 248 | 249 | bool copy_file( const char *filename, const char *newfilename ); 250 | 251 | std::string string_format( const char *fmt, ... ) ATTRIBUTE_PRINTF( 1, 2 ); 252 | 253 | std::string string_strftime(); 254 | 255 | void string_replace_char( std::string &s, const char search, const char replace ); 256 | void string_replace_str( std::string &s, const std::string &search, const std::string &replace ); 257 | 258 | std::string gen_random_str( size_t len ); 259 | 260 | // trim from start (in place) 261 | void string_ltrim( std::string &s ); 262 | // trim from end (in place) 263 | void string_rtrim( std::string &s ); 264 | // trim from both ends (in place) 265 | void string_trim( std::string &s ); 266 | // remove punctuation from string 267 | std::string string_remove_punct( const std::string &s ); 268 | 269 | // disassemble a string into parts 270 | std::vector< std::string > string_explode( std::string const &s, char delim ); 271 | // assembles a vector of string elements with a delimiter 272 | std::string string_implode( std::vector< std::string > &elements, const std::string &delimiter ); 273 | 274 | // trim from start (copying) 275 | std::string string_ltrimmed( std::string s ); 276 | // trim from end (copying) 277 | std::string string_rtrimmed( std::string s ); 278 | // trim from both ends (copying) 279 | std::string string_trimmed( std::string s ); 280 | 281 | // Remove leading and trailing whitespace from string (in place) 282 | void str_strip_whitespace( char *str ); 283 | // Strstr routine which ignores whitespace 284 | char *strstr_ignore_spaces( char *haystack, const char *needle, size_t *len = NULL ); 285 | // Remove substrings in place from a string 286 | void remove_substrings( char *str, const char *fmt, ... ) ATTRIBUTE_PRINTF( 2, 3 ); 287 | 288 | inline char *strncasestr( const char *haystack, const char *needle, size_t needle_len ) 289 | { 290 | for ( ; *haystack; haystack++ ) 291 | { 292 | if ( !strncasecmp( haystack, needle, needle_len ) ) 293 | return ( char * )haystack; 294 | } 295 | return NULL; 296 | } 297 | 298 | template < typename T > 299 | T Clamp( const T& val, const T& lower, const T& upper ) 300 | { 301 | return std::max< T >( lower, std::min< T >( val, upper ) ); 302 | } 303 | 304 | template < typename T, size_t size > 305 | constexpr size_t ARRAY_SIZE( const T (&)[ size ] ) 306 | { 307 | return size; 308 | } 309 | 310 | template < size_t T > 311 | int snprintf_safe( char ( &buf )[ T ], const char *fmt, ... ) ATTRIBUTE_PRINTF( 2, 3 ); 312 | template < size_t T > 313 | int snprintf_safe( char ( &buf )[ T ], const char *fmt, ... ) 314 | { 315 | va_list ap; 316 | int retval; 317 | 318 | va_start( ap, fmt ); 319 | 320 | retval = vsnprintf( buf, T, fmt, ap ); 321 | buf[ T - 1 ] = 0; 322 | 323 | va_end( ap ); 324 | 325 | return retval; 326 | } 327 | 328 | template < size_t T > 329 | int vsnprintf_safe( char ( &buf )[ T ], const char *fmt, va_list ap ) ATTRIBUTE_PRINTF( 2, 0 ); 330 | template < size_t T > 331 | int vsnprintf_safe( char ( &buf )[ T ], const char *fmt, va_list ap ) 332 | { 333 | int retval; 334 | 335 | retval = vsnprintf( buf, T, fmt, ap ); 336 | buf[ T - 1 ] = 0; 337 | 338 | return retval; 339 | } 340 | 341 | template < size_t T > 342 | char *strcpy_safe( char ( &dest )[ T ], const char *src ) 343 | { 344 | size_t len = std::min< size_t >( T - 1, strlen( src ) ); 345 | 346 | memcpy( dest, src, len ); 347 | dest[ len ] = 0; 348 | 349 | return dest; 350 | } 351 | 352 | template < size_t T > 353 | char *strcpy_safe( char ( &dest )[ T ], const std::string &src ) 354 | { 355 | size_t len = std::min< size_t >( T - 1, src.size() ); 356 | 357 | memcpy( dest, src.data(), len ); 358 | dest[ len ] = 0; 359 | 360 | return dest; 361 | } 362 | 363 | template < size_t T > 364 | char *strcat_safe( char ( &dest )[ T ], const char *src ) 365 | { 366 | size_t i; 367 | 368 | for ( i = strlen( dest ); ( i < T - 1 ) && *src; ) 369 | dest[ i++ ] = *src++; 370 | 371 | dest[ i ] = '\0'; 372 | return dest; 373 | } 374 | 375 | #define STATIC_ASSERT( _x ) static_assert( _x, #_x ) 376 | 377 | #else 378 | 379 | #define STATIC_ASSERT( _x ) 380 | 381 | #endif // __cplusplus 382 | 383 | #endif // GPUVIS_MACROS_H_ 384 | -------------------------------------------------------------------------------- /src/hook_gtk3.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Valve Software 3 | * 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | char *g_errstr = NULL; 28 | static void *g_libgtk = NULL; 29 | 30 | // Function pointer typedefs 31 | extern "C" 32 | { 33 | #define HOOK_FUNC( _ret, _func, _args, ... ) typedef _ret ( _func ## _t )( __VA_ARGS__ ); 34 | #define HOOK_FUNCV( _ret, _func, _args, ... ) typedef _ret ( _func ## _t )( __VA_ARGS__ ); 35 | #include "hook_gtk3_funcs.inl" 36 | #undef HOOK_FUNC 37 | #undef HOOK_FUNCV 38 | } 39 | 40 | // Function pointers struct 41 | struct 42 | { 43 | #define HOOK_FUNC( _ret, _func, _args, ... ) _func ## _t *_func; 44 | #define HOOK_FUNCV( _ret, _func, _args, ... ) _func ## _t *_func; 45 | #include "hook_gtk3_funcs.inl" 46 | #undef HOOK_FUNC 47 | #undef HOOK_FUNCV 48 | } g_gtk; 49 | 50 | // Init function pointers struct 51 | static const char *hook_gtk3_init() 52 | { 53 | const char *fail_func = NULL; 54 | 55 | // Already loaded? 56 | if ( g_libgtk ) 57 | return NULL; 58 | 59 | // Already error'd out? 60 | if ( g_errstr ) 61 | return g_errstr; 62 | 63 | // Try to load gtk3 dso 64 | g_libgtk = dlopen( "libgtk-3.so.0", RTLD_NOW | RTLD_GLOBAL ); 65 | if ( !g_libgtk ) 66 | g_libgtk = dlopen( "libgtk-3.so", RTLD_NOW | RTLD_GLOBAL ); 67 | if ( !g_libgtk ) 68 | { 69 | if (-1 == asprintf( &g_errstr, "dlopen( libgtk-3.so ) failed: %s\n", dlerror() )) 70 | g_errstr = NULL; 71 | return g_errstr; 72 | } 73 | 74 | // Get addresses of gtk3 functions 75 | #define DLSYM_FUNC( _func ) \ 76 | { \ 77 | g_gtk._func = ( _func ## _t * )dlsym( g_libgtk, #_func ); \ 78 | if ( !g_gtk._func ) \ 79 | { \ 80 | fail_func = #_func; \ 81 | break; \ 82 | } \ 83 | } 84 | #define HOOK_FUNC( _ret, _func, _args, ... ) DLSYM_FUNC( _func ) 85 | #define HOOK_FUNCV( _ret, _func, _args, ... ) DLSYM_FUNC( _func ) 86 | 87 | do 88 | { 89 | #include "hook_gtk3_funcs.inl" 90 | } while ( 0 ); 91 | 92 | #undef HOOK_FUNC 93 | #undef HOOK_FUNCV 94 | 95 | // Error out and free library if any dlsym calls failed 96 | if ( fail_func ) 97 | { 98 | if (-1 == asprintf( &g_errstr, "dlsym( %s ) failed: %s\n", fail_func, dlerror() )) 99 | g_errstr = NULL; 100 | 101 | dlclose( g_libgtk ); 102 | g_libgtk = NULL; 103 | } 104 | 105 | return g_errstr; 106 | } 107 | 108 | #define g_type_check_instance_cast g_gtk.g_type_check_instance_cast 109 | #define gtk_dialog_run g_gtk.gtk_dialog_run 110 | #define gtk_dialog_get_type g_gtk.gtk_dialog_get_type 111 | #define gtk_init_check g_gtk.gtk_init_check 112 | #define gtk_events_pending g_gtk.gtk_events_pending 113 | #define gtk_main_iteration g_gtk.gtk_main_iteration 114 | #define gtk_widget_destroy g_gtk.gtk_widget_destroy 115 | #define gtk_file_chooser_get_type g_gtk.gtk_file_chooser_get_type 116 | #define gtk_file_chooser_set_filename g_gtk.gtk_file_chooser_set_filename 117 | #define gtk_file_chooser_set_current_name g_gtk.gtk_file_chooser_set_current_name 118 | #define gtk_file_chooser_set_do_overwrite_confirmation g_gtk.gtk_file_chooser_set_do_overwrite_confirmation 119 | #define gtk_file_chooser_get_filename g_gtk.gtk_file_chooser_get_filename 120 | #define gtk_file_chooser_dialog_new g_gtk.gtk_file_chooser_dialog_new 121 | #define gtk_file_chooser_add_filter g_gtk.gtk_file_chooser_add_filter 122 | #define gtk_file_filter_new g_gtk.gtk_file_filter_new 123 | #define gtk_file_filter_set_name g_gtk.gtk_file_filter_set_name 124 | #define gtk_file_filter_add_pattern g_gtk.gtk_file_filter_add_pattern 125 | -------------------------------------------------------------------------------- /src/hook_gtk3_funcs.inl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Valve Software 3 | * 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | HOOK_FUNC( GTypeInstance *, g_type_check_instance_cast, ( instance, iface_type ), GTypeInstance *instance, GType iface_type ) 26 | 27 | HOOK_FUNC( gint, gtk_dialog_run, ( dialog ), GtkDialog *dialog ) 28 | HOOK_FUNC( GType, gtk_dialog_get_type, (), void ) 29 | 30 | HOOK_FUNC( gboolean, gtk_init_check, ( argc, argv ), int *argc, char ***argv ) 31 | HOOK_FUNC( gboolean, gtk_events_pending, (), void ) 32 | HOOK_FUNC( gboolean, gtk_main_iteration, (), void ) 33 | HOOK_FUNCV( void, gtk_widget_destroy, ( widget ), GtkWidget *widget ) 34 | 35 | HOOK_FUNC( GType, gtk_file_chooser_get_type, (), void ) 36 | HOOK_FUNC( gboolean, gtk_file_chooser_set_filename, (chooser, filename), GtkFileChooser *chooser, const char *filename ) 37 | HOOK_FUNCV( void, gtk_file_chooser_set_current_name, ( chooser, name ), GtkFileChooser *chooser, const gchar *name ) 38 | HOOK_FUNCV( void, gtk_file_chooser_set_do_overwrite_confirmation, ( chooser, do_overwrite_confirmation ), GtkFileChooser *chooser, gboolean do_overwrite_confirmation ) 39 | HOOK_FUNC( gchar *, gtk_file_chooser_get_filename, ( chooser ), GtkFileChooser *chooser ) 40 | HOOK_FUNC( GtkWidget *, gtk_file_chooser_dialog_new, ( title, parent, action, first_button_text, NULL ), const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ... ) 41 | HOOK_FUNCV( void, gtk_file_chooser_add_filter, ( chooser, filter ), GtkFileChooser *chooser, GtkFileFilter *filter ) 42 | 43 | HOOK_FUNC( GtkFileFilter *, gtk_file_filter_new, (), void ) 44 | HOOK_FUNCV( void, gtk_file_filter_set_name, ( filter, name ), GtkFileFilter *filter, const gchar *name ) 45 | HOOK_FUNCV( void, gtk_file_filter_add_pattern, ( filter, pattern ), GtkFileFilter *filter, const gchar *pattern ) 46 | -------------------------------------------------------------------------------- /src/i915-perf/i915-perf-read.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Intel Corporation 3 | * 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef _LARGEFILE64_SOURCE 26 | #define _LARGEFILE64_SOURCE 27 | #endif 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #ifdef USE_I915_PERF 44 | #include 45 | #include 46 | #include 47 | #include 48 | #endif 49 | 50 | #include "../gpuvis_macros.h" 51 | #include "../trace-cmd/trace-read.h" 52 | #include "i915-perf-read.h" 53 | 54 | void logf( const char *fmt, ... ) ATTRIBUTE_PRINTF( 1, 2 ); 55 | 56 | // xe functions are identical to i915 functions, except for use of 57 | // xe library data structs, #define's and function calls 58 | int read_xe_perf_file( const char *file, StrPool &strpool, trace_info_t &trace_info, struct intel_xe_perf_data_reader **out_reader, EventCallback &cb ) 59 | { 60 | GPUVIS_TRACE_BLOCK( __func__ ); 61 | 62 | #ifdef USE_I915_PERF 63 | int fd = open( file, O_RDONLY ); 64 | if ( fd < 0 ) 65 | { 66 | logf( "[Error] %s: opening xe-perf file failed: %s.\n", __func__, strerror( errno ) ); 67 | return -1; 68 | } 69 | 70 | *out_reader = new intel_xe_perf_data_reader; 71 | struct intel_xe_perf_data_reader *reader = *out_reader; 72 | 73 | if ( !intel_xe_perf_data_reader_init( reader, fd ) ) 74 | { 75 | logf( "[Error] %s: initializing xe-perf reader failed: %s.\n", __func__, reader->error_msg ); 76 | return -1; 77 | } 78 | 79 | trace_info.file = std::string(file); 80 | 81 | for (uint32_t i = 0; i < reader->n_timelines; i++) 82 | { 83 | trace_event_t event; 84 | 85 | if ( reader->timelines[i].cpu_ts_start < trace_info.min_file_ts ) 86 | continue; 87 | 88 | event.flags = TRACE_FLAG_I915_PERF; 89 | event.pid = reader->timelines[i].hw_id; 90 | event.cpu = 0; 91 | event.comm = strpool.getstr( "xe-perf" ); 92 | event.system = strpool.getstr( "xe-perf" ); 93 | event.user_comm = strpool.getstrf( "[xe-perf hw_id=0x%x]", reader->timelines[i].hw_id ); 94 | 95 | event.name = strpool.getstr( "xe-perf-begin" ); 96 | event.ts = reader->timelines[i].cpu_ts_start; 97 | event.duration = reader->timelines[i].cpu_ts_end - reader->timelines[i].cpu_ts_start; 98 | 99 | event.i915_perf_timeline = i; 100 | 101 | cb( event ); 102 | 103 | event.name = strpool.getstr( "xe-perf-end" ); 104 | event.ts = reader->timelines[i].cpu_ts_end - 1; 105 | event.duration = INT64_MAX; 106 | 107 | cb( event ); 108 | } 109 | #endif 110 | 111 | return 0; 112 | } 113 | 114 | int read_i915_perf_file( const char *file, StrPool &strpool, trace_info_t &trace_info, struct intel_perf_data_reader **out_reader, EventCallback &cb ) 115 | { 116 | GPUVIS_TRACE_BLOCK( __func__ ); 117 | 118 | #ifdef USE_I915_PERF 119 | int fd = open( file, O_RDONLY ); 120 | if ( fd < 0 ) 121 | { 122 | logf( "[Error] %s: opening i915-perf file failed: %s.\n", __func__, strerror( errno ) ); 123 | return -1; 124 | } 125 | 126 | *out_reader = new intel_perf_data_reader; 127 | struct intel_perf_data_reader *reader = *out_reader; 128 | 129 | if ( !intel_perf_data_reader_init( reader, fd ) ) 130 | { 131 | logf( "[Error] %s: initializing i915-perf reader failed: %s.\n", __func__, reader->error_msg ); 132 | return -1; 133 | } 134 | 135 | trace_info.file = std::string(file); 136 | 137 | for (uint32_t i = 0; i < reader->n_timelines; i++) 138 | { 139 | trace_event_t event; 140 | 141 | if ( reader->timelines[i].cpu_ts_start < trace_info.min_file_ts ) 142 | continue; 143 | 144 | // Abuse PID, this is kind of a similar concept... 145 | event.flags = TRACE_FLAG_I915_PERF; 146 | event.pid = reader->timelines[i].hw_id; 147 | event.cpu = 0; 148 | event.comm = strpool.getstr( "i915-perf" ); 149 | event.system = strpool.getstr( "i915-perf" ); 150 | event.user_comm = strpool.getstrf( "[i915-perf hw_id=0x%x]", reader->timelines[i].hw_id ); 151 | 152 | event.name = strpool.getstr( "i915-perf-begin" ); 153 | event.ts = reader->timelines[i].cpu_ts_start; 154 | event.duration = reader->timelines[i].cpu_ts_end - reader->timelines[i].cpu_ts_start; 155 | 156 | // This will track the timeline number and allow us to compute counter 157 | // deltas. 158 | event.i915_perf_timeline = i; 159 | 160 | cb( event ); 161 | 162 | event.name = strpool.getstr( "i915-perf-end" ); 163 | // The GPU context switch event happens on a single timestamp. Make 164 | // begin/end look like they happen at different time so that events 165 | // are ordered properly. 166 | event.ts = reader->timelines[i].cpu_ts_end - 1; 167 | event.duration = INT64_MAX; 168 | 169 | cb( event ); 170 | } 171 | #endif 172 | 173 | return 0; 174 | } 175 | 176 | #if USE_I915_PERF 177 | static uint64_t record_xe_timestamp( struct intel_xe_perf_data_reader *reader, 178 | const struct intel_xe_perf_record_header *record ) 179 | { 180 | return intel_xe_perf_read_record_timestamp(reader->perf, reader->metric_set, record); 181 | } 182 | 183 | static uint64_t record_timestamp( struct intel_perf_data_reader *reader, 184 | const struct drm_i915_perf_record_header *record ) 185 | { 186 | return intel_perf_read_record_timestamp(reader->perf, reader->metric_set, record); 187 | } 188 | #endif 189 | 190 | void load_xe_perf_counter_values( struct intel_xe_perf_data_reader *reader, 191 | struct intel_xe_perf_logical_counter *counter, 192 | const trace_event_t &event, I915CounterCallback &cb ) 193 | { 194 | #if USE_I915_PERF 195 | assert( event.i915_perf_timeline < reader->n_timelines ); 196 | 197 | const struct intel_xe_perf_timeline_item *item = &reader->timelines[ event.i915_perf_timeline ]; 198 | const struct intel_xe_perf_record_header *first_record = reader->records[ item->record_start ]; 199 | for ( uint32_t j = item->record_start; j < item->record_end; j++ ) 200 | { 201 | const struct intel_xe_perf_record_header *record = reader->records[j]; 202 | int64_t ts = item->cpu_ts_start + 203 | ( record_xe_timestamp( reader, record ) - record_xe_timestamp( reader, first_record ) ) * 204 | ( item->cpu_ts_end - item->cpu_ts_start ) / ( item->ts_end - item->ts_start ); 205 | struct intel_xe_perf_accumulator acc; 206 | 207 | intel_xe_perf_accumulate_reports( &acc, reader->perf, reader->metric_set, 208 | reader->records[j], reader->records[j + 1] ); 209 | 210 | float value; 211 | if ( counter->storage == INTEL_XE_PERF_LOGICAL_COUNTER_STORAGE_DOUBLE || 212 | counter->storage == INTEL_XE_PERF_LOGICAL_COUNTER_STORAGE_FLOAT ) 213 | { 214 | value = counter->read_float( reader->perf, reader->metric_set, acc.deltas ); 215 | } 216 | else 217 | { 218 | value = counter->read_uint64( reader->perf, reader->metric_set, acc.deltas ); 219 | } 220 | 221 | cb( event, ts, value / 1000000.0 ); // Report the frequency in MHz, not Hz 222 | } 223 | #endif 224 | } 225 | 226 | void load_i915_perf_counter_values( struct intel_perf_data_reader *reader, 227 | struct intel_perf_logical_counter *counter, 228 | const trace_event_t &event, I915CounterCallback &cb ) 229 | { 230 | #if USE_I915_PERF 231 | assert( event.i915_perf_timeline < reader->n_timelines ); 232 | 233 | const struct intel_perf_timeline_item *item = &reader->timelines[ event.i915_perf_timeline ]; 234 | const struct drm_i915_perf_record_header *first_record = reader->records[ item->record_start ]; 235 | for ( uint32_t j = item->record_start; j < item->record_end; j++ ) 236 | { 237 | const struct drm_i915_perf_record_header *record = reader->records[j]; 238 | int64_t ts = item->cpu_ts_start + 239 | ( record_timestamp( reader, record ) - record_timestamp( reader, first_record ) ) * 240 | ( item->cpu_ts_end - item->cpu_ts_start ) / ( item->ts_end - item->ts_start ); 241 | struct intel_perf_accumulator acc; 242 | 243 | intel_perf_accumulate_reports( &acc, reader->perf, reader->metric_set, 244 | reader->records[j], reader->records[j + 1] ); 245 | 246 | float value; 247 | if ( counter->storage == INTEL_PERF_LOGICAL_COUNTER_STORAGE_DOUBLE || 248 | counter->storage == INTEL_PERF_LOGICAL_COUNTER_STORAGE_FLOAT ) 249 | { 250 | value = counter->read_float( reader->perf, reader->metric_set, acc.deltas ); 251 | } 252 | else 253 | { 254 | value = counter->read_uint64( reader->perf, reader->metric_set, acc.deltas ); 255 | } 256 | 257 | cb( event, ts, value / 1000000.0 ); // Report the frequency in MHz, not Hz 258 | } 259 | #endif 260 | } 261 | 262 | struct intel_xe_perf_logical_counter *get_xe_perf_frequency_counter( struct intel_xe_perf_data_reader *reader ) 263 | { 264 | #if USE_I915_PERF 265 | struct intel_xe_perf_metric_set *metric_set = reader->metric_set; 266 | 267 | for ( uint32_t i = 0; i < metric_set->n_counters; i++ ) 268 | { 269 | struct intel_xe_perf_logical_counter *counter = &metric_set->counters[ i ]; 270 | 271 | if ( strcmp( counter->symbol_name, "AvgGpuCoreFrequency" ) == 0 ) 272 | { 273 | return counter; 274 | } 275 | } 276 | 277 | return NULL; 278 | #else 279 | return NULL; 280 | #endif 281 | } 282 | 283 | struct intel_perf_logical_counter *get_i915_perf_frequency_counter( struct intel_perf_data_reader *reader ) 284 | { 285 | #if USE_I915_PERF 286 | struct intel_perf_metric_set *metric_set = reader->metric_set; 287 | 288 | for ( uint32_t i = 0; i < metric_set->n_counters; i++ ) 289 | { 290 | struct intel_perf_logical_counter *counter = &metric_set->counters[ i ]; 291 | 292 | if ( strcmp( counter->symbol_name, "AvgGpuCoreFrequency" ) == 0 ) 293 | { 294 | return counter; 295 | } 296 | } 297 | 298 | return NULL; 299 | #else 300 | return NULL; 301 | #endif 302 | } 303 | -------------------------------------------------------------------------------- /src/i915-perf/i915-perf-read.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Intel Corporation 3 | * 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef I915_PERF_READ_H_ 26 | #define I915_PERF_READ_H_ 27 | 28 | #include 29 | 30 | #define __STDC_FORMAT_MACROS 31 | #include 32 | 33 | extern "C" { 34 | struct intel_perf_data_reader; 35 | struct intel_perf_logical_counter; 36 | struct intel_xe_perf_data_reader; 37 | struct intel_xe_perf_logical_counter; 38 | } 39 | 40 | typedef std::function< void ( const trace_event_t &event, int64_t ts, float value ) > I915CounterCallback; 41 | 42 | int read_i915_perf_file( const char *file, StrPool &strpool, trace_info_t &trace_info, struct intel_perf_data_reader **reader, EventCallback &cb ); 43 | struct intel_perf_logical_counter *get_i915_perf_frequency_counter( struct intel_perf_data_reader *reader ); 44 | void load_i915_perf_counter_values( struct intel_perf_data_reader *reader, 45 | struct intel_perf_logical_counter *counter, 46 | const trace_event_t &event, I915CounterCallback &cb ); 47 | 48 | int read_xe_perf_file( const char *file, StrPool &strpool, trace_info_t &trace_info, struct intel_xe_perf_data_reader **out_reader, EventCallback &cb ); 49 | struct intel_xe_perf_logical_counter *get_xe_perf_frequency_counter( struct intel_xe_perf_data_reader *reader ); 50 | void load_xe_perf_counter_values( struct intel_xe_perf_data_reader *reader, 51 | struct intel_xe_perf_logical_counter *counter, 52 | const trace_event_t &event, I915CounterCallback &cb ); 53 | 54 | #endif // I915_PERF_READ_H_ 55 | -------------------------------------------------------------------------------- /src/imgui/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // COMPILE-TIME OPTIONS FOR DEAR IMGUI 3 | // Most options (memory allocation, clipboard callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO(). 4 | //----------------------------------------------------------------------------- 5 | // A) You may edit imconfig.h (and not overwrite it when updating imgui, or maintain a patch/branch with your modifications to imconfig.h) 6 | // B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h" 7 | // Note that options such as IMGUI_API, IM_VEC2_CLASS_EXTRA or ImDrawIdx needs to be defined consistently everywhere you include imgui.h, not only for the imgui*.cpp compilation units. 8 | //----------------------------------------------------------------------------- 9 | 10 | #pragma once 11 | 12 | //---- Define assertion handler. Defaults to calling assert(). 13 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 14 | 15 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows. 16 | //#define IMGUI_API __declspec( dllexport ) 17 | //#define IMGUI_API __declspec( dllimport ) 18 | 19 | //---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce likelihood of using already obsolete function/names 20 | #define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 21 | 22 | //---- Don't implement default handlers for Windows (so as not to link with certain functions) 23 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // Don't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. 24 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // Don't use and link with ImmGetContext/ImmSetCompositionWindow. 25 | 26 | //---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) 27 | //---- It is very strongly recommended to NOT disable the demo windows. Please read the comment at the top of imgui_demo.cpp. 28 | //#define IMGUI_DISABLE_DEMO_WINDOWS 29 | 30 | //---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself. 31 | //#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS 32 | 33 | //---- Include imgui_user.h at the end of imgui.h as a convenience 34 | //#define IMGUI_INCLUDE_IMGUI_USER_H 35 | 36 | //---- Pack colors to BGRA8 instead of RGBA8 (if you needed to convert from one to another anyway) 37 | //#define IMGUI_USE_BGRA_PACKED_COLOR 38 | 39 | //---- Implement STB libraries in a namespace to avoid linkage conflicts (defaults to global namespace) 40 | //#define IMGUI_STB_NAMESPACE ImGuiStb 41 | 42 | //---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. 43 | // This will be inlined as part of ImVec2 and ImVec4 class declarations. 44 | /* 45 | #define IM_VEC2_CLASS_EXTRA \ 46 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ 47 | operator MyVec2() const { return MyVec2(x,y); } 48 | 49 | #define IM_VEC4_CLASS_EXTRA \ 50 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ 51 | operator MyVec4() const { return MyVec4(x,y,z,w); } 52 | */ 53 | 54 | //---- Use 32-bit vertex indices (instead of default 16-bit) to allow meshes with more than 64K vertices. Render function needs to support it. 55 | //#define ImDrawIdx unsigned int 56 | 57 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 58 | /* 59 | namespace ImGui 60 | { 61 | void MyFunction(const char* name, const MyMatrix44& v); 62 | } 63 | */ 64 | 65 | // Allow meshes with more than 64k indices (NB: probably a sign that we aren't clipping enough when using ImDrawList? but doesn't hurt/cost too much to have 32-bit indices anyway) 66 | #define ImDrawIdx unsigned int 67 | 68 | //$ TODO mikesart: quick hack to change text color until imgui gets official method. 69 | // https://github.com/ocornut/imgui/issues/902 70 | #define IMGUI_TEXT_ESCAPE_SKIP() \ 71 | if (c == '\033' && s[1] && s[2] && s[3] && s[4]) \ 72 | { \ 73 | s += 5; \ 74 | continue; \ 75 | } 76 | 77 | #define IMGUI_TEXT_ESCAPE_RENDER() \ 78 | if (c == '\033' && s[1] && s[2] && s[3] && s[4]) \ 79 | { \ 80 | const unsigned char *us = (const unsigned char *)s; \ 81 | col = IM_COL32(us[1], us[2], us[3], us[4]); \ 82 | s += 5; \ 83 | continue; \ 84 | } 85 | -------------------------------------------------------------------------------- /src/imgui/imgui_freetype.h: -------------------------------------------------------------------------------- 1 | // Wrapper to use Freetype (instead of stb_truetype) for Dear ImGui 2 | // Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype 3 | // Original code by @Vuhdo (Aleksei Skriabin), maintained by @ocornut 4 | 5 | #pragma once 6 | 7 | #include "imgui.h" // IMGUI_API, ImFontAtlas 8 | 9 | namespace ImGuiFreeType 10 | { 11 | // Hinting greatly impacts visuals (and glyph sizes). 12 | // When disabled, FreeType generates blurrier glyphs, more or less matches the stb's output. 13 | // The Default hinting mode usually looks good, but may distort glyphs in an unusual way. 14 | // The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer. 15 | 16 | // You can set those flags on a per font basis in ImFontConfig::RasterizerFlags. 17 | // Use the 'extra_flags' parameter of BuildFontAtlas() to force a flag on all your fonts. 18 | enum RasterizerFlags 19 | { 20 | // By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter. 21 | NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes. 22 | NoAutoHint = 1 << 1, // Disable auto-hinter. 23 | ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter. 24 | LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text. 25 | MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output. 26 | Bold = 1 << 5, // Styling: Should we artificially embolden the font? 27 | Oblique = 1 << 6 // Styling: Should we slant the font, emulating italic style? 28 | }; 29 | 30 | IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0); 31 | } 32 | -------------------------------------------------------------------------------- /src/imgui/imgui_impl_sdl_gl3.h: -------------------------------------------------------------------------------- 1 | // ImGui SDL2 binding with OpenGL3 2 | // (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) 3 | // (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) 4 | 5 | // Implemented features: 6 | // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. 7 | 8 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 9 | // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). 10 | // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. 11 | // https://github.com/ocornut/imgui 12 | 13 | struct SDL_Window; 14 | typedef union SDL_Event SDL_Event; 15 | 16 | IMGUI_API bool ImGui_ImplSdlGL3_Init(SDL_Window* window); 17 | IMGUI_API void ImGui_ImplSdlGL3_Shutdown(); 18 | IMGUI_API void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window, bool *use_freetype); 19 | IMGUI_API void ImGui_ImplSdlGL3_RenderDrawData(ImDrawData* draw_data, float Gamma = 2.2f); 20 | IMGUI_API bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event); 21 | 22 | // Use if you want to reset your rendering device without losing ImGui state. 23 | IMGUI_API void ImGui_ImplSdlGL3_InvalidateDeviceObjects(); 24 | IMGUI_API bool ImGui_ImplSdlGL3_CreateDeviceObjects(bool *use_freetype); 25 | -------------------------------------------------------------------------------- /src/libtraceevent/README: -------------------------------------------------------------------------------- 1 | Upstream: https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 2 | 3 | Git Revision: d0fbd046a090834ac1ee69d45f321d7fa2a5c9b4 4 | 5 | Changes are marked with "gpuvis change!" 6 | -------------------------------------------------------------------------------- /src/libtraceevent/include/asm/bug.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #ifndef _TOOLS_ASM_BUG_H 3 | #define _TOOLS_ASM_BUG_H 4 | 5 | #include 6 | #include 7 | 8 | #ifdef _WIN32 /* gpuvis change! */ 9 | #define __WARN_printf(arg, ...) 10 | #else 11 | #define __WARN_printf(arg...) do { fprintf(stderr, arg); fprintf(stderr, "\n");} while (0) 12 | #endif 13 | 14 | #ifdef _WIN32 /* gpuvis change! */ 15 | #define WARN(condition, format, ...) 16 | #else 17 | #define WARN(condition, format...) ({ \ 18 | int __ret_warn_on = !!(condition); \ 19 | if (unlikely(__ret_warn_on)) \ 20 | __WARN_printf(format); \ 21 | unlikely(__ret_warn_on); \ 22 | }) 23 | #endif 24 | 25 | #define WARN_ON(condition) ({ \ 26 | int __ret_warn_on = !!(condition); \ 27 | if (unlikely(__ret_warn_on)) \ 28 | __WARN_printf("assertion failed at %s:%d\n", \ 29 | __FILE__, __LINE__); \ 30 | unlikely(__ret_warn_on); \ 31 | }) 32 | 33 | #define WARN_ON_ONCE(condition) ({ \ 34 | static int __warned; \ 35 | int __ret_warn_once = !!(condition); \ 36 | \ 37 | if (unlikely(__ret_warn_once && !__warned)) { \ 38 | __warned = true; \ 39 | WARN_ON(1); \ 40 | } \ 41 | unlikely(__ret_warn_once); \ 42 | }) 43 | 44 | #ifdef _WIN32 /* gpuvis change! */ 45 | #define WARN_ONCE(condition, format, ...) (0) 46 | #else 47 | #define WARN_ONCE(condition, format...) ({ \ 48 | static int __warned; \ 49 | int __ret_warn_once = !!(condition); \ 50 | \ 51 | if (unlikely(__ret_warn_once)) \ 52 | if (WARN(!__warned, format)) \ 53 | __warned = 1; \ 54 | unlikely(__ret_warn_once); \ 55 | }) 56 | #endif 57 | 58 | #endif /* _TOOLS_ASM_BUG_H */ 59 | -------------------------------------------------------------------------------- /src/libtraceevent/include/linux/compiler-gcc.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #ifndef _TOOLS_LINUX_COMPILER_H_ 3 | #error "Please don't include directly, include instead." 4 | #endif 5 | 6 | /* 7 | * Common definitions for all gcc versions go here. 8 | */ 9 | #ifndef GCC_VERSION 10 | #define GCC_VERSION (__GNUC__ * 10000 \ 11 | + __GNUC_MINOR__ * 100 \ 12 | + __GNUC_PATCHLEVEL__) 13 | #endif 14 | 15 | #if GCC_VERSION >= 70000 && !defined(__CHECKER__) 16 | # define __fallthrough __attribute__ ((fallthrough)) 17 | #endif 18 | 19 | #if GCC_VERSION >= 40300 20 | # define __compiletime_error(message) __attribute__((error(message))) 21 | #endif /* GCC_VERSION >= 40300 */ 22 | 23 | /* &a[0] degrades to a pointer: a different type from an array */ 24 | #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) 25 | 26 | #ifndef __pure 27 | #define __pure __attribute__((pure)) 28 | #endif 29 | #define noinline __attribute__((noinline)) 30 | #ifdef __has_attribute 31 | #if __has_attribute(disable_tail_calls) 32 | #define __no_tail_call __attribute__((disable_tail_calls)) 33 | #endif 34 | #endif 35 | #ifndef __no_tail_call 36 | #if GCC_VERSION > 40201 37 | #define __no_tail_call __attribute__((optimize("no-optimize-sibling-calls"))) 38 | #else 39 | #define __no_tail_call 40 | #endif 41 | #endif 42 | #ifndef __packed 43 | #define __packed __attribute__((packed)) 44 | #endif 45 | #ifndef __noreturn 46 | #define __noreturn __attribute__((noreturn)) 47 | #endif 48 | #ifndef __aligned 49 | #define __aligned(x) __attribute__((aligned(x))) 50 | #endif 51 | #define __printf(a, b) __attribute__((format(printf, a, b))) 52 | #define __scanf(a, b) __attribute__((format(scanf, a, b))) 53 | 54 | #if GCC_VERSION >= 50100 55 | #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 56 | #endif 57 | -------------------------------------------------------------------------------- /src/libtraceevent/include/linux/compiler.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #ifndef _TOOLS_LINUX_COMPILER_H_ 3 | #define _TOOLS_LINUX_COMPILER_H_ 4 | 5 | #ifdef __GNUC__ 6 | #include 7 | #endif 8 | 9 | #ifdef _WIN32 /* gpuvis change! */ 10 | #define __always_inline __inline 11 | #define __attribute__(a) 12 | #define __asm__ 13 | #define __maybe_unused 14 | #endif 15 | 16 | #ifndef __compiletime_error 17 | # define __compiletime_error(message) 18 | #endif 19 | 20 | #ifdef __OPTIMIZE__ 21 | # define __compiletime_assert(condition, msg, prefix, suffix) \ 22 | do { \ 23 | extern void prefix ## suffix(void) __compiletime_error(msg); \ 24 | if (!(condition)) \ 25 | prefix ## suffix(); \ 26 | } while (0) 27 | #else 28 | # define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0) 29 | #endif 30 | 31 | #define _compiletime_assert(condition, msg, prefix, suffix) \ 32 | __compiletime_assert(condition, msg, prefix, suffix) 33 | 34 | /** 35 | * compiletime_assert - break build and emit msg if condition is false 36 | * @condition: a compile-time constant condition to check 37 | * @msg: a message to emit if condition is false 38 | * 39 | * In tradition of POSIX assert, this macro will break the build if the 40 | * supplied condition is *false*, emitting the supplied error message if the 41 | * compiler has support to do so. 42 | */ 43 | #define compiletime_assert(condition, msg) \ 44 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) 45 | 46 | /* Optimization barrier */ 47 | /* The "volatile" is due to gcc bugs */ 48 | #ifdef _WIN32 /* gpuvis change! */ 49 | #define barrier() /* Hypothetically this could be MemoryBarrier or whatever */ 50 | #else 51 | #define barrier() __asm__ __volatile__("": : :"memory") 52 | #endif 53 | 54 | #ifndef __always_inline 55 | # define __always_inline inline __attribute__((always_inline)) 56 | #endif 57 | 58 | #ifndef noinline 59 | #define noinline 60 | #endif 61 | #ifndef __no_tail_call 62 | #define __no_tail_call 63 | #endif 64 | 65 | /* Are two types/vars the same type (ignoring qualifiers)? */ 66 | #ifndef __same_type 67 | # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) 68 | #endif 69 | 70 | #ifdef __ANDROID__ 71 | /* 72 | * FIXME: Big hammer to get rid of tons of: 73 | * "warning: always_inline function might not be inlinable" 74 | * 75 | * At least on android-ndk-r12/platforms/android-24/arch-arm 76 | */ 77 | #undef __always_inline 78 | #define __always_inline inline 79 | #endif 80 | 81 | #define __user 82 | #define __rcu 83 | #define __read_mostly 84 | 85 | #ifndef __attribute_const__ 86 | # define __attribute_const__ 87 | #endif 88 | 89 | #ifndef __maybe_unused 90 | # define __maybe_unused __attribute__((unused)) 91 | #endif 92 | 93 | #ifndef __used 94 | # define __used __attribute__((__unused__)) 95 | #endif 96 | 97 | #ifndef __packed 98 | # define __packed __attribute__((__packed__)) 99 | #endif 100 | 101 | #ifndef __force 102 | # define __force 103 | #endif 104 | 105 | #ifndef __weak 106 | # define __weak __attribute__((weak)) 107 | #endif 108 | 109 | #ifndef likely 110 | # define likely(x) __builtin_expect(!!(x), 1) 111 | #endif 112 | 113 | #ifndef unlikely 114 | # define unlikely(x) __builtin_expect(!!(x), 0) 115 | #endif 116 | 117 | #ifndef __init 118 | # define __init 119 | #endif 120 | 121 | #ifndef noinline 122 | # define noinline 123 | #endif 124 | 125 | #if !defined(__linux__) /* gpuvis change! */ 126 | #include 127 | typedef uint8_t __u8; 128 | typedef uint16_t __u16; 129 | typedef uint32_t __u32; 130 | typedef uint64_t __u64; 131 | #ifdef _WIN32 132 | #include 133 | #define __builtin_memcpy memcpy 134 | #endif 135 | #else 136 | #include 137 | #endif 138 | 139 | /* 140 | * Following functions are taken from kernel sources and 141 | * break aliasing rules in their original form. 142 | * 143 | * While kernel is compiled with -fno-strict-aliasing, 144 | * perf uses -Wstrict-aliasing=3 which makes build fail 145 | * under gcc 4.4. 146 | * 147 | * Using extra __may_alias__ type to allow aliasing 148 | * in this case. 149 | */ 150 | typedef __u8 __attribute__((__may_alias__)) __u8_alias_t; 151 | typedef __u16 __attribute__((__may_alias__)) __u16_alias_t; 152 | typedef __u32 __attribute__((__may_alias__)) __u32_alias_t; 153 | typedef __u64 __attribute__((__may_alias__)) __u64_alias_t; 154 | 155 | static __always_inline void __read_once_size(const volatile void *p, void *res, int size) 156 | { 157 | switch (size) { 158 | case 1: *(__u8_alias_t *) res = *(volatile __u8_alias_t *) p; break; 159 | case 2: *(__u16_alias_t *) res = *(volatile __u16_alias_t *) p; break; 160 | case 4: *(__u32_alias_t *) res = *(volatile __u32_alias_t *) p; break; 161 | case 8: *(__u64_alias_t *) res = *(volatile __u64_alias_t *) p; break; 162 | default: 163 | barrier(); 164 | __builtin_memcpy((void *)res, (const void *)p, size); 165 | barrier(); 166 | } 167 | } 168 | 169 | static __always_inline void __write_once_size(volatile void *p, void *res, int size) 170 | { 171 | switch (size) { 172 | case 1: *(volatile __u8_alias_t *) p = *(__u8_alias_t *) res; break; 173 | case 2: *(volatile __u16_alias_t *) p = *(__u16_alias_t *) res; break; 174 | case 4: *(volatile __u32_alias_t *) p = *(__u32_alias_t *) res; break; 175 | case 8: *(volatile __u64_alias_t *) p = *(__u64_alias_t *) res; break; 176 | default: 177 | barrier(); 178 | __builtin_memcpy((void *)p, (const void *)res, size); 179 | barrier(); 180 | } 181 | } 182 | 183 | /* 184 | * Prevent the compiler from merging or refetching reads or writes. The 185 | * compiler is also forbidden from reordering successive instances of 186 | * READ_ONCE and WRITE_ONCE, but only when the compiler is aware of some 187 | * particular ordering. One way to make the compiler aware of ordering is to 188 | * put the two invocations of READ_ONCE or WRITE_ONCE in different C 189 | * statements. 190 | * 191 | * These two macros will also work on aggregate data types like structs or 192 | * unions. If the size of the accessed data type exceeds the word size of 193 | * the machine (e.g., 32 bits or 64 bits) READ_ONCE() and WRITE_ONCE() will 194 | * fall back to memcpy and print a compile-time warning. 195 | * 196 | * Their two major use cases are: (1) Mediating communication between 197 | * process-level code and irq/NMI handlers, all running on the same CPU, 198 | * and (2) Ensuring that the compiler does not fold, spindle, or otherwise 199 | * mutilate accesses that either do not require ordering or that interact 200 | * with an explicit memory barrier or atomic instruction that provides the 201 | * required ordering. 202 | */ 203 | 204 | #define READ_ONCE(x) \ 205 | ({ \ 206 | union { typeof(x) __val; char __c[1]; } __u = \ 207 | { .__c = { 0 } }; \ 208 | __read_once_size(&(x), __u.__c, sizeof(x)); \ 209 | __u.__val; \ 210 | }) 211 | 212 | #define WRITE_ONCE(x, val) \ 213 | ({ \ 214 | union { typeof(x) __val; char __c[1]; } __u = \ 215 | { .__val = (val) }; \ 216 | __write_once_size(&(x), __u.__c, sizeof(x)); \ 217 | __u.__val; \ 218 | }) 219 | 220 | 221 | #ifndef __fallthrough 222 | # define __fallthrough 223 | #endif 224 | 225 | /* Indirect macros required for expanded argument pasting, eg. __LINE__. */ 226 | #define ___PASTE(a, b) a##b 227 | #define __PASTE(a, b) ___PASTE(a, b) 228 | 229 | #endif /* _TOOLS_LINUX_COMPILER_H */ 230 | -------------------------------------------------------------------------------- /src/libtraceevent/include/linux/time64.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | #ifndef _TOOLS_LINUX_TIME64_H 3 | #define _TOOLS_LINUX_TIME64_H 4 | 5 | #define MSEC_PER_SEC 1000L 6 | #define USEC_PER_MSEC 1000L 7 | #define NSEC_PER_USEC 1000L 8 | #define NSEC_PER_MSEC 1000000L 9 | #define USEC_PER_SEC 1000000L 10 | #define NSEC_PER_SEC 1000000000L 11 | #define FSEC_PER_SEC 1000000000000000LL 12 | 13 | #endif /* _LINUX_TIME64_H */ 14 | -------------------------------------------------------------------------------- /src/libtraceevent/src/event-parse-api.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | 7 | #include "event-parse.h" 8 | #include "event-parse-local.h" 9 | #include "event-utils.h" 10 | 11 | /** 12 | * tep_get_event - returns the event with the given index 13 | * @tep: a handle to the tep_handle 14 | * @index: index of the requested event, in the range 0 .. nr_events 15 | * 16 | * This returns pointer to the element of the events array with the given index 17 | * If @tep is NULL, or @index is not in the range 0 .. nr_events, NULL is returned. 18 | */ 19 | struct tep_event *tep_get_event(struct tep_handle *tep, int index) 20 | { 21 | if (tep && tep->events && index < tep->nr_events) 22 | return tep->events[index]; 23 | 24 | return NULL; 25 | } 26 | 27 | /** 28 | * tep_get_first_event - returns the first event in the events array 29 | * @tep: a handle to the tep_handle 30 | * 31 | * This returns pointer to the first element of the events array 32 | * If @tep is NULL, NULL is returned. 33 | */ 34 | struct tep_event *tep_get_first_event(struct tep_handle *tep) 35 | { 36 | return tep_get_event(tep, 0); 37 | } 38 | 39 | /** 40 | * tep_get_events_count - get the number of defined events 41 | * @tep: a handle to the tep_handle 42 | * 43 | * This returns number of elements in event array 44 | * If @tep is NULL, 0 is returned. 45 | */ 46 | int tep_get_events_count(struct tep_handle *tep) 47 | { 48 | if (tep) 49 | return tep->nr_events; 50 | return 0; 51 | } 52 | 53 | /** 54 | * tep_set_flag - set event parser flag 55 | * @tep: a handle to the tep_handle 56 | * @flag: flag, or combination of flags to be set 57 | * can be any combination from enum tep_flag 58 | * 59 | * This sets a flag or combination of flags from enum tep_flag 60 | */ 61 | void tep_set_flag(struct tep_handle *tep, int flag) 62 | { 63 | if (tep) 64 | tep->flags |= flag; 65 | } 66 | 67 | /** 68 | * tep_clear_flag - clear event parser flag 69 | * @tep: a handle to the tep_handle 70 | * @flag: flag to be cleared 71 | * 72 | * This clears a tep flag 73 | */ 74 | void tep_clear_flag(struct tep_handle *tep, enum tep_flag flag) 75 | { 76 | if (tep) 77 | tep->flags &= ~flag; 78 | } 79 | 80 | /** 81 | * tep_test_flag - check the state of event parser flag 82 | * @tep: a handle to the tep_handle 83 | * @flag: flag to be checked 84 | * 85 | * This returns the state of the requested tep flag. 86 | * Returns: true if the flag is set, false otherwise. 87 | */ 88 | bool tep_test_flag(struct tep_handle *tep, enum tep_flag flag) 89 | { 90 | if (tep) 91 | return tep->flags & flag; 92 | return false; 93 | } 94 | 95 | __hidden unsigned short data2host2(struct tep_handle *tep, unsigned short data) 96 | { 97 | unsigned short swap; 98 | 99 | if (!tep || tep->host_bigendian == tep->file_bigendian) 100 | return data; 101 | 102 | swap = ((data & 0xffULL) << 8) | 103 | ((data & (0xffULL << 8)) >> 8); 104 | 105 | return swap; 106 | } 107 | 108 | __hidden unsigned int data2host4(struct tep_handle *tep, unsigned int data) 109 | { 110 | unsigned int swap; 111 | 112 | if (!tep || tep->host_bigendian == tep->file_bigendian) 113 | return data; 114 | 115 | swap = ((data & 0xffULL) << 24) | 116 | ((data & (0xffULL << 8)) << 8) | 117 | ((data & (0xffULL << 16)) >> 8) | 118 | ((data & (0xffULL << 24)) >> 24); 119 | 120 | return swap; 121 | } 122 | 123 | __hidden unsigned long long 124 | data2host8(struct tep_handle *tep, unsigned long long data) 125 | { 126 | unsigned long long swap; 127 | 128 | if (!tep || tep->host_bigendian == tep->file_bigendian) 129 | return data; 130 | 131 | swap = ((data & 0xffULL) << 56) | 132 | ((data & (0xffULL << 8)) << 40) | 133 | ((data & (0xffULL << 16)) << 24) | 134 | ((data & (0xffULL << 24)) << 8) | 135 | ((data & (0xffULL << 32)) >> 8) | 136 | ((data & (0xffULL << 40)) >> 24) | 137 | ((data & (0xffULL << 48)) >> 40) | 138 | ((data & (0xffULL << 56)) >> 56); 139 | 140 | return swap; 141 | } 142 | 143 | /** 144 | * tep_get_header_page_size - get size of the header page 145 | * @tep: a handle to the tep_handle 146 | * 147 | * This returns size of the header page 148 | * If @tep is NULL, 0 is returned. 149 | */ 150 | int tep_get_header_page_size(struct tep_handle *tep) 151 | { 152 | if (tep) 153 | return tep->header_page_size_size; 154 | return 0; 155 | } 156 | 157 | /** 158 | * tep_get_header_timestamp_size - get size of the timestamp in the header page 159 | * @tep: a handle to the tep_handle 160 | * 161 | * This returns size of the timestamp in the header page 162 | * If @tep is NULL, 0 is returned. 163 | */ 164 | int tep_get_header_timestamp_size(struct tep_handle *tep) 165 | { 166 | if (tep) 167 | return tep->header_page_ts_size; 168 | return 0; 169 | } 170 | 171 | /** 172 | * tep_get_cpus - get the number of CPUs 173 | * @tep: a handle to the tep_handle 174 | * 175 | * This returns the number of CPUs 176 | * If @tep is NULL, 0 is returned. 177 | */ 178 | int tep_get_cpus(struct tep_handle *tep) 179 | { 180 | if (tep) 181 | return tep->cpus; 182 | return 0; 183 | } 184 | 185 | /** 186 | * tep_set_cpus - set the number of CPUs 187 | * @tep: a handle to the tep_handle 188 | * 189 | * This sets the number of CPUs 190 | */ 191 | void tep_set_cpus(struct tep_handle *tep, int cpus) 192 | { 193 | if (tep) 194 | tep->cpus = cpus; 195 | } 196 | 197 | /** 198 | * tep_get_long_size - get the size of a long integer on the traced machine 199 | * @tep: a handle to the tep_handle 200 | * 201 | * This returns the size of a long integer on the traced machine 202 | * If @tep is NULL, 0 is returned. 203 | */ 204 | int tep_get_long_size(struct tep_handle *tep) 205 | { 206 | if (tep) 207 | return tep->long_size; 208 | return 0; 209 | } 210 | 211 | /** 212 | * tep_set_long_size - set the size of a long integer on the traced machine 213 | * @tep: a handle to the tep_handle 214 | * @size: size, in bytes, of a long integer 215 | * 216 | * This sets the size of a long integer on the traced machine 217 | */ 218 | void tep_set_long_size(struct tep_handle *tep, int long_size) 219 | { 220 | if (tep) 221 | tep->long_size = long_size; 222 | } 223 | 224 | /** 225 | * tep_get_page_size - get the size of a memory page on the traced machine 226 | * @tep: a handle to the tep_handle 227 | * 228 | * This returns the size of a memory page on the traced machine 229 | * If @tep is NULL, 0 is returned. 230 | */ 231 | int tep_get_page_size(struct tep_handle *tep) 232 | { 233 | if (tep) 234 | return tep->page_size; 235 | return 0; 236 | } 237 | 238 | /** 239 | * tep_set_page_size - set the size of a memory page on the traced machine 240 | * @tep: a handle to the tep_handle 241 | * @_page_size: size of a memory page, in bytes 242 | * 243 | * This sets the size of a memory page on the traced machine 244 | */ 245 | void tep_set_page_size(struct tep_handle *tep, int _page_size) 246 | { 247 | if (tep) 248 | tep->page_size = _page_size; 249 | } 250 | 251 | /** 252 | * tep_is_file_bigendian - return the endian of the file 253 | * @tep: a handle to the tep_handle 254 | * 255 | * This returns true if the file is in big endian order 256 | * If @tep is NULL, false is returned. 257 | */ 258 | bool tep_is_file_bigendian(struct tep_handle *tep) 259 | { 260 | if (tep) 261 | return (tep->file_bigendian == TEP_BIG_ENDIAN); 262 | return false; 263 | } 264 | 265 | /** 266 | * tep_set_file_bigendian - set if the file is in big endian order 267 | * @tep: a handle to the tep_handle 268 | * @endian: non zero, if the file is in big endian order 269 | * 270 | * This sets if the file is in big endian order 271 | */ 272 | void tep_set_file_bigendian(struct tep_handle *tep, enum tep_endian endian) 273 | { 274 | if (tep) 275 | tep->file_bigendian = endian; 276 | } 277 | 278 | /** 279 | * tep_is_local_bigendian - return the endian of the saved local machine 280 | * @tep: a handle to the tep_handle 281 | * 282 | * This returns true if the saved local machine in @tep is big endian. 283 | * If @tep is NULL, false is returned. 284 | */ 285 | bool tep_is_local_bigendian(struct tep_handle *tep) 286 | { 287 | if (tep) 288 | return (tep->host_bigendian == TEP_BIG_ENDIAN); 289 | return 0; 290 | } 291 | 292 | /** 293 | * tep_set_local_bigendian - set the stored local machine endian order 294 | * @tep: a handle to the tep_handle 295 | * @endian: non zero, if the local host has big endian order 296 | * 297 | * This sets the endian order for the local machine. 298 | */ 299 | void tep_set_local_bigendian(struct tep_handle *tep, enum tep_endian endian) 300 | { 301 | if (tep) 302 | tep->host_bigendian = endian; 303 | } 304 | 305 | /** 306 | * tep_is_old_format - get if an old kernel is used 307 | * @tep: a handle to the tep_handle 308 | * 309 | * This returns true, if an old kernel is used to generate the tracing events or 310 | * false if a new kernel is used. Old kernels did not have header page info. 311 | * If @tep is NULL, false is returned. 312 | */ 313 | bool tep_is_old_format(struct tep_handle *tep) 314 | { 315 | if (tep) 316 | return tep->old_format; 317 | return false; 318 | } 319 | 320 | /** 321 | * tep_set_test_filters - set a flag to test a filter string 322 | * @tep: a handle to the tep_handle 323 | * @test_filters: the new value of the test_filters flag 324 | * 325 | * This sets a flag to test a filter string. If this flag is set, when 326 | * tep_filter_add_filter_str() API as called,it will print the filter string 327 | * instead of adding it. 328 | */ 329 | void tep_set_test_filters(struct tep_handle *tep, int test_filters) 330 | { 331 | if (tep) 332 | tep->test_filters = test_filters; 333 | } 334 | -------------------------------------------------------------------------------- /src/libtraceevent/src/event-parse-local.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | 7 | #ifndef _PARSE_EVENTS_INT_H 8 | #define _PARSE_EVENTS_INT_H 9 | 10 | struct tep_cmdline; 11 | struct cmdline_list; 12 | struct func_map; 13 | struct func_list; 14 | struct event_handler; 15 | struct func_resolver; 16 | struct tep_plugins_dir; 17 | 18 | #ifdef _WIN32 /* gpuvis change! */ 19 | #define __hidden 20 | #else 21 | #define __hidden __attribute__((visibility ("hidden"))) 22 | #endif 23 | 24 | struct tep_handle { 25 | int ref_count; 26 | 27 | int header_page_ts_offset; 28 | int header_page_ts_size; 29 | int header_page_size_offset; 30 | int header_page_size_size; 31 | int header_page_data_offset; 32 | int header_page_data_size; 33 | int header_page_overwrite; 34 | 35 | enum tep_endian file_bigendian; 36 | enum tep_endian host_bigendian; 37 | 38 | int old_format; 39 | 40 | int cpus; 41 | int long_size; 42 | int page_size; 43 | 44 | struct tep_cmdline *cmdlines; 45 | struct cmdline_list *cmdlist; 46 | int cmdline_count; 47 | 48 | struct func_map *func_map; 49 | struct func_resolver *func_resolver; 50 | struct func_list *funclist; 51 | unsigned int func_count; 52 | 53 | struct printk_map *printk_map; 54 | struct printk_list *printklist; 55 | unsigned int printk_count; 56 | 57 | /* gpuvis change! */ 58 | int *tgid_map; 59 | unsigned int tgid_count; 60 | 61 | struct tep_event **events; 62 | int nr_events; 63 | struct tep_event **sort_events; 64 | enum tep_event_sort_type last_type; 65 | 66 | int type_offset; 67 | int type_size; 68 | 69 | int pid_offset; 70 | int pid_size; 71 | 72 | int pc_offset; 73 | int pc_size; 74 | 75 | int flags_offset; 76 | int flags_size; 77 | 78 | int ld_offset; 79 | int ld_size; 80 | 81 | int test_filters; 82 | 83 | int flags; 84 | 85 | struct tep_format_field *bprint_ip_field; 86 | struct tep_format_field *bprint_fmt_field; 87 | struct tep_format_field *bprint_buf_field; 88 | 89 | struct event_handler *handlers; 90 | struct tep_function_handler *func_handlers; 91 | 92 | /* cache */ 93 | struct tep_event *last_event; 94 | 95 | struct tep_plugins_dir *plugins_dir; 96 | }; 97 | 98 | enum tep_print_parse_type { 99 | PRINT_FMT_STRING, 100 | PRINT_FMT_ARG_DIGIT, 101 | PRINT_FMT_ARG_POINTER, 102 | PRINT_FMT_ARG_STRING, 103 | }; 104 | 105 | struct tep_print_parse { 106 | struct tep_print_parse *next; 107 | 108 | char *format; 109 | int ls; 110 | enum tep_print_parse_type type; 111 | struct tep_print_arg *arg; 112 | struct tep_print_arg *len_as_arg; 113 | }; 114 | 115 | void free_tep_event(struct tep_event *event); 116 | void free_tep_format_field(struct tep_format_field *field); 117 | void free_tep_plugin_paths(struct tep_handle *tep); 118 | 119 | unsigned short data2host2(struct tep_handle *tep, unsigned short data); 120 | unsigned int data2host4(struct tep_handle *tep, unsigned int data); 121 | unsigned long long data2host8(struct tep_handle *tep, unsigned long long data); 122 | 123 | /* access to the internal parser */ 124 | int peek_char(void); 125 | void init_input_buf(const char *buf, unsigned long long size); 126 | unsigned long long get_input_buf_ptr(void); 127 | const char *get_input_buf(void); 128 | enum tep_event_type read_token(char **tok); 129 | void free_token(char *tok); 130 | 131 | #endif /* _PARSE_EVENTS_INT_H */ 132 | -------------------------------------------------------------------------------- /src/libtraceevent/src/event-utils.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Copyright (C) 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #ifndef __TEP_EVENT_UTIL_H 7 | #define __TEP_EVENT_UTIL_H 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "event-parse.h" 14 | 15 | void tep_warning(const char *fmt, ...); 16 | void tep_info(const char *fmt, ...); 17 | 18 | /* Can be overridden */ 19 | int tep_vprint(const char *name, enum tep_loglevel level, 20 | bool print_err, const char *fmt, va_list ap); 21 | 22 | /* The actual call of tep_vprint() for overrides to use */ 23 | int __tep_vprint(const char *name, enum tep_loglevel level, 24 | bool print_err, const char *fmt, va_list ap); 25 | 26 | 27 | #ifdef _WIN32 /* gpuvis change! */ 28 | #define __deprecated(msg) 29 | #else 30 | #define __deprecated(msg) __attribute__((deprecated("msg"))) 31 | #endif 32 | 33 | /* For backward compatibilty, do not use */ 34 | int tep_vwarning(const char *name, const char *fmt, va_list ap) __deprecated(Use tep_vprint instead); 35 | void pr_stat(const char *fmt, ...) __deprecated(Use tep_info instead); 36 | void vpr_stat(const char *fmt, va_list ap) __deprecated(Use tep_vprint instead); 37 | void __pr_stat(const char *fmt, ...) __deprecated(Use tep_info instead);; 38 | void __vpr_stat(const char *fmt, va_list ap) __deprecated(Use tep_vprint instead);; 39 | 40 | #ifndef _WIN32 /* gpuvis change! */ 41 | #define min(x, y) ({ \ 42 | typeof(x) _min1 = (x); \ 43 | typeof(y) _min2 = (y); \ 44 | (void) (&_min1 == &_min2); \ 45 | _min1 < _min2 ? _min1 : _min2; }) 46 | #endif 47 | 48 | static inline char *strim(char *string) 49 | { 50 | char *ret; 51 | 52 | if (!string) 53 | return NULL; 54 | while (*string) { 55 | if (!isspace(*string)) 56 | break; 57 | string++; 58 | } 59 | ret = string; 60 | 61 | string = ret + strlen(ret) - 1; 62 | while (string > ret) { 63 | if (!isspace(*string)) 64 | break; 65 | string--; 66 | } 67 | string[1] = 0; 68 | 69 | return ret; 70 | } 71 | 72 | static inline int has_text(const char *text) 73 | { 74 | if (!text) 75 | return 0; 76 | 77 | while (*text) { 78 | if (!isspace(*text)) 79 | return 1; 80 | text++; 81 | } 82 | 83 | return 0; 84 | } 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/libtraceevent/src/kbuffer.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1 */ 2 | /* 3 | * Copyright (C) 2012 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #ifndef _KBUFFER_H 7 | #define _KBUFFER_H 8 | 9 | #ifndef TS_SHIFT 10 | #define TS_SHIFT 27 11 | #endif 12 | 13 | enum kbuffer_endian { 14 | KBUFFER_ENDIAN_BIG, 15 | KBUFFER_ENDIAN_LITTLE, 16 | }; 17 | 18 | enum kbuffer_long_size { 19 | KBUFFER_LSIZE_4, 20 | KBUFFER_LSIZE_8, 21 | }; 22 | 23 | enum { 24 | KBUFFER_TYPE_PADDING = 29, 25 | KBUFFER_TYPE_TIME_EXTEND = 30, 26 | KBUFFER_TYPE_TIME_STAMP = 31, 27 | }; 28 | 29 | struct kbuffer; 30 | 31 | struct kbuffer *kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian); 32 | void kbuffer_free(struct kbuffer *kbuf); 33 | int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer); 34 | void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts); 35 | void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts); 36 | unsigned long long kbuffer_timestamp(struct kbuffer *kbuf); 37 | unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf); 38 | unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr); 39 | 40 | void *kbuffer_translate_data(int swap, void *data, unsigned int *size); 41 | 42 | void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset, unsigned long long *ts); 43 | 44 | int kbuffer_curr_index(struct kbuffer *kbuf); 45 | 46 | int kbuffer_curr_offset(struct kbuffer *kbuf); 47 | int kbuffer_curr_size(struct kbuffer *kbuf); 48 | int kbuffer_event_size(struct kbuffer *kbuf); 49 | int kbuffer_missed_events(struct kbuffer *kbuf); 50 | int kbuffer_subbuffer_size(struct kbuffer *kbuf); 51 | 52 | void kbuffer_set_old_format(struct kbuffer *kbuf); 53 | int kbuffer_start_of_data(struct kbuffer *kbuf); 54 | 55 | /* Debugging */ 56 | 57 | struct kbuffer_raw_info { 58 | int type; 59 | int length; 60 | unsigned long long delta; 61 | void *next; 62 | }; 63 | 64 | /* Read raw data */ 65 | struct kbuffer_raw_info *kbuffer_raw_get(struct kbuffer *kbuf, void *subbuf, 66 | struct kbuffer_raw_info *info); 67 | 68 | #endif /* _K_BUFFER_H */ 69 | -------------------------------------------------------------------------------- /src/libtraceevent/src/parse-utils.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "event-utils.h" 13 | #include "event-parse.h" 14 | 15 | #ifdef _WIN32 /* gpuvis change! */ 16 | #define __weak 17 | #else 18 | #define __weak __attribute__((weak)) 19 | #endif 20 | 21 | static int log_level = TEP_LOG_CRITICAL; 22 | 23 | /** 24 | * tep_set_loglevel - set log level of the library 25 | * @level: desired level of the library messages 26 | */ 27 | void tep_set_loglevel(enum tep_loglevel level) 28 | { 29 | log_level = level; 30 | } 31 | 32 | /** 33 | * tep_vprint - print library log messages 34 | * @name: name of the library. 35 | * @level: severity of the log message. This parameter is not used in this implementation, but as 36 | * the function is weak and can be overridden, having the log level could be useful 37 | * for other implementations. 38 | * @print_err: whether to print the errno, if non zero. 39 | * @fmt: printf format string of the message. 40 | * @ap: list of printf parameters. 41 | * 42 | * This function is used to print all messages from traceevent, tracefs and trace-cmd libraries. 43 | * It is defined as weak, so the application that uses those libraries can override it in order 44 | * to implement its own logic for printing library logs. 45 | * 46 | * Return the value of errno at the function enter. 47 | */ 48 | int __weak tep_vprint(const char *name, enum tep_loglevel level, 49 | bool print_err, const char *fmt, va_list ap) 50 | { 51 | return __tep_vprint(name, level, print_err, fmt, ap); 52 | } 53 | 54 | /** 55 | * __tep_vprint - print library log messages 56 | * @name: name of the library. 57 | * @level: severity of the log message. This parameter is not used in this implementation, but as 58 | * the function is weak and can be overridden, having the log level could be useful 59 | * for other implementations. 60 | * @print_err: whether to print the errno, if non zero. 61 | * @fmt: printf format string of the message. 62 | * @ap: list of printf parameters. 63 | * 64 | * This function is used to print all messages from traceevent, tracefs and trace-cmd libraries. 65 | * It is defined as weak, so the application that uses those libraries can override it in order 66 | * to implement its own logic for printing library logs. 67 | * 68 | * Return the value of errno at the function enter. 69 | */ 70 | int __tep_vprint(const char *name, enum tep_loglevel level, 71 | bool print_err, const char *fmt, va_list ap) 72 | { 73 | int ret = errno; 74 | 75 | if (errno && print_err) 76 | perror(name); 77 | 78 | fprintf(stderr, " "); 79 | vfprintf(stderr, fmt, ap); 80 | fprintf(stderr, "\n"); 81 | 82 | return ret; 83 | } 84 | 85 | void tep_warning(const char *fmt, ...) 86 | { 87 | va_list ap; 88 | 89 | if (log_level < TEP_LOG_WARNING) 90 | return; 91 | 92 | va_start(ap, fmt); 93 | tep_vprint("libtraceevent", TEP_LOG_WARNING, true, fmt, ap); 94 | va_end(ap); 95 | } 96 | 97 | 98 | void tep_info(const char *fmt, ...) 99 | { 100 | va_list ap; 101 | 102 | if (log_level < TEP_LOG_INFO) 103 | return; 104 | 105 | va_start(ap, fmt); 106 | tep_vprint("libtraceevent", TEP_LOG_INFO, false, fmt, ap); 107 | va_end(ap); 108 | } 109 | 110 | /* The below is for backward compatibility */ 111 | int __weak tep_vwarning(const char *name, const char *fmt, va_list ap) 112 | { 113 | return tep_vprint(name, TEP_LOG_WARNING, true, fmt, ap); 114 | } 115 | 116 | void pr_stat(const char *fmt, ...) 117 | #if !defined(__APPLE__) && !defined(_WIN32) /* gpuvis change! */ 118 | __attribute__((weak, alias("tep_info"))) 119 | #endif 120 | ; 121 | void __pr_stat(const char *fmt, ...) 122 | #if !defined(__APPLE__) && !defined(_WIN32) /* gpuvis change! */ 123 | __attribute__((weak, alias("tep_info"))) 124 | #endif 125 | ; 126 | 127 | void __weak __vpr_stat(const char *fmt, va_list ap) 128 | { 129 | tep_vprint("libtraceevent", TEP_LOG_INFO, false, fmt, ap); 130 | } 131 | 132 | void vpr_stat(const char *fmt, va_list ap) 133 | #if !defined(__APPLE__) && !defined(_WIN32) /* gpuvis change! */ 134 | __attribute__((weak, alias("__vpr_stat"))) 135 | #endif 136 | ; 137 | -------------------------------------------------------------------------------- /src/libtraceevent/src/tep_strerror.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | #undef _GNU_SOURCE 3 | #include 4 | #include 5 | 6 | #include "event-parse.h" 7 | 8 | #undef _PE 9 | #define _PE(code, str) str 10 | static const char * const tep_error_str[] = { 11 | TEP_ERRORS 12 | }; 13 | #undef _PE 14 | 15 | /* 16 | * The tools so far have been using the strerror_r() GNU variant, that returns 17 | * a string, be it the buffer passed or something else. 18 | * 19 | * But that, besides being tricky in cases where we expect that the function 20 | * using strerror_r() returns the error formatted in a provided buffer (we have 21 | * to check if it returned something else and copy that instead), breaks the 22 | * build on systems not using glibc, like Alpine Linux, where musl libc is 23 | * used. 24 | * 25 | * So, introduce yet another wrapper, str_error_r(), that has the GNU 26 | * interface, but uses the portable XSI variant of strerror_r(), so that users 27 | * rest asured that the provided buffer is used and it is what is returned. 28 | */ 29 | int tep_strerror(struct tep_handle *tep __maybe_unused, 30 | enum tep_errno errnum, char *buf, size_t buflen) 31 | { 32 | const char *msg; 33 | int idx; 34 | 35 | if (!buflen) 36 | return 0; 37 | 38 | if (errnum >= 0) { 39 | int err = strerror_r(errnum, buf, buflen); 40 | buf[buflen - 1] = 0; 41 | return err; 42 | } 43 | 44 | if (errnum <= __TEP_ERRNO__START || 45 | errnum >= __TEP_ERRNO__END) 46 | return -1; 47 | 48 | idx = errnum - __TEP_ERRNO__START - 1; 49 | msg = tep_error_str[idx]; 50 | snprintf(buf, buflen, "%s", msg); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /src/libtraceevent/src/trace-seq.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2009 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | #include "trace-seq.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include "event-parse.h" 15 | #include "event-utils.h" 16 | 17 | #include "../../gpuvis_macros.h" /* gpuvis change! */ 18 | 19 | /* 20 | * The TRACE_SEQ_POISON is to catch the use of using 21 | * a trace_seq structure after it was destroyed. 22 | */ 23 | #define TRACE_SEQ_POISON ((void *)0xdeadbeef) 24 | #ifdef _WIN32 /* gpuvis change! */ 25 | #define TRACE_SEQ_CHECK(s) 26 | #define TRACE_SEQ_CHECK_RET_N(s, n) 27 | #define TRACE_SEQ_CHECK_RET(s) 28 | #define TRACE_SEQ_CHECK_RET0(s) 29 | #else 30 | #define TRACE_SEQ_CHECK(s) \ 31 | do { \ 32 | if (WARN_ONCE((s)->buffer == TRACE_SEQ_POISON, \ 33 | "Usage of trace_seq after it was destroyed")) \ 34 | (s)->state = TRACE_SEQ__BUFFER_POISONED; \ 35 | } while (0) 36 | 37 | #define TRACE_SEQ_CHECK_RET_N(s, n) \ 38 | do { \ 39 | TRACE_SEQ_CHECK(s); \ 40 | if ((s)->state != TRACE_SEQ__GOOD) \ 41 | return n; \ 42 | } while (0) 43 | 44 | #define TRACE_SEQ_CHECK_RET(s) TRACE_SEQ_CHECK_RET_N(s, ) 45 | #define TRACE_SEQ_CHECK_RET0(s) TRACE_SEQ_CHECK_RET_N(s, 0) 46 | #endif 47 | 48 | /** 49 | * trace_seq_init - initialize the trace_seq structure 50 | * @s: a pointer to the trace_seq structure to initialize 51 | */ 52 | void trace_seq_init(struct trace_seq *s) 53 | { 54 | s->len = 0; 55 | /* s->readpos = 0; */ 56 | s->buffer_size = TRACE_SEQ_BUF_SIZE; 57 | s->buffer = s->buf; /* gpuvis change! malloc(s->buffer_size); */ 58 | if (s->buffer != NULL) 59 | s->state = TRACE_SEQ__GOOD; 60 | else 61 | s->state = TRACE_SEQ__MEM_ALLOC_FAILED; 62 | } 63 | 64 | /** 65 | * trace_seq_reset - re-initialize the trace_seq structure 66 | * @s: a pointer to the trace_seq structure to reset 67 | */ 68 | void trace_seq_reset(struct trace_seq *s) 69 | { 70 | if (!s) 71 | return; 72 | TRACE_SEQ_CHECK(s); 73 | s->len = 0; 74 | /* gpuvis change! s->readpos = 0; */ 75 | } 76 | 77 | /** 78 | * trace_seq_destroy - free up memory of a trace_seq 79 | * @s: a pointer to the trace_seq to free the buffer 80 | * 81 | * Only frees the buffer, not the trace_seq struct itself. 82 | */ 83 | void trace_seq_destroy(struct trace_seq *s) 84 | { 85 | if (!s) 86 | return; 87 | TRACE_SEQ_CHECK_RET(s); 88 | if (s->buffer != s->buf) /* gpuvis change! */ 89 | { 90 | free(s->buffer); 91 | s->buffer = TRACE_SEQ_POISON; 92 | } 93 | } 94 | 95 | static void expand_buffer(struct trace_seq *s) 96 | { 97 | char *buf; 98 | 99 | if (s->buffer == s->buf) /* gpuvis change! */ 100 | { 101 | buf = malloc(s->buffer_size + TRACE_SEQ_BUF_SIZE); 102 | if (WARN_ONCE(!buf, "Can't allocate trace_seq buffer memory")) { 103 | s->state = TRACE_SEQ__MEM_ALLOC_FAILED; 104 | return; 105 | } 106 | } 107 | else 108 | { 109 | buf = realloc(s->buffer, s->buffer_size + TRACE_SEQ_BUF_SIZE); 110 | if (WARN_ONCE(!buf, "Can't allocate trace_seq buffer memory")) { 111 | s->state = TRACE_SEQ__MEM_ALLOC_FAILED; 112 | return; 113 | } 114 | } 115 | 116 | s->buffer = buf; 117 | s->buffer_size += TRACE_SEQ_BUF_SIZE; 118 | } 119 | 120 | /* gpuvis change! */ 121 | 122 | /* Fast format_decimal code taken from fmt library (and modified for C): 123 | * https://github.com/fmtlib/fmt/blob/master/include/fmt/format.h#L1079 124 | * http://fmtlib.net/latest/index.html 125 | * http://www.zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html 126 | */ 127 | #define BUFFER_SIZE 64 128 | 129 | /* Formats value in reverse and returns a pointer to the beginning. */ 130 | static char *format_decimal(char buf[BUFFER_SIZE], unsigned long long value) 131 | { 132 | char *ptr = buf + BUFFER_SIZE; 133 | static const char DIGITS[] = 134 | "0001020304050607080910111213141516171819" 135 | "2021222324252627282930313233343536373839" 136 | "4041424344454647484950515253545556575859" 137 | "6061626364656667686970717273747576777879" 138 | "8081828384858687888990919293949596979899"; 139 | 140 | *--ptr = 0; 141 | 142 | while (value >= 100) 143 | { 144 | /* Integer division is slow so do it for a group of two digits instead 145 | * of for every digit. The idea comes from the talk by Alexandrescu 146 | * "Three Optimization Tips for C++". See speed-test for a comparison. 147 | */ 148 | unsigned index = (unsigned int)((value % 100) * 2); 149 | 150 | value /= 100; 151 | *--ptr = DIGITS[index + 1]; 152 | *--ptr = DIGITS[index]; 153 | } 154 | 155 | if (value < 10) 156 | { 157 | *--ptr = (char)('0' + value); 158 | return ptr; 159 | } 160 | 161 | unsigned index = (unsigned int)(value * 2); 162 | *--ptr = DIGITS[index + 1]; 163 | *--ptr = DIGITS[index]; 164 | return ptr; 165 | } 166 | 167 | static char *format_signed(char buf[BUFFER_SIZE], long long value) 168 | { 169 | char *str; 170 | bool negative = (value < 0); 171 | unsigned long long abs_value = (unsigned long long)(value); 172 | 173 | if (negative) 174 | abs_value = 0 - abs_value; 175 | 176 | str = format_decimal(buf, abs_value); 177 | 178 | if (negative) 179 | *--str = '-'; 180 | 181 | #if 0 182 | char buf2[64]; 183 | sprintf(buf2, "%lld", value); 184 | if (strcmp(str, buf2)) 185 | printf("%s ERROR: %s != %s\n", __func__, buf, buf2); 186 | #endif 187 | return str; 188 | } 189 | 190 | int trace_seq_put_sval(struct trace_seq *s, long long val) 191 | { 192 | const char *str; 193 | char buf[BUFFER_SIZE]; 194 | 195 | str = format_signed(buf, val); 196 | trace_seq_puts(s, str); 197 | return 1; 198 | } 199 | 200 | int trace_seq_put_uval(struct trace_seq *s, unsigned long long val) 201 | { 202 | const char *str; 203 | char buf[BUFFER_SIZE]; 204 | 205 | str = format_decimal(buf, val); 206 | trace_seq_puts(s, str); 207 | return 1; 208 | } 209 | 210 | /* End gpuvis change! */ 211 | 212 | /** 213 | * trace_seq_printf - sequence printing of trace information 214 | * @s: trace sequence descriptor 215 | * @fmt: printf format string 216 | * 217 | * It returns 0 if the trace oversizes the buffer's free 218 | * space, the number of characters printed, or a negative 219 | * value in case of an error. 220 | * 221 | * The tracer may use either sequence operations or its own 222 | * copy to user routines. To simplify formating of a trace 223 | * trace_seq_printf is used to store strings into a special 224 | * buffer (@s). Then the output may be either used by 225 | * the sequencer or pulled into another buffer. 226 | */ 227 | int 228 | trace_seq_printf(struct trace_seq *s, const char *fmt, ...) 229 | { 230 | va_list ap; 231 | int len; 232 | int ret; 233 | 234 | /* gpuvis change! 235 | static int s_ctx = 1; 236 | gpuvis_trace_begin_ctx_printf( ++s_ctx, "%s", __func__ ); 237 | */ 238 | GPUVIS_COUNT_HOT_FUNC_CALLS(); 239 | 240 | /* gpuvis change! */ 241 | if (fmt[ 0 ] == '%' && fmt[ 1 ] == 's' && fmt[ 2 ] == '\0') 242 | { 243 | const char *str; 244 | 245 | va_start(ap, fmt); 246 | str = va_arg(ap, const char *); 247 | va_end(ap); 248 | 249 | trace_seq_puts(s, str); 250 | /* gpuvis_trace_end_ctx_printf( s_ctx, "%s", __func__ ); */ 251 | return 1; 252 | } 253 | 254 | try_again: 255 | TRACE_SEQ_CHECK_RET0(s); 256 | 257 | len = (s->buffer_size - 1) - s->len; 258 | 259 | va_start(ap, fmt); 260 | ret = vsnprintf(s->buffer + s->len, len, fmt, ap); 261 | va_end(ap); 262 | 263 | if (ret >= len) { 264 | expand_buffer(s); 265 | goto try_again; 266 | } 267 | 268 | if (ret > 0) 269 | s->len += ret; 270 | 271 | /* gpuvis change! gpuvis_trace_end_ctx_printf( s_ctx, "%s", __func__ ); */ 272 | return ret; 273 | } 274 | 275 | /** 276 | * trace_seq_vprintf - sequence printing of trace information 277 | * @s: trace sequence descriptor 278 | * @fmt: printf format string 279 | * 280 | * It returns 0 if the trace oversizes the buffer's free 281 | * space, the number of characters printed, or a negative 282 | * value in case of an error. 283 | * * 284 | * The tracer may use either sequence operations or its own 285 | * copy to user routines. To simplify formating of a trace 286 | * trace_seq_printf is used to store strings into a special 287 | * buffer (@s). Then the output may be either used by 288 | * the sequencer or pulled into another buffer. 289 | */ 290 | int 291 | trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) 292 | { 293 | int len; 294 | int ret; 295 | 296 | try_again: 297 | TRACE_SEQ_CHECK_RET0(s); 298 | 299 | len = (s->buffer_size - 1) - s->len; 300 | 301 | ret = vsnprintf(s->buffer + s->len, len, fmt, args); 302 | 303 | if (ret >= len) { 304 | expand_buffer(s); 305 | goto try_again; 306 | } 307 | 308 | if (ret > 0) 309 | s->len += ret; 310 | 311 | return ret; 312 | } 313 | 314 | /** 315 | * trace_seq_puts - trace sequence printing of simple string 316 | * @s: trace sequence descriptor 317 | * @str: simple string to record 318 | * 319 | * The tracer may use either the sequence operations or its own 320 | * copy to user routines. This function records a simple string 321 | * into a special buffer (@s) for later retrieval by a sequencer 322 | * or other mechanism. 323 | */ 324 | int trace_seq_puts(struct trace_seq *s, const char *str) 325 | { 326 | size_t len; /* gpuvis change! */ 327 | 328 | TRACE_SEQ_CHECK_RET0(s); 329 | 330 | len = strlen(str); 331 | 332 | while (len > ((s->buffer_size - 1) - s->len)) 333 | expand_buffer(s); 334 | 335 | TRACE_SEQ_CHECK_RET0(s); 336 | 337 | memcpy(s->buffer + s->len, str, len); 338 | s->len += (unsigned long) len; /* gpuvis change! */ 339 | 340 | return (int) len; /* gpuvis change! */ 341 | } 342 | 343 | int trace_seq_putc(struct trace_seq *s, unsigned char c) 344 | { 345 | TRACE_SEQ_CHECK_RET0(s); 346 | 347 | while (s->len >= (s->buffer_size - 1)) 348 | expand_buffer(s); 349 | 350 | TRACE_SEQ_CHECK_RET0(s); 351 | 352 | s->buffer[s->len++] = c; 353 | 354 | return 1; 355 | } 356 | 357 | void trace_seq_terminate(struct trace_seq *s) 358 | { 359 | TRACE_SEQ_CHECK_RET(s); 360 | 361 | /* There's always one character left on the buffer */ 362 | s->buffer[s->len] = 0; 363 | } 364 | 365 | int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp) 366 | { 367 | TRACE_SEQ_CHECK(s); 368 | 369 | switch (s->state) { 370 | case TRACE_SEQ__GOOD: 371 | return fprintf(fp, "%.*s", s->len, s->buffer); 372 | case TRACE_SEQ__BUFFER_POISONED: 373 | fprintf(fp, "%s\n", "Usage of trace_seq after it was destroyed"); 374 | break; 375 | case TRACE_SEQ__MEM_ALLOC_FAILED: 376 | fprintf(fp, "%s\n", "Can't allocate trace_seq buffer memory"); 377 | break; 378 | } 379 | return -1; 380 | } 381 | 382 | int trace_seq_do_printf(struct trace_seq *s) 383 | { 384 | return trace_seq_do_fprintf(s, stdout); 385 | } 386 | -------------------------------------------------------------------------------- /src/libtraceevent/src/trace-seq.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: LGPL-2.1 2 | /* 3 | * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt 4 | * 5 | */ 6 | 7 | #ifndef _TRACE_SEQ_H 8 | #define _TRACE_SEQ_H 9 | 10 | #include 11 | #include 12 | 13 | /* ----------------------- trace_seq ----------------------- */ 14 | 15 | #ifndef TRACE_SEQ_BUF_SIZE 16 | #define TRACE_SEQ_BUF_SIZE 4096 17 | #endif 18 | 19 | enum trace_seq_fail { 20 | TRACE_SEQ__GOOD, 21 | TRACE_SEQ__BUFFER_POISONED, 22 | TRACE_SEQ__MEM_ALLOC_FAILED, 23 | }; 24 | 25 | /* 26 | * Trace sequences are used to allow a function to call several other functions 27 | * to create a string of data to use (up to a max of PAGE_SIZE). 28 | */ 29 | 30 | struct trace_seq { 31 | char *buffer; 32 | unsigned int buffer_size; 33 | unsigned int len; 34 | /* unsigned int readpos; */ 35 | char buf[TRACE_SEQ_BUF_SIZE]; /* gpuvis change! */ 36 | enum trace_seq_fail state; 37 | }; 38 | 39 | void trace_seq_init(struct trace_seq *s); 40 | void trace_seq_reset(struct trace_seq *s); 41 | void trace_seq_destroy(struct trace_seq *s); 42 | 43 | extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) 44 | #ifndef _WIN32 /* gpuvis change! */ 45 | __attribute__ ((format (printf, 2, 3))) 46 | #endif 47 | ; 48 | extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) 49 | #ifndef _WIN32 /* gpuvis change! */ 50 | __attribute__ ((format (printf, 2, 0))) 51 | #endif 52 | ; 53 | 54 | extern int trace_seq_puts(struct trace_seq *s, const char *str); 55 | extern int trace_seq_putc(struct trace_seq *s, unsigned char c); 56 | 57 | /* gpuvis change! */ 58 | extern int trace_seq_put_sval(struct trace_seq *s, long long val); 59 | extern int trace_seq_put_uval(struct trace_seq *s, unsigned long long val); 60 | 61 | extern void trace_seq_terminate(struct trace_seq *s); 62 | 63 | extern int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp); 64 | extern int trace_seq_do_printf(struct trace_seq *s); 65 | 66 | #endif /* _TRACE_SEQ_H */ 67 | -------------------------------------------------------------------------------- /src/noc_file_dialog.h: -------------------------------------------------------------------------------- 1 | /* noc_file_dialog library 2 | * 3 | * Copyright (c) 2015 Guillaume Chereau 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to 7 | * deal in the Software without restriction, including without limitation the 8 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | * sell copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | /* A portable library to create open and save dialogs on linux, osx and 25 | * windows. 26 | * 27 | * The library define a single function : noc_file_dialog_open. 28 | * With three different implementations. 29 | * 30 | * Usage: 31 | * 32 | * The library does not automatically select the implementation, you need to 33 | * define one of those macros before including this file: 34 | * 35 | * NOC_FILE_DIALOG_GTK 36 | * NOC_FILE_DIALOG_WIN32 37 | * NOC_FILE_DIALOG_OSX 38 | */ 39 | 40 | #ifndef _NOC_FILE_DIALOG_H_ 41 | #define _NOC_FILE_DIALOG_H_ 42 | 43 | enum { 44 | NOC_FILE_DIALOG_OPEN = 1 << 0, // Create an open file dialog. 45 | NOC_FILE_DIALOG_SAVE = 1 << 1, // Create a save file dialog. 46 | NOC_FILE_DIALOG_DIR = 1 << 2, // Open a directory. 47 | NOC_FILE_DIALOG_OVERWRITE_CONFIRMATION = 1 << 3, 48 | }; 49 | 50 | // There is a single function defined. 51 | 52 | /* flags : union of the NOC_FILE_DIALOG_XXX masks. 53 | * filters : a list of strings separated by '\0' of the form: 54 | * "name1 reg1 name2 reg2 ..." 55 | * The last value is followed by two '\0'. For example, 56 | * to filter png and jpeg files, you can use: 57 | * "png\0*.png\0jpeg\0*.jpeg\0" 58 | * You can also separate patterns with ';': 59 | * "jpeg\0*.jpg;*.jpeg\0" 60 | * Set to NULL for no filter. 61 | * default_path : the default file to use or NULL. 62 | * default_name : the default file name to use or NULL. 63 | * 64 | * The function return a C string. There is no need to free it, as it is 65 | * managed by the library. The string is valid until the next call to 66 | * no_dialog_open. If the user canceled, the return value is NULL. 67 | */ 68 | const char *noc_file_dialog_open(int flags, 69 | const char *filters, 70 | const char *default_path, 71 | const char *default_name); 72 | 73 | // NULL: Success, ERROR: error string 74 | const char *noc_file_init(); 75 | 76 | #if defined( NOC_FILE_DIALOG_IMPLEMENTATION ) 77 | 78 | #include 79 | #include 80 | 81 | static char *g_noc_file_dialog_ret = NULL; 82 | 83 | #if defined( NOC_FILE_DIALOG_GTK ) 84 | 85 | GCC_DIAG_PUSH_OFF( parentheses ) 86 | #include 87 | GCC_DIAG_POP() 88 | 89 | #include "hook_gtk3.h" 90 | 91 | const char *noc_file_init() 92 | { 93 | return hook_gtk3_init(); 94 | } 95 | 96 | const char *noc_file_dialog_open(int flags, 97 | const char *filters, 98 | const char *default_path, 99 | const char *default_name) 100 | { 101 | GtkWidget *dialog; 102 | GtkFileFilter *filter; 103 | GtkFileChooser *chooser; 104 | GtkFileChooserAction action; 105 | gint res; 106 | char buf[128], *patterns; 107 | 108 | if ( noc_file_init() ) 109 | return NULL; 110 | 111 | action = flags & NOC_FILE_DIALOG_SAVE ? GTK_FILE_CHOOSER_ACTION_SAVE : 112 | GTK_FILE_CHOOSER_ACTION_OPEN; 113 | if (flags & NOC_FILE_DIALOG_DIR) 114 | action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; 115 | 116 | gtk_init_check(NULL, NULL); 117 | dialog = gtk_file_chooser_dialog_new( 118 | flags & NOC_FILE_DIALOG_SAVE ? "Save File" : "Open File", 119 | NULL, 120 | action, 121 | "_Cancel", GTK_RESPONSE_CANCEL, 122 | flags & NOC_FILE_DIALOG_SAVE ? "_Save" : "_Open", GTK_RESPONSE_ACCEPT, 123 | NULL ); 124 | chooser = GTK_FILE_CHOOSER(dialog); 125 | if (flags & NOC_FILE_DIALOG_OVERWRITE_CONFIRMATION) 126 | gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE); 127 | 128 | if (default_path) 129 | gtk_file_chooser_set_filename(chooser, default_path); 130 | if (default_name) 131 | gtk_file_chooser_set_current_name(chooser, default_name); 132 | 133 | while (filters && *filters) { 134 | filter = gtk_file_filter_new(); 135 | gtk_file_filter_set_name(filter, filters); 136 | filters += strlen(filters) + 1; 137 | 138 | // Split the filter pattern with ';'. 139 | strcpy(buf, filters); 140 | buf[strlen(buf)] = '\0'; 141 | for (patterns = buf; *patterns; patterns++) 142 | if (*patterns == ';') *patterns = '\0'; 143 | patterns = buf; 144 | while (*patterns) { 145 | gtk_file_filter_add_pattern(filter, patterns); 146 | patterns += strlen(patterns) + 1; 147 | } 148 | 149 | gtk_file_chooser_add_filter(chooser, filter); 150 | filters += strlen(filters) + 1; 151 | } 152 | 153 | res = gtk_dialog_run(GTK_DIALOG(dialog)); 154 | 155 | free(g_noc_file_dialog_ret); 156 | g_noc_file_dialog_ret = NULL; 157 | 158 | if (res == GTK_RESPONSE_ACCEPT) 159 | g_noc_file_dialog_ret = gtk_file_chooser_get_filename(chooser); 160 | gtk_widget_destroy(dialog); 161 | while (gtk_events_pending()) gtk_main_iteration(); 162 | return g_noc_file_dialog_ret; 163 | } 164 | 165 | #elif defined( NOC_FILE_DIALOG_WIN32 ) 166 | 167 | #include 168 | #include 169 | 170 | const char *noc_file_init() 171 | { 172 | return NULL; 173 | } 174 | 175 | const char *noc_file_dialog_open(int flags, 176 | const char *filters, 177 | const char *default_path, 178 | const char *default_name) 179 | { 180 | OPENFILENAME ofn; // common dialog box structure 181 | char szFile[260]; // buffer for file name 182 | int ret; 183 | 184 | ZeroMemory(&ofn, sizeof(ofn)); 185 | ofn.lStructSize = sizeof(ofn); 186 | ofn.lpstrFile = szFile; 187 | ofn.lpstrFile[0] = '\0'; 188 | ofn.nMaxFile = sizeof(szFile); 189 | ofn.lpstrFilter = filters; 190 | ofn.nFilterIndex = 1; 191 | ofn.lpstrFileTitle = NULL; 192 | ofn.nMaxFileTitle = 0; 193 | ofn.lpstrInitialDir = NULL; 194 | ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; 195 | 196 | if (flags & NOC_FILE_DIALOG_OPEN) 197 | ret = GetOpenFileName(&ofn); 198 | else 199 | ret = GetSaveFileName(&ofn); 200 | 201 | free(g_noc_file_dialog_ret); 202 | g_noc_file_dialog_ret = ret ? strdup(szFile) : NULL; 203 | return g_noc_file_dialog_ret; 204 | } 205 | 206 | #elif defined( NOC_FILE_DIALOG_OSX ) 207 | 208 | // moved to noc_file_dialog_osx.mm 209 | 210 | #else 211 | 212 | const char *noc_file_init() 213 | { 214 | return "ERROR: noc_file_dialog_open NYI"; 215 | } 216 | 217 | inline const char *noc_file_dialog_open(int flags, 218 | const char *filters, 219 | const char *default_path, 220 | const char *default_name) 221 | { 222 | return NULL; 223 | } 224 | 225 | #endif 226 | 227 | #endif // NOC_FILE_DIALOG_IMPLEMENTATION 228 | 229 | #endif // _NOC_FILE_DIALOG_H_ 230 | -------------------------------------------------------------------------------- /src/noc_file_dialog_osx.mm: -------------------------------------------------------------------------------- 1 | #define NOC_FILE_DIALOG_IMPLEMENTATION 2 | #define NOC_FILE_DIALOG_OSX 3 | #include "noc_file_dialog.h" 4 | 5 | #include 6 | 7 | const char *noc_file_init() 8 | { 9 | return NULL; 10 | } 11 | 12 | const char *noc_file_dialog_open(int flags, 13 | const char *filters, 14 | const char *default_path, 15 | const char *default_name) 16 | { 17 | NSURL *url; 18 | const char *utf8_path; 19 | NSSavePanel *panel; 20 | NSOpenPanel *open_panel; 21 | NSMutableArray *types_array; 22 | NSURL *default_url; 23 | char buf[128], *patterns; 24 | // XXX: I don't know about memory management with cococa, need to check 25 | // if I leak memory here. 26 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 27 | 28 | if (flags & NOC_FILE_DIALOG_OPEN) { 29 | panel = open_panel = [NSOpenPanel openPanel]; 30 | } else { 31 | panel = [NSSavePanel savePanel]; 32 | } 33 | 34 | if (flags & NOC_FILE_DIALOG_DIR) { 35 | [open_panel setCanChooseDirectories:YES]; 36 | [open_panel setCanChooseFiles:NO]; 37 | } 38 | 39 | if (default_path) { 40 | default_url = [NSURL fileURLWithPath: 41 | [NSString stringWithUTF8String:default_path]]; 42 | [panel setDirectoryURL:default_url]; 43 | [panel setNameFieldStringValue:default_url.lastPathComponent]; 44 | } 45 | 46 | if (filters) { 47 | types_array = [NSMutableArray array]; 48 | while (*filters) { 49 | filters += strlen(filters) + 1; // skip the name 50 | // Split the filter pattern with ';'. 51 | strcpy(buf, filters); 52 | buf[strlen(buf) + 1] = '\0'; 53 | for (patterns = buf; *patterns; patterns++) 54 | if (*patterns == ';') *patterns = '\0'; 55 | patterns = buf; 56 | while (*patterns) { 57 | assert(strncmp(patterns, "*.", 2) == 0); 58 | patterns += 2; // Skip the "*." 59 | [types_array addObject:[NSString stringWithUTF8String: patterns]]; 60 | patterns += strlen(patterns) + 1; 61 | } 62 | filters += strlen(filters) + 1; 63 | } 64 | [panel setAllowedFileTypes:types_array]; 65 | } 66 | 67 | free(g_noc_file_dialog_ret); 68 | g_noc_file_dialog_ret = NULL; 69 | if ( [panel runModal] == NSModalResponseOK ) { 70 | url = [panel URL]; 71 | utf8_path = [[url path] UTF8String]; 72 | g_noc_file_dialog_ret = strdup(utf8_path); 73 | } 74 | 75 | [pool release]; 76 | return g_noc_file_dialog_ret; 77 | } 78 | -------------------------------------------------------------------------------- /src/stlini.h: -------------------------------------------------------------------------------- 1 | #ifndef _STLINI_H 2 | #define _STLINI_H 1 3 | 4 | // From http://robertk.com/source/ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #define __STDC_FORMAT_MACROS 11 | #include 12 | 13 | struct StlIniCompareStringNoCase 14 | { 15 | bool operator()( const std::string &x, const std::string &y ) const; 16 | }; 17 | 18 | // return true or false depending on whether the first string is less than the second 19 | inline bool StlIniCompareStringNoCase::operator()( const std::string &x, const std::string &y ) const 20 | { 21 | return ( strcasecmp( x.c_str(), y.c_str() ) < 0 ) ? true : false; 22 | } 23 | 24 | // these typedefs just make the code a bit more readable 25 | typedef std::pair< std::string, std::string > INIEntry; // key, value 26 | typedef std::map< std::string, std::string, StlIniCompareStringNoCase > INISection; 27 | typedef std::map< std::string, INISection, StlIniCompareStringNoCase > INIFile; 28 | 29 | std::string util_get_config_dir( const char *dirname ); 30 | 31 | class CIniFile 32 | { 33 | public: 34 | CIniFile() {} 35 | ~CIniFile() { Close(); } 36 | 37 | void Open( const char *app, const char *filename ); 38 | void Save(); 39 | void Close(); 40 | 41 | void PutInt( const char *key, int value, const char *section = NULL ); 42 | int GetInt( const char *key, int defval, const char *section = NULL ); 43 | 44 | void PutUint64( const char *key, uint64_t value, const char *section = NULL ); 45 | uint64_t GetUint64( const char *key, uint64_t defval, const char *section = NULL ); 46 | 47 | void PutFloat( const char *key, float value, const char *section = NULL ); 48 | float GetFloat( const char *key, float defval, const char *section = NULL ); 49 | 50 | void PutStr( const char *key, const char *value, const char *section = NULL ); 51 | std::string GetStr( const char *key, const char *defval = NULL, const char *section = NULL ); 52 | 53 | void PutVec4( const char *key, const ImVec4& value, const char *section = NULL ); 54 | ImVec4 GetVec4( const char *key, const ImVec4 &defval, const char *section = NULL ); 55 | 56 | void PutVec2( const char *key, const ImVec2& value, const char *section = NULL ); 57 | ImVec2 GetVec2( const char *key, const ImVec2 &defval, const char *section = NULL ); 58 | 59 | std::vector< std::string > GetSections(); 60 | std::vector< INIEntry > GetSectionEntries( const char *section ); 61 | 62 | void ClearSection( const char *section ); 63 | 64 | public: 65 | INIFile m_inifile; 66 | std::string m_filename; 67 | static const char *m_settings; 68 | static const char *m_colors; 69 | }; 70 | 71 | #endif // _STLINI_H 72 | 73 | -------------------------------------------------------------------------------- /src/tdopexpr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Valve Software 3 | * 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef TDOPEXPR_H_ 25 | #define TDOPEXPR_H_ 26 | 27 | typedef std::function< const char * ( const char *name, size_t len ) > tdop_get_key_func; 28 | typedef std::function< const char * ( const char *name, char ( &buf )[ 64 ] ) > tdop_get_keyval_func; 29 | 30 | class TdopExpr *tdopexpr_compile( const char *expression, tdop_get_key_func &get_key_func, std::string &errstr ); 31 | const char *tdopexpr_exec( class TdopExpr *tdop_expr, tdop_get_keyval_func &get_keyval_func ); 32 | void tdopexpr_delete( class TdopExpr *tdop_expr ); 33 | 34 | #endif // TDOPEXPR_H_ 35 | -------------------------------------------------------------------------------- /src/trace-cmd/trace-read.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Valve Software 3 | * 4 | * All Rights Reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | // From kernel/trace/trace.h 26 | #ifndef TRACE_BUF_SIZE 27 | #define TRACE_BUF_SIZE 1024 28 | #endif 29 | 30 | // About process states: 31 | // https://www.ibm.com/developerworks/linux/library/l-task-killable/ 32 | 33 | // R Running 34 | // S Sleeping in an interruptible wait 35 | // D Waiting in uninterruptible disk sleep 36 | // T Stopped (on a signal) or (before Linux 2.6.33) trace stopped 37 | // t Tracing stop (Linux 2.6.33 onward) 38 | // X Dead (from Linux 2.6.0 onward) 39 | // Z Zombie 40 | // P Parked (Linux 3.9 to 3.13 only) 41 | 42 | // Bits for sched_switch prev_state field: 43 | // From task_index_to_char() in include/linux/sched.h 44 | 45 | /* Used in tsk->state: */ 46 | #define TASK_RUNNING 0x0000 // R 47 | #define TASK_INTERRUPTIBLE 0x0001 // S 48 | #define TASK_UNINTERRUPTIBLE 0x0002 // D 49 | #define TASK_STOPPED 0x0004 // T 50 | #define TASK_TRACED 0x0008 // t 51 | /* Used in tsk->exit_state: */ 52 | #define EXIT_DEAD 0x0010 // X 53 | #define EXIT_ZOMBIE 0x0020 // Z 54 | /* Used in tsk->state again: */ 55 | #define TASK_PARKED 0x0040 // P 56 | #define TASK_DEAD 0x0080 // I 57 | 58 | #define TASK_REPORT_MAX 0x0100 // (0x7f + 1) << 1 59 | 60 | #define INVALID_ID ( ( uint32_t )-1 ) 61 | 62 | inline bool is_valid_id( uint32_t id ) 63 | { 64 | return ( id != INVALID_ID ); 65 | } 66 | 67 | struct tgid_info_t 68 | { 69 | int tgid = 0; 70 | std::vector< int > pids; 71 | 72 | // Colored 'foobarapp-1234' string for tgid 73 | const char *commstr_clr; 74 | const char *commstr; 75 | 76 | uint32_t hashval = 0; 77 | uint32_t color = 0; 78 | 79 | void add_pid( int pid ); 80 | }; 81 | 82 | struct cpu_info_t 83 | { 84 | // per_cpu/cpu0/stats 85 | // 86 | // This displays certain stats about the ring buffer: 87 | // entries: The number of events that are still in the buffer. 88 | // overrun: The number of lost events due to overwriting when· 89 | // the buffer was full. 90 | // commit overrun: Should always be zero. 91 | // This gets set if so many events happened within a nested 92 | // event (ring buffer is re-entrant), that it fills the 93 | // buffer and starts dropping events. 94 | // bytes: Bytes actually read (not overwritten). 95 | // oldest event ts: The oldest timestamp in the buffer 96 | // now ts: The current timestamp 97 | // dropped events: Events lost due to overwrite option being off.· 98 | // read events: The number of events read. 99 | int64_t entries = 0; 100 | int64_t overrun = 0; 101 | int64_t commit_overrun = 0; 102 | int64_t bytes = 0; 103 | int64_t oldest_event_ts = 0; 104 | int64_t now_ts = 0; 105 | int64_t dropped_events = 0; 106 | int64_t read_events = 0; 107 | 108 | uint64_t file_offset = 0; 109 | uint64_t file_size = 0; 110 | 111 | int64_t min_ts = 0; 112 | int64_t max_ts = 0; 113 | 114 | // Non-trimmed events read for this cpu 115 | uint64_t events = 0; 116 | // Total events read for this cpu 117 | uint64_t tot_events = 0; 118 | }; 119 | 120 | struct trace_info_t 121 | { 122 | uint32_t cpus = 0; 123 | std::string file; 124 | std::string uname; 125 | std::string opt_version; 126 | bool timestamp_in_us; 127 | 128 | std::vector< cpu_info_t > cpu_info; 129 | 130 | // ts of the first event in the file 131 | int64_t min_file_ts = INT64_MAX; 132 | 133 | // ts where we trimmed from 134 | bool trim_trace = false; 135 | int64_t trimmed_ts = 0; 136 | 137 | // Manual load trimming 138 | uint64_t m_tracestart = 0; 139 | uint64_t m_tracelen = 0; 140 | 141 | // Map tgid to vector of child pids and color 142 | util_umap< int, tgid_info_t > tgid_pids; 143 | // Map pid to tgid 144 | util_umap< int, int > pid_tgid_map; 145 | // Map pid to comm 146 | util_umap< int, const char * > pid_comm_map; 147 | // Map pid from sched_switch event prev_pid, next_pid fields to comm 148 | util_umap< int, const char * > sched_switch_pid_comm_map; 149 | }; 150 | 151 | struct event_field_t 152 | { 153 | const char *key; 154 | const char *value; 155 | }; 156 | 157 | enum trace_flag_type_t { 158 | // TRACE_FLAG_IRQS_OFF = 0x01, // interrupts were disabled 159 | // TRACE_FLAG_IRQS_NOSUPPORT = 0x02, 160 | // TRACE_FLAG_NEED_RESCHED = 0x04, 161 | // TRACE_FLAG_HARDIRQ = 0x08, // inside an interrupt handler 162 | // TRACE_FLAG_SOFTIRQ = 0x10, // inside a softirq handler 163 | 164 | TRACE_FLAG_FTRACE_PRINT = 0x00100, 165 | TRACE_FLAG_VBLANK = 0x00200, 166 | TRACE_FLAG_TIMELINE = 0x00400, 167 | TRACE_FLAG_SW_QUEUE = 0x00800, // amdgpu_cs_ioctl 168 | TRACE_FLAG_HW_QUEUE = 0x01000, // amdgpu_sched_run_job 169 | TRACE_FLAG_FENCE_SIGNALED = 0x02000, // *fence_signaled 170 | TRACE_FLAG_SCHED_SWITCH = 0x04000, // sched_switch 171 | TRACE_FLAG_SCHED_SWITCH_TASK_RUNNING = 0x08000, // TASK_RUNNING 172 | TRACE_FLAG_SCHED_SWITCH_SYSTEM_EVENT = 0x10000, 173 | TRACE_FLAG_AUTOGEN_COLOR = 0x20000, 174 | TRACE_FLAG_I915_PERF = 0x40000, // i915-perf gpu generated 175 | TRACE_FLAG_LINUX_PERF = 0x80000, 176 | TRACE_FLAG_GPUVIS_PRINT = 0x100000, // Added for new `gpuvis_print` event type in kernel 177 | }; 178 | 179 | struct trace_event_t 180 | { 181 | public: 182 | bool is_filtered_out = false; 183 | 184 | int pid; // event process id 185 | uint32_t id; // event id 186 | uint32_t cpu = UINT32_MAX; // cpu this event was hit on 187 | int64_t ts; // timestamp 188 | 189 | uint32_t flags = 0; // TRACE_FLAGS_IRQS_OFF, TRACE_FLAG_HARDIRQ, TRACE_FLAG_SOFTIRQ 190 | uint32_t seqno = 0; // event seqno (from fields) 191 | uint32_t id_start = INVALID_ID; // start event if this is a graph sequence event (ie amdgpu_sched_run_job, fence_signaled) 192 | uint32_t graph_row_id = 0; 193 | int crtc = -1; // drm_vblank_event crtc (or -1) 194 | int64_t vblank_ts = INT64_MAX; // time-stamp that is passed with the drm_event_vblank event 195 | bool vblank_ts_high_prec = false; // denotes whether or not the hardware timestamp is high-precision 196 | uint32_t i915_perf_timeline = 197 | INVALID_ID; // Pointer into the i915-perf timelines to this element. 198 | 199 | uint32_t color = 0; // color of the event (or 0 for default) 200 | 201 | // i915 events: col_Graph_Bari915SubmitDelay, etc 202 | // ftrace print events: buf hashval for colors 203 | // otherwise: -1 204 | uint32_t color_index = ( uint32_t )-1; 205 | 206 | int64_t duration = INT64_MAX; // how long this timeline event took (or INT64_MAX for not set) 207 | 208 | const char *comm; // command name 209 | const char *system; // event system (ftrace-print, etc.) 210 | const char *name; // event name 211 | const char *user_comm; // User space comm (if we can figure this out) 212 | 213 | uint32_t numfields = 0; 214 | event_field_t *fields = nullptr; 215 | std::vector< const char * > backtrace; 216 | 217 | public: 218 | bool is_fence_signaled() const { return !!( flags & TRACE_FLAG_FENCE_SIGNALED ); } 219 | bool is_ftrace_print() const { return !!( flags & TRACE_FLAG_FTRACE_PRINT ); } 220 | bool is_gpuvis_print() const { return !!( flags & TRACE_FLAG_GPUVIS_PRINT ); } 221 | bool is_vblank() const { return !!( flags & TRACE_FLAG_VBLANK ); } 222 | bool is_timeline() const { return !!( flags & TRACE_FLAG_TIMELINE ); } 223 | bool is_sched_switch() const { return !!( flags & TRACE_FLAG_SCHED_SWITCH ); } 224 | bool is_i915_perf() const { return !!( flags & TRACE_FLAG_I915_PERF ); } 225 | bool is_linux_perf() const { return !!( flags & TRACE_FLAG_LINUX_PERF ); } 226 | 227 | bool has_duration() const { return duration != INT64_MAX; } 228 | bool has_cpu() const { return cpu != UINT32_MAX; } 229 | int64_t get_vblank_ts(bool want_high_prec) const { return want_high_prec && (vblank_ts != INT64_MAX) && vblank_ts_high_prec ? vblank_ts : ts; } 230 | 231 | const char *get_timeline_name( const char *def = NULL ) const 232 | { 233 | if ( flags & TRACE_FLAG_SW_QUEUE ) 234 | return "SW queue"; 235 | else if ( flags & TRACE_FLAG_HW_QUEUE ) 236 | return "HW queue"; 237 | else if ( is_fence_signaled() ) 238 | return "Execution"; 239 | 240 | return def; 241 | } 242 | }; 243 | 244 | const char *get_event_field_val( const trace_event_t &event, const char *name, const char *defval = "" ); 245 | event_field_t *get_event_field( trace_event_t &event, const char *name ); 246 | 247 | typedef std::function< int ( const trace_event_t &event ) > EventCallback; 248 | int read_trace_file( const char *file, StrPool &strpool, trace_info_t &trace_info, EventCallback &cb ); 249 | -------------------------------------------------------------------------------- /src/ya_getopt.c: -------------------------------------------------------------------------------- 1 | /* -*- indent-tabs-mode: nil -*- 2 | * 3 | * ya_getopt - Yet another getopt 4 | * https://github.com/kubo/ya_getopt 5 | * 6 | * Copyright 2015 Kubo Takehiro 7 | * 8 | * Redistribution and use in source and binary forms, with or without modification, are 9 | * permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, this list of 12 | * conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list 15 | * of conditions and the following disclaimer in the documentation and/or other materials 16 | * provided with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR IMPLIED 19 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR 21 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * The views and conclusions contained in the software and documentation are those of the 29 | * authors and should not be interpreted as representing official policies, either expressed 30 | * or implied, of the authors. 31 | * 32 | */ 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "ya_getopt.h" 38 | #include "gpuvis_macros.h" 39 | 40 | char *ya_optarg = NULL; 41 | int ya_optind = 1; 42 | int ya_opterr = 1; 43 | int ya_optopt = '?'; 44 | static char *ya_optnext = NULL; 45 | static int posixly_correct = -1; 46 | static int handle_nonopt_argv = 0; 47 | 48 | static void ya_getopt_error(const char *optstring, const char *format, ...); 49 | static void check_gnu_extension(const char *optstring); 50 | static int ya_getopt_internal(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex, int long_only); 51 | static int ya_getopt_shortopts(int argc, char * const argv[], const char *optstring, int long_only); 52 | static int ya_getopt_longopts(int argc, char * const argv[], char *arg, const char *optstring, const struct option *longopts, int *longindex, int *long_only_flag); 53 | 54 | static void ya_getopt_error(const char *optstring, const char *format, ...) ATTRIBUTE_PRINTF(2, 3); 55 | static void ya_getopt_error(const char *optstring, const char *format, ...) 56 | { 57 | if (ya_opterr && optstring[0] != ':') { 58 | va_list ap; 59 | va_start(ap, format); 60 | vfprintf(stderr, format, ap); 61 | va_end(ap); 62 | } 63 | } 64 | 65 | static void check_gnu_extension(const char *optstring) 66 | { 67 | if (optstring[0] == '+' || getenv("POSIXLY_CORRECT") != NULL) { 68 | posixly_correct = 1; 69 | } else { 70 | posixly_correct = 0; 71 | } 72 | if (optstring[0] == '-') { 73 | handle_nonopt_argv = 1; 74 | } else { 75 | handle_nonopt_argv = 0; 76 | } 77 | } 78 | 79 | int ya_getopt(int argc, char * const argv[], const char *optstring) 80 | { 81 | return ya_getopt_internal(argc, argv, optstring, NULL, NULL, 0); 82 | } 83 | 84 | int ya_getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex) 85 | { 86 | return ya_getopt_internal(argc, argv, optstring, longopts, longindex, 0); 87 | } 88 | 89 | int ya_getopt_long_only(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex) 90 | { 91 | return ya_getopt_internal(argc, argv, optstring, longopts, longindex, 1); 92 | } 93 | 94 | static int ya_getopt_internal(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex, int long_only) 95 | { 96 | static int start, end; 97 | 98 | if (ya_optopt == '?') { 99 | ya_optopt = 0; 100 | } 101 | 102 | if (posixly_correct == -1) { 103 | check_gnu_extension(optstring); 104 | } 105 | 106 | if (ya_optind == 0) { 107 | check_gnu_extension(optstring); 108 | ya_optind = 1; 109 | ya_optnext = NULL; 110 | } 111 | 112 | switch (optstring[0]) { 113 | case '+': 114 | case '-': 115 | optstring++; 116 | } 117 | 118 | if (ya_optnext == NULL && start != 0) { 119 | int last_pos = ya_optind - 1; 120 | 121 | ya_optind -= end - start; 122 | if (ya_optind <= 0) { 123 | ya_optind = 1; 124 | } 125 | while (start < end--) { 126 | int i; 127 | char *arg = argv[end]; 128 | 129 | for (i = end; i < last_pos; i++) { 130 | ((char **)argv)[i] = argv[i + 1]; 131 | } 132 | ((char const **)argv)[i] = arg; 133 | last_pos--; 134 | } 135 | start = 0; 136 | } 137 | 138 | if (ya_optind >= argc) { 139 | ya_optarg = NULL; 140 | return -1; 141 | } 142 | if (ya_optnext == NULL) { 143 | const char *arg = argv[ya_optind]; 144 | if (*arg != '-') { 145 | if (handle_nonopt_argv) { 146 | ya_optarg = argv[optind++]; 147 | start = 0; 148 | return 1; 149 | } else if (posixly_correct) { 150 | ya_optarg = NULL; 151 | return -1; 152 | } else { 153 | int i; 154 | 155 | start = ya_optind; 156 | for (i = ya_optind + 1; i < argc; i++) { 157 | if (argv[i][0] == '-') { 158 | end = i; 159 | break; 160 | } 161 | } 162 | if (i == argc) { 163 | ya_optarg = NULL; 164 | return -1; 165 | } 166 | ya_optind = i; 167 | arg = argv[ya_optind]; 168 | } 169 | } 170 | if (strcmp(arg, "--") == 0) { 171 | ya_optind++; 172 | return -1; 173 | } 174 | if (longopts != NULL && arg[1] == '-') { 175 | return ya_getopt_longopts(argc, argv, argv[ya_optind] + 2, optstring, longopts, longindex, NULL); 176 | } 177 | } 178 | 179 | if (ya_optnext == NULL) { 180 | ya_optnext = argv[ya_optind] + 1; 181 | } 182 | if (long_only) { 183 | int long_only_flag = 0; 184 | int rv = ya_getopt_longopts(argc, argv, ya_optnext, optstring, longopts, longindex, &long_only_flag); 185 | if (!long_only_flag) { 186 | ya_optnext = NULL; 187 | return rv; 188 | } 189 | } 190 | 191 | return ya_getopt_shortopts(argc, argv, optstring, long_only); 192 | } 193 | 194 | static int ya_getopt_shortopts(int argc, char * const argv[], const char *optstring, int long_only) 195 | { 196 | int opt = *ya_optnext; 197 | const char *os = strchr(optstring, opt); 198 | 199 | if (os == NULL) { 200 | ya_optarg = NULL; 201 | if (long_only) { 202 | ya_getopt_error(optstring, "%s: unrecognized option '-%s'\n", argv[0], ya_optnext); 203 | ya_optind++; 204 | ya_optnext = NULL; 205 | } else { 206 | ya_optopt = opt; 207 | ya_getopt_error(optstring, "%s: invalid option -- '%c'\n", argv[0], opt); 208 | if (*(++ya_optnext) == 0) { 209 | ya_optind++; 210 | ya_optnext = NULL; 211 | } 212 | } 213 | return '?'; 214 | } 215 | if (os[1] == ':') { 216 | if (ya_optnext[1] == 0) { 217 | ya_optind++; 218 | if (os[2] == ':') { 219 | /* optional argument */ 220 | ya_optarg = NULL; 221 | } else { 222 | if (ya_optind == argc) { 223 | ya_optarg = NULL; 224 | ya_optopt = opt; 225 | ya_getopt_error(optstring, "%s: option requires an argument -- '%c'\n", argv[0], opt); 226 | if (optstring[0] == ':') { 227 | return ':'; 228 | } else { 229 | return '?'; 230 | } 231 | } 232 | ya_optarg = argv[ya_optind]; 233 | ya_optind++; 234 | } 235 | } else { 236 | ya_optarg = ya_optnext + 1; 237 | ya_optind++; 238 | } 239 | ya_optnext = NULL; 240 | } else { 241 | ya_optarg = NULL; 242 | if (ya_optnext[1] == 0) { 243 | ya_optnext = NULL; 244 | ya_optind++; 245 | } else { 246 | ya_optnext++; 247 | } 248 | } 249 | return opt; 250 | } 251 | 252 | static int ya_getopt_longopts(int argc, char * const argv[], char *arg, const char *optstring, const struct option *longopts, int *longindex, int *long_only_flag) 253 | { 254 | char *val = NULL; 255 | const struct option *opt; 256 | size_t namelen; 257 | int idx; 258 | 259 | for (idx = 0; longopts[idx].name != NULL; idx++) { 260 | opt = &longopts[idx]; 261 | namelen = strlen(opt->name); 262 | if (strncmp(arg, opt->name, namelen) == 0) { 263 | switch (arg[namelen]) { 264 | case '\0': 265 | switch (opt->has_arg) { 266 | case ya_required_argument: 267 | ya_optind++; 268 | if (ya_optind == argc) { 269 | ya_optarg = NULL; 270 | ya_optopt = opt->val; 271 | ya_getopt_error(optstring, "%s: option '--%s' requires an argument\n", argv[0], opt->name); 272 | if (optstring[0] == ':') { 273 | return ':'; 274 | } else { 275 | return '?'; 276 | } 277 | } 278 | val = argv[ya_optind]; 279 | break; 280 | } 281 | goto found; 282 | case '=': 283 | if (opt->has_arg == ya_no_argument) { 284 | const char *hyphens = (argv[ya_optind][1] == '-') ? "--" : "-"; 285 | 286 | ya_optind++; 287 | ya_optarg = NULL; 288 | ya_optopt = opt->val; 289 | ya_getopt_error(optstring, "%s: option '%s%s' doesn't allow an argument\n", argv[0], hyphens, opt->name); 290 | return '?'; 291 | } 292 | val = arg + namelen + 1; 293 | goto found; 294 | } 295 | } 296 | } 297 | if (long_only_flag) { 298 | *long_only_flag = 1; 299 | } else { 300 | ya_getopt_error(optstring, "%s: unrecognized option '%s'\n", argv[0], argv[ya_optind]); 301 | ya_optind++; 302 | } 303 | return '?'; 304 | found: 305 | ya_optarg = val; 306 | ya_optind++; 307 | if (opt->flag) { 308 | *opt->flag = opt->val; 309 | } 310 | if (longindex) { 311 | *longindex = idx; 312 | } 313 | return opt->flag ? 0 : opt->val; 314 | } 315 | -------------------------------------------------------------------------------- /src/ya_getopt.h: -------------------------------------------------------------------------------- 1 | /* -*- indent-tabs-mode: nil -*- 2 | * 3 | * ya_getopt - Yet another getopt 4 | * https://github.com/kubo/ya_getopt 5 | * 6 | * Copyright 2015 Kubo Takehiro 7 | * 8 | * Redistribution and use in source and binary forms, with or without modification, are 9 | * permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, this list of 12 | * conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list 15 | * of conditions and the following disclaimer in the documentation and/or other materials 16 | * provided with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR IMPLIED 19 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR 21 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * The views and conclusions contained in the software and documentation are those of the 29 | * authors and should not be interpreted as representing official policies, either expressed 30 | * or implied, of the authors. 31 | * 32 | */ 33 | #ifndef YA_GETOPT_H 34 | #define YA_GETOPT_H 1 35 | 36 | #if defined(__cplusplus) 37 | extern "C" { 38 | #endif 39 | 40 | #define ya_no_argument 0 41 | #define ya_required_argument 1 42 | #define ya_optional_argument 2 43 | 44 | struct option { 45 | const char *name; 46 | int has_arg; 47 | int *flag; 48 | int val; 49 | }; 50 | 51 | int ya_getopt(int argc, char * const argv[], const char *optstring); 52 | int ya_getopt_long(int argc, char * const argv[], const char *optstring, 53 | const struct option *longopts, int *longindex); 54 | int ya_getopt_long_only(int argc, char * const argv[], const char *optstring, 55 | const struct option *longopts, int *longindex); 56 | 57 | extern char *ya_optarg; 58 | extern int ya_optind, ya_opterr, ya_optopt; 59 | 60 | #ifndef YA_GETOPT_NO_COMPAT_MACRO 61 | #define getopt ya_getopt 62 | #define getopt_long ya_getopt_long 63 | #define getopt_long_only ya_getopt_long_only 64 | #define optarg ya_optarg 65 | #define optind ya_optind 66 | #define opterr ya_opterr 67 | #define optopt ya_optopt 68 | #define no_argument ya_no_argument 69 | #define required_argument ya_required_argument 70 | #define optional_argument ya_optional_argument 71 | #endif 72 | 73 | #if defined(__cplusplus) 74 | } 75 | #endif 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /traces/amdgpu_trace.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikesart/gpuvis/a1a1e173fd5cdca57a4b1085c1b1ee47dc9669c9/traces/amdgpu_trace.zip -------------------------------------------------------------------------------- /traces/windows_etl.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikesart/gpuvis/a1a1e173fd5cdca57a4b1085c1b1ee47dc9669c9/traces/windows_etl.zip --------------------------------------------------------------------------------