This is a command-line GPU performance validation tool for GPU driver development, performance-related reverse-engineering, and pre-silicon validation that isolates and measures performance of specific GPU and GPU API features and workload types and how different GPUs, APIs, API translation and forwarding layers, and operating systems compare in GPU utilization and performance.
Some of the project goals are:
- Help GPU driver developers quickly and effectively identify areas that need improvement.
- Infer detailed information about undocumented GPU architectures through highly artificial tests.
It produces CSV output and reports GPU performance in pixels per clock, samples per clock, primitives per clock, ray intersections per clock (TBD), memory throughput, latencies, etc. with different combinations of pipeline states, shaders, and different types of draw/compute/blit/RT/etc. operations to show how observed GPU performance is affected by the choice of drivers (closed source, open source / Mesa), APIs (DX11, DX12, GL, VK), API translation and forwarding layers (DXVK, VKD3D, Zink, WSL2, VirtIO), and operating systems (Android, Linux, Windows).
This project is for anybody who would like to understand, improve, and validate the performance of their GPU drivers and API/OS implementations.
Broad support of APIs and API pipeline construction codepaths enables the following comparisons:
- Open source vs closed source driver
- Windows vs Linux vs Android
- Vulkan vs OpenGL vs Zink
- Vulkan vs DX12 vs VKD3D
- Vulkan vs DX11 vs DXVK
- OpenGL in WSL2 vs Vulkan in WSL2 vs DX12
- Vulkan graphics pipeline objects vs graphics pipeline libraries vs shader objects
- Vulkan static state vs dynamic state
- VirtIO Native Context vs VirtIO VirGL/Venus vs bare metal
Examples of result interpretation:
- If one driver achieves 2x pixels/clock at 32 bpp than another, the other driver might not program the HW optimally for 32 bpp.
- If one driver has 4x higher early depth-test rejection rate than another, HiZ may be disabled for the other driver.
- If a driver sustains only 300 GB/s for image blits while the maximum memory bandwidth is 500 GB/s, the blit implementation in that driver may be suboptimal.
- If Vulkan pipeline objects using dynamic state are 2x slower than equivalent objects using static state, the dynamic state handling in that driver may be suboptimal.
The official repository is at https://gitlab.freedesktop.org/mesa/gpu-ratemeter. An indexable robot-friendly mirror is at https://github.com/marekolsak/gpu-ratemeter.
[[TOC]]
gpu-ratemeter [optional parameters] [api].[test][.regex]
Choose api and test from the options below. Optional regex is a regular expression that filters which tests are run.
Examples:
gpu-ratemeter gl.bufbw
gpu-ratemeter vk.imgbw.clear.*mrt
gpu-ratemeter vk.imgbw.resolve
gpu-ratemeter vk.prim
gpu-ratemeter -lean vkld.pix
gpu-ratemeter -lean vkld.pix.noaa.raster
gpu-ratemeter -lean vkld.pix.multiview.1persp.*samplemask$
gpu-ratemeter -spacing=128 -maxsize=1M -clockbits=20 vk.latency
API identifiers:
- ⏳*(not implemented yet)*
d11: Direct3D 11 - ⏳*(not implemented yet)*
d12: Direct3D 12 gl: OpenGL (linked shaders only)vk: Vulkan (graphics pipeline objects + static state)vkd: Vulkan (graphics pipeline objects + dynamic state)vkl: Vulkan (graphics pipeline libraries + static state)vkld: Vulkan (graphics pipeline libraries + dynamic state)- ⏳*(not implemented yet)*
vkso: Vulkan (using shader objects)
| OpenGL | Vulkan | |
|---|---|---|
| Graphics Pipeline Tests | ||
pix |
✓ | ✓ |
prim |
✓ | ✓ |
| Compute Tests | ||
cs_launch |
✓ | ✓ |
latency |
✓ | ✓ |
| Transfer Tests | ||
bufbw |
✓ | ✓ |
imgbw |
✓ | ✓ |
| API Tests | ||
sparsebind |
✓ |
All numeric options allow K, M, G, T suffixes for kilo, mega, giga, tera, respectively.
-baserate=N:- if reporting throughput: set this to the number of items/clock that the GPU can do; this causes results to be reported as a percentage of the given rate N (all results are multiplied by 100/N); useful for conversion of perf/second or perf/clock to % of a specific rate
- if reporting time: if the work is performed by multiple parallel units, set this to the total number of the units performing the work; this causes results to be multiplied by N, reporting time per unit instead of time per device
-maxvalidresult=N: (for buggy HW timestamps) if the result is greater than N, print "error" instead of the result-freq=N: the GPU frequency in MHz; required for reporting perf/clock; without it, billion units/s are reported (onlypix,prim)-rdna4ts: a mostly functional workaround for broken timestamps on RDNA 4 (it slightly reduces perf) (onlyimgbw,pix)-top: use top-of-pipe timestamps instead of the default bottom-of-pipe timestamps
-gl-tiling-linear: indicate that regular GL textures are allocated as linear ifGL_LINEAR_TILING_EXTis set; this also setsMESA_DEBUG=api-tiling-linearto make Mesa not ignoreGL_LINEAR_TILING_EXTfor regular GL textures
-device=N: the device index of the device to use (default: 0), Vulkan only-no-validator: disable the Vulkan validation layer (the layer is enabled by default)
-compute: execute on the compute queue-transfer: execute on the transfer queue
-maxsize=N(required): The maximum buffer size to test. The value should be a power of two. Buffer sizes between 1K and this size are tested, with ~1.3-1.5x size increments. If needed to measure memory (cache miss) latency, it should also be > last level cache size.-spacing=N(required): All load addresses are multiples of this number. This should be a power of two and <= cache line size. To make the test faster, it's recommended to set this exactly to the cache line size.maxsize / spacingis the number of executed load indirections of each subtest, so it affects test length, and it also implies that the shader visits every load address that's a multiple ofspacingonly once in the largest buffer. Thus, larger spacing reduces the number of loads needed to traverse the largest buffer, while very small spacing with very large buffers can lead to a GPU timeout. If spacing > cache line size, the latency of tested buffer sizes will no longer correspond to cache sizes because a subset of cache-line-sized buffer segments is never loaded if the spacing is large enough to skip them, reducing cache utilization, and thus creating an illusion that the cache can hold more data than it should. (this behavior can be exploited to find the exact cache line size if it's unknown)-bda: Use buffer device addresses instead of storage buffers to traverse the buffer. (this may report more lower latencies on some drivers)-int8: Use 8-bit addresses for shared memory tests. (this may report lower latencies on some drivers)-clockbits=N: It the shader subgroup clock has less than 64 bits, this is the number of bits that it returns. This parameter enables low-bit clock handling. (it must be set to 20 for RDNA 2 and 3)-sparse-bound: The traversed buffer is sparse and the smallest possible buffers are bound across its whole range. This can be used to measure the impact of small pages.-sparse-unbound: The whole buffer is sparse and its whole range is unbound.- Good starting parameters:
-maxsize=16M -spacing=64(optimal if the last level cache size is 8 MB and the cache line size is 64)
- Good starting parameters:
-bw: print memory bandwidth in GB/s instead of pixels/clock; only subtests that only write the color buffer are executed (this can be used to determine whether pixel throughput is limited by fixed-function logic or memory bandwidth)-format=REGEX: only test the image formats matching the regular expression-lean: don't test 8bpp, 16bpp, and rgb10a2 image formats-samplerate: report samples/clock instead of pixels/clock
Each column is a different color buffer format except for the first column, which tests a fragment shader with only an out-of-range image store (no color buffer is present in this case).
The test is executed multiple times, each time with a different framebuffer (and rasterization) behavior. The following framebuffer configurations are tested:
noaa: the framebuffer is 2D with 1 sample and 1 layermsaa2,msaa4,msaa8: the framebuffer is 2D with 2, 4, or 8 samples and 1 layermultiview: the framebuffer is 2D with 1 sample and 2 layers, using the multiview feature to render to both layers simultaneously (per-view varyings are not tested currently)image3d: the framebuffer is a 3D image with 8 slices, but only slice 0 is drawn to (only a small subset of representative tests is executed for this case)linear: the framebuffer is a 2D image using the linear layout (only a small subset of representative tests is executed for this case)
Decoding subtest names:
fs_empty: empty fragment shaderfs_discard: the fragment shader containsdiscard;before writing the color outputfs_discard_no_output: the fragment shader containsdiscard;with no outputs (it only discards Z writes)helper_invoc: the subtest usesgl_HelperInvocationto suppress the automatic use of VRS by some driverszbuf: the framebuffer contains a Z bufferzwrite: Z writes are enabledz_tess_*.fail,z_tess_*.pass: the subtest uses the given Z compare op to pass or fail the Z testcolormask=0,colormask=x: the color mask is set to 0 or only the X componentblend_src_color0,blend_src_color1,blend_src_alpha0,blend_src_alpha1: the subtest uses blending with color or alpha blend factors and color values such that 0 means that blending fully discards the pixels, while 1 means that blending fully overwrites the pixelsblend_src_color_other,blend_src_alpha_other: the subtest uses blending with color or alpha blend factors and color values such that no pixels are completely discarded or completely overwritten and actual blending must take placeoutput.color,output.z,output.samplemask: the fragment shader contains color, Z, or samplemask outputs (all other subtests also write a color output unless 1) the name containsoutputwithoutcolor, or 2) it's theimgStorecolumn)z_disabled: the Z test is disableda2c: alpha-to-coverage is enabledvrs1x2,vrs2x1,vrs2x2: the given amount of VRSrasterN: fill the screen with triangles of a specific size; N is the percentage of non-helper FS invocations relating to the size of triangles, see the description in the subsection belowcyclesN: the fragment shader waits for N clock cycles to pass before finishing using the subgroup clock; this measures how fragment shaders of different sizes affect pixel throughput and shows when the GPU is limited by the fragment shader execution time and when it's limited by the fixed-function pixel pipeline throughputconst_fill: the color output is a constant colorcull_back: back-face culling is enabled (with no effect - the full-screen triangle is front-facing)- Used system values are indicated as follows:
face:gl_FrontFacingfragpos_*:gl_FragCoord.*using only the listed componentsfully_covered:gl_FullyCoveredEXT(also known asgl_FragFullyCoveredNV)layer:gl_Layerprimitive_id:gl_PrimitiveIDsampleid:gl_SampleID(this forces sample shading if framebuffer samples > 1)samplemask:gl_SampleMaskInsamplepos:gl_SamplePosition(this forces sample shading if framebuffer samples > 1)shading_rate:gl_ShadingRateEXTview_index:gl_ViewIndexviewport_index:gl_ViewportIndex
- Used inputs are indicated as follows:
Nflat: N flat inputsNpersp: N inputs with perspective interpolation at centerNpersp_sample: N inputs with perspective interpolation at sample (this forces sample shading if framebuffer samples > 1)Ncentroid: N inputs with perspective interpolation at centroidNlinear: N inputs with linear (noperspective) interpolation at center
This subsection explains that there are situations when fragment shader execution time doesn't affect performance, and how to determine when it does.
There are 2 major factors that limit observed performance:
- Fragment shader execution time
- Pixel pipeline throughput (fixed-function logic with a fixed per-clock-cycle throughput)
Memory bandwidth can affect both, but let's put that aside.
If the pixel pipeline is the limiting factor, then shader compiler improvements may not affect performance at all. Such improvements may improve power consumptions since shorter shaders consume less power, and they may also allow other shader stages to run in parallel with fragment shaders because fragment shaders that finish sooner make HW resources available to those other shader stages sooner, but observed performance may be unaffected if the pixel pipeline keeps being the limiting factor.
If we run the cyclesN subtests with different forced SIMD occupancy settings, the results demonstrate
that for every pipeline state combination and SIMD occupancy, there is fragment shader execution time T
in clock cycles such that if a fragment shader takes between 0 and T time to execute, the observed performance
is always the same. If a fragment shader takes more time to execute than T, the observed performance decreases
inversely with T.
Time T can be calculated from pixel throughput and SIMD occupancy, and pixel throughput can be calculated
from pipeline states. (In fact, the pixel throughput equation of a specific GPU or GPU architecture can be
inferred from pix results.) Once T is known for a specific set of fragment shaders, then we only need to gather
their average execution time to make the judgement call as to which fragment shaders are worth optimizing.
The implication is that pix results are representative of all fragment shaders and graphics pipeline
configurations where the FS execution time is <= T and memory bandwidth is not a limitation.
The raster subtests measure how much helper invocations and triangle
sizes negatively impact pixel throughput and when primitive throughput starts becoming the limiting
factor. While all other subtests use a single fullscreen triangle and 0 helper invocations,
the raster subtests draw a mesh of equally-sized roughly equilateral triangles. Each subsequent
subtest decreases the triangle size and increases the number of triangles to always fill the whole screen.
A fullscreen triangle and fullscreen quad subtests are also included for reference.
The pipeline statistics of each subtest are in the table below. Unlike standard pipeline statistics, these also include helper invocations.
| Subtest | Total FS invoc. | % non-helper invoc. | Visible tris | Avg. tri area | Avg. pixels / tri | Avg. FS invoc. / tri |
|---|---|---|---|---|---|---|
| raster100.fullscreen_triangle | 1048576 | 100.0 % | 1 | 1024.00² | 1048576.0 | 1048576.0 |
| raster99.8.fullscreen_quad | 1050624 | 99.8 % | 2 | 724.08² | 524288.0 | 525312.0 |
| raster99.9 | 1049800 | 99.9 % | 2 | 724.08² | 524288.0 | 524900.0 |
| raster99.6 | 1053072 | 99.6 % | 6 | 418.05² | 174762.7 | 175512.0 |
| raster99.4 | 1054384 | 99.4 % | 11 | 308.75² | 95325.1 | 95853.1 |
| raster99.1 | 1058496 | 99.1 % | 21 | 223.46² | 49932.2 | 50404.6 |
| raster98.7 | 1062708 | 98.7 % | 40 | 161.91² | 26214.4 | 26567.7 |
| raster98.0 | 1069924 | 98.0 % | 74 | 119.04² | 14169.9 | 14458.4 |
| raster97.2 | 1078396 | 97.2 % | 134 | 88.46² | 7825.2 | 8047.7 |
| raster96.3 | 1088344 | 96.3 % | 226 | 68.12² | 4639.7 | 4815.7 |
| raster94.6 | 1108172 | 94.6 % | 456 | 47.95² | 2299.5 | 2430.2 |
| raster93.0 | 1128072 | 93.0 % | 800 | 36.20² | 1310.7 | 1410.1 |
| raster89.8 | 1167704 | 89.8 % | 1728 | 24.63² | 606.8 | 675.8 |
| raster84.1 | 1247160 | 84.1 % | 4720 | 14.90² | 222.2 | 264.2 |
| raster81.5 | 1286492 | 81.5 % | 6722 | 12.49² | 156.0 | 191.4 |
| raster76.8 | 1366140 | 76.8 % | 11906 | 9.38² | 88.1 | 114.7 |
| raster72.5 | 1445360 | 72.5 % | 18408 | 7.55² | 57.0 | 78.5 |
| raster68.8 | 1524564 | 68.8 % | 26508 | 6.29² | 39.6 | 57.5 |
| raster62.3 | 1682720 | 62.3 % | 46874 | 4.73² | 22.4 | 35.9 |
| raster57.0 | 1840632 | 57.0 % | 73008 | 3.79² | 14.4 | 25.2 |
| raster52.5 | 1998232 | 52.5 % | 105282 | 3.16² | 10.0 | 19.0 |
| raster45.3 | 2313032 | 45.3 % | 186502 | 2.37² | 5.6 | 12.4 |
| raster39.9 | 2626632 | 39.9 % | 290786 | 1.90² | 3.6 | 9.0 |
Each column is a different number of vec4 inputs received by the fragment shader.
Decoding subtest names:
cull_100%,cull_75%,cull_50%,cull_0%: the test culls this % of primitives using one of the culling methods belowtrilist,tristrip: draw as triangle list or triangle stripmesh32,mesh64,mesh128,mesh192,mesh256: draw with a mesh shader, the number indicates the mesh shader workgroup sizereuse0,reuse1,reuse2: how many vertices each primitive reuses from 2 previous primitives using an index buffer (triangle strips always reuse 2 vertices)cull_back: primitives are culled by back face cullingcull_xy: primitives are culled by setting their (x,y) vertex positions such that the primitive is entirely outside the viewportdegenerate: triangles are culled by being degenerate, i.e. 0 area (2 out of 3 vertex positions are equal)rasterizer_discard: all primitives are culled by "rasterizer discard"N_small_tris_pp: exactly N tiny triangles are drawn to fill 1 pixel, i.e. N small triangles per pixel (these are subpixel triangles that are culled due to not intersecting the pixel center, so only the single triangle intersecting the pixel center is drawn)clipdist4,culldist4: culled by clip/cull distance outputs, 4 clip/cull distances are writtenclipdist8,culldist8: culled by clip/cull distance outputs, 8 clip/cull distances are writtenclipdist1357,culldist1357: culled by clip/cull distance outputs where only clip/cull distance outputs 1, 3, 5, 7 do the culling; clip/cull distance outputs 0, 2, 4, 6 are set to constant 1output_pointsize: additionally write the point size output (with no effect on behavior)output_layer: additionally write the layer output (with no effect on behavior)output_vrs1x1: additionally write the primitive shading rate output (with no effect on behavior)
The test measures the following depending on which options are present:
- the time to launch one compute dispatch (default)
- the time to launch one compute subgroup when the
-subgrouptimeoption is set - the time to launch N compute invocations when the
-timeperinvocs=Noption is set
The compute shader is trivial enough that the only bottleneck should be the compute launch rate. The subtest names indicate which compute system values are used.
The cost of compute pipeline binding and descriptor set binding before dispatches is also measured, which exposes command buffer overhead. Using -top (top-of-pipe timestamps) may be better for that.
Decoding subtest names:
gfx,comp: the queue type, graphics or computedirect,indirect: the type of compute dispatchwgN: the workgroup size is Nwg_id.xyz: which workgroup IDs the shader uses, which also determines the dimensionality of the dispatch (1D, 2D, or 3D);_indicates an unused dimensionlocal_invoc_id.xyz: which local invocation IDs the shader uses to identify the invocation, which also determines the dimensionality of the workgroup (1D, 2D, or 3D);_indicates an unused dimensionlocal_invoc_index: the local invocation index is used to identify the invocationsubgroup_ids: the subgroup ID and the subgroup invocation ID are used to identify the invocationbind:: the list of states that are changed before dispatch, the options areshader, meaning the compute pipeline object in Vulkan, anddesc, meaning the descriptor set
The test measures memory load latency as observed by shaders. Besides measuring latencies of all cache levels and memory, it can also be used to infer cache sizes and cache line sizes of all cache levels.
It reports the average number of elapsed ticks of the shader subgroup clock between issued loads and reading their result. Both uniform (scalar) and non-uniform (vector) latencies are measured.
Buffers of different sizes are completely traversed via load indirections in a manner that prevents cache hits if the whole buffer doesn't fit in the cache. The results are printed for each tested buffer size. Each printed latency should exactly correspond to the latency of the last cache level that can hold the buffer of that size.
If the shader compiler inserts ALU instructions between load-use and load-issue, the measured latencies will include the cost of those extra instructions. Looking at the shader disassembly is recommended to see what is actually being measured.
Decoding subtest names:
default: no GLSL qualifier is addedcoherent: the GLSL "coherent" qualifier is addednonuniform: the load addresses are non-uniformuniform: the load addresses are uniformdevmem: the traversed buffer is in device memoryhostmem: the traversed buffer is in host memory uncached by the CPUdevmem_coherent: the traversed buffer is in host-coherent device memory (VK_AMD_device_coherent_memory or equivalent is required)hostmem_coherent: the traversed buffer is in host-coherent host memory uncached by the CPU (VK_AMD_device_coherent_memory or equivalent is required)shared: the traversed buffer is in shared memory
Each column is the size passed to the fill or copy buffer call.
Decoding subtest names:
fill,copy,copy_indirect: the operation is "fill buffer", "copy buffer", or "copy memory indirect"devmem,hostmem: indicating that the buffer is allocated either in device local memory or host memoryhit: whether the cache hit bandwidth is tested by repeating the same operation on the same buffer rangemiss: whether the cache miss bandwidth is tested by increasing the buffer offset monotonically and wrapping at 512 MB (cache misses are guaranteed only if the last level cache is smaller than that)miss_no_barrier: whether the cache miss bandwidth is tested as above, and also there is no barrier between individual operations; this is only executed for APIs that require explicit barriers at fill and copy operationsmaxalign: buffer offsets passed to the fill or copy call are maximally aligned (currently 64K)dst=N,src=N: the destination or source buffer offset passed to the fill or copy call is aligned to N (N=1 means unaligned)both=N: both offsets are aligned to N (N=1 means unaligned)
imgbw: Framebuffer Clear, Image Clear/Copy/Blit, and MSAA Image Clear/Copy/Blit/Resolve Bandwidth (GB/s)
Each column is the total size cleared, copied, blitted, or resolved.
All operations are tested with different image contents or different clear values to exercise data-dependent HW image compression in different scenarios.
The table below shows how subtests are mapped to API functions.
| Subtest name | OpenGL | Vulkan |
|---|---|---|
clear_framebuffer |
glClear |
vkCmdBeginRenderPass (vk, vkl) or vkCmdBeginRendering (vkd, vkld) |
clear_fb_then_draw |
glClear |
vkCmdBeginRenderPass (vk, vkl) or vkCmdBeginRendering (vkd, vkld), then the whole image is overdrawn with a different solid color and stencil, while Z gets a sloped quad. |
clear_attachment |
scissored glClear |
vkCmdClearAttachments |
clear_image |
glClearTex{Sub}Image |
vkCmdClearColorImage and vkCmdClearDepthStencilImage |
copy |
glCopyImageSubData |
vkCmdCopyImage2 |
blit |
glBlitNamedFramebuffer |
vkCmdBlitImage2 - for the scaled variants, the memory footpring of one image is 2x the size of the other image (√2x larger in each dimension). |
resolve |
glBlitNamedFramebuffer |
vkCmdResolveImage2 |
Image formats in subtest names should be mostly self-explanatory. For example, rgba8_d32s8_4mrt in clear subtests means 4 RGBA8 color attachments and D32S8 as the depth-stencil attachment.
Decoding subtest fill identifiers in subtest names:
fill_black: if clearing, the clear color is 0; if copying, blitting, or resolving, the source image is pre-cleared to that value using a framebuffer clearfill_solid: if clearing, the clear color is a non-trivial value (i.e. not 0/1); if copying, blitting, or resolving, the source image is pre-cleared to that value using a framebuffer clearfill_gradient: using a draw, the source image is pre-filled with a gradual change of color; if the image uses a depth format, the fill is done by drawing a sloped quad to write Z naturally (exercising optimal Z compression)fill_random: using a draw, the source image is pre-filled with random noise (defeating DCC); ifsamples >= 2, the draw sets all samples to the same random value (exercising ideal MSAA compression)fill_fragmented2: same asfill_random, but sample 0 and the remaining samples contain different random noise where the remaining samples contain the same noise (exercising decently effective MSAA compression with 4-8 samples and defeating MSAA compression with 2 samples)fill_fragmented4: same asfill_random, but sample 0, sample 1, sample 2, and the remaining samples contain different random noise where the remaining samples contain the same noise (exercising limited MSAA compression with 8 samples and defeating MSAA compression with 4 samples)fill_fragmented8: same asfill_random, but all samples contain different random noise (defeating MSAA compression with 8 samples)
Decoding the clear/copy/blit/resolve region identifiers in subtest names:
region_full: the operation runs on the whole imageregion_partial: the operation excludes a small area, but the region offsets and extents are aligned to 8region_unaligned: the operation excludes a small area, and the region offsets and extents are odd (unaligned)region_yflip: the operation runs on the whole image, but it blits/resolves the image upside downregion_yflip_unaligned: same asregion_yflip, but the operation excludes a small area and the region offsets and extents are odd (unaligned)
Decoding other identifiers in subtest names:
2d,2d_array4,3d: the image dimensionality,2d_array4means a 2D image with 4 layers1s-8s: the number of samplessrc_linear: the source image uses linear tilingdst_linear: the destination image uses linear tiling
This measures the throughput of sparse bind/unbind operations in API calls/s.
Each sparse bind/unbind operation is followed by either no command buffer, empty command buffer, or simple command buffer. The command buffer, if present, always waits for its sparse bind/unbind operation.
The last 2 columns show test results for an asynchronous sparse bind queue that runs with no waits.
The buffer used for testing is divided into an equal number of sparse blocks. Each sparse block has its own memory allocation that can be bound/unbound.
Decoding subtest names:
bind_one: each call binds 1 new sparse block, increasing the number of bound sparse blocks monotonically (the subtest always starts with all sparse blocks unbound)unbind_one: each call unbinds 1 sparse block, decreasing the number of bound sparse blocks monotonically (the subtest always starts with all sparse blocks bound)bind_unbind_same_one: even calls bind the same sparse block, odd calls unbind itbind_unbind_all: even calls bind all sparse blocks at once, odd calls unbind all at oncesizeNm: the buffer has N MBblockNk: each sparse block has N KBstart_bound: the subtest starts with all sparse blocks bound (bind_onenever has this,unbind_onealways has this)
Dependencies: Vulkan, GL, EGL (surfaceless), libpcre2, libpng, libshaderc
mkdir build
cd build
meson setup ..
ninja
TBD
We recommend that the GPU power profile is set to maintain a constant GPU graphics core frequency. This is recommended for stability of memory bandwidth results, and required to get accurate measurements of performance per clock. When we measure performance per clock, the frequency that we choose (low or high) is irrelevant. Reduced constant frequencies are also useful when we want to isolate the effect of performance per clock optimizations from memory bandwidth optimizations.
Run sudo umr --gui &, select your GPU in the tab at the top, and then select the Power tab. In there, select one of the DPM (dynamic power management) profiles that begin with profile. All profile_* profiles maintain constant pre-determined frequencies. The frequency changes are shown in real time on the Power tab.
Since constant frequencies defeat power optimizations and can cause more heat to be generated, the firmware may change the profile back to auto if temperatures exceed safe limits. This will be immediately visible in the real time frequency chart on the Power tab.
Get umr here: https://gitlab.freedesktop.org/tomstdenis/umr
- GPU timestamps are used for measurements.
- Each subtest contains a warm-up phase where N initial iterations are discarded, but it's not enough if a GPU takes a longer time to ramp up its frequency. It's recommended to use a power profile that keeps the frequency constant.
- % progress is printed while building pipelines and executing subtests. Results are only printed at the end (unless a specific test has multiple stages).
- The app is windowless and doesn't even register with the window system where that's possible.
- If needed for debugging or developing new tests/subtests, it can save any rendered image to a PNG and open it in an image viewer.