IQ.Pilot Release Commit @ b6534c0
This commit is contained in:
14
artifacts/package_sources/tinygrad/extra/sqtt/README.md
Normal file
14
artifacts/package_sources/tinygrad/extra/sqtt/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# SQTT Profiling
|
||||
|
||||
## Getting SQ Thread Trace
|
||||
|
||||
`VIZ=2` to enable SQTT profiling.
|
||||
|
||||
`SQTT_ITRACE_SE_MASK=X` to select shader engines for instruction tracing, -1 = all, 0 = disabled, >0 = SE bitmask, default 0b11.
|
||||
|
||||
`SQTT_BUFFER_SIZE=X` to change size of SQTT buffer (per shader engine, 6 SEs on 7900xtx) in megabytes, default 256.
|
||||
|
||||
## Viewing the traces
|
||||
|
||||
- Web UI: `tinygrad/viz/serve.py`
|
||||
- Command line: `python -m tinygrad.renderer.amd.sqtt`
|
||||
@@ -0,0 +1,27 @@
|
||||
import os, subprocess, sys, shlex
|
||||
from pathlib import Path
|
||||
from tinygrad.helpers import temp, getenv
|
||||
|
||||
EXAMPLES_DIR = Path(__file__).parent
|
||||
PROFILE_PATH = Path(temp("profile.pkl", append_user=True))
|
||||
|
||||
EXAMPLES = {
|
||||
"empty":"test/backend/test_custom_kernel.py TestCustomKernel.test_empty",
|
||||
"plus":"test/test_tiny.py TestTiny.test_plus",
|
||||
"gemm":"-c \"from tinygrad import Tensor; (Tensor.empty(N:=32, N)@Tensor.empty(N, N)).realize()\"",
|
||||
"sync":"test/amd/test_asm_kernel.py TestAsmKernel.test_lds_sync",
|
||||
"handwritten":"test/amd/test_asm_kernel.py TestAsmKernel.test_handwritten",
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
arch = subprocess.check_output(["python", "-c", "from tinygrad import Device; print(Device['AMD'].arch)"], text=True,
|
||||
env={**os.environ, "DEBUG":"0"}).rstrip()
|
||||
(EXAMPLES_DIR/arch).mkdir(exist_ok=True)
|
||||
for name,test in EXAMPLES.items():
|
||||
if getenv("NAME", name) != name: continue
|
||||
for i in range(2):
|
||||
# AM_RESET=1 gets a clear trace, does not work on mi300 machines
|
||||
subprocess.run([sys.executable, *shlex.split(test)], cwd=EXAMPLES_DIR.parent.parent.parent,
|
||||
env={**os.environ, "DEV":"AMD", "AM_RESET":"1" if not arch.startswith("gfx9") else "0", "VIZ":"-2", "PYTHONPATH":"."})
|
||||
PROFILE_PATH.rename(dest:=EXAMPLES_DIR/arch/f"profile_{name}_run_{i}.pkl")
|
||||
print(f"saved SQTT trace to {dest}")
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
23
artifacts/package_sources/tinygrad/extra/sqtt/install_rocprof_decoder.py
Executable file
23
artifacts/package_sources/tinygrad/extra/sqtt/install_rocprof_decoder.py
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
import os, platform, shutil, subprocess
|
||||
from pathlib import Path
|
||||
from tinygrad.helpers import fetch, OSX
|
||||
|
||||
VERSION = "0.1.6"
|
||||
DEST = Path("/usr/local/lib")
|
||||
DEST.mkdir(exist_ok=True)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if OSX:
|
||||
arch = "arm64" if platform.machine() == "arm64" else "x86_64"
|
||||
dmg = fetch(f"https://github.com/ROCm/rocprof-trace-decoder/releases/download/{VERSION}/rocprof-trace-decoder-macos-{arch}-{VERSION}-Darwin.dmg")
|
||||
mnt = Path(subprocess.check_output(["hdiutil", "attach", "-nobrowse", "-readonly", "-mountrandom", "/tmp", str(dmg)],
|
||||
text=True).split("\t")[-1].strip())
|
||||
try: shutil.copy2(next(mnt.rglob("librocprof-trace-decoder.dylib")), DEST)
|
||||
finally: subprocess.run(["hdiutil", "detach", str(mnt)], check=True)
|
||||
lib = DEST/"librocprof-trace-decoder.dylib"
|
||||
else:
|
||||
lib = DEST/"librocprof-trace-decoder.so"
|
||||
os.system(f"sudo curl -L https://github.com/ROCm/rocprof-trace-decoder/raw/{VERSION}/releases/linux_glibc_2_28_x86_64/librocprof-trace-decoder.so -o {lib}")
|
||||
os.system("sudo ldconfig")
|
||||
print(f"Installed {lib.name} ({VERSION}) to", DEST)
|
||||
347
artifacts/package_sources/tinygrad/extra/sqtt/rgptool.py
Executable file
347
artifacts/package_sources/tinygrad/extra/sqtt/rgptool.py
Executable file
@@ -0,0 +1,347 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
import argparse, ctypes, struct, hashlib, pickle, code, typing, functools
|
||||
import tinygrad.runtime.autogen.sqtt as sqtt
|
||||
from tinygrad.device import ProfileEvent, ProfileDeviceEvent, ProfileProgramEvent
|
||||
from tinygrad.runtime.ops_amd import ProfileSQTTEvent
|
||||
from tinygrad.helpers import round_up, flatten, all_same, temp
|
||||
from dataclasses import dataclass
|
||||
|
||||
CHUNK_CLASSES = {
|
||||
sqtt.SQTT_FILE_CHUNK_TYPE_ASIC_INFO: sqtt.struct_sqtt_file_chunk_asic_info,
|
||||
sqtt.SQTT_FILE_CHUNK_TYPE_SQTT_DESC: sqtt.struct_sqtt_file_chunk_sqtt_desc,
|
||||
sqtt.SQTT_FILE_CHUNK_TYPE_SQTT_DATA: sqtt.struct_sqtt_file_chunk_sqtt_data,
|
||||
sqtt.SQTT_FILE_CHUNK_TYPE_API_INFO: sqtt.struct_sqtt_file_chunk_api_info,
|
||||
sqtt.SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS: sqtt.struct_sqtt_file_chunk_queue_event_timings,
|
||||
sqtt.SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION: sqtt.struct_sqtt_file_chunk_clock_calibration,
|
||||
sqtt.SQTT_FILE_CHUNK_TYPE_CPU_INFO: sqtt.struct_sqtt_file_chunk_cpu_info,
|
||||
sqtt.SQTT_FILE_CHUNK_TYPE_SPM_DB: sqtt.struct_sqtt_file_chunk_spm_db,
|
||||
sqtt.SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE: sqtt.struct_sqtt_file_chunk_code_object_database,
|
||||
sqtt.SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS: sqtt.struct_sqtt_file_chunk_code_object_loader_events,
|
||||
sqtt.SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION: sqtt.struct_sqtt_file_chunk_pso_correlation,
|
||||
}
|
||||
|
||||
def pretty(val, pad=0) -> str:
|
||||
if isinstance(val, (ctypes.Structure, ctypes.Union)):
|
||||
nl = '\n' # old python versions don't support \ in f-strings
|
||||
return f"{val.__class__.__name__}({nl}{' '*(pad+2)}{(f', {nl}'+' '*(pad+2)).join([f'{field[0]}={pretty(getattr(val, field[0]), pad=pad+2)}' for field in val._fields_])}{nl}{' '*pad})"
|
||||
if isinstance(val, ctypes.Array):
|
||||
return f"[{', '.join(map(pretty, val))}]"
|
||||
if isinstance(val, int) and val >= 1024: return hex(val)
|
||||
return repr(val)
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RGPChunk:
|
||||
header: sqtt.Structure
|
||||
data: list[typing.Any]|list[tuple[typing.Any, bytes]]|bytes|None = None
|
||||
def print(self):
|
||||
print(pretty(self.header))
|
||||
# if isinstance(self.data, bytes): print(repr(self.data))
|
||||
if isinstance(self.data, list):
|
||||
for dchunk in self.data:
|
||||
if isinstance(dchunk, tuple):
|
||||
print(pretty(dchunk[0]))
|
||||
# print(repr(dchunk[1]))
|
||||
else:
|
||||
print(pretty(dchunk))
|
||||
# TODO: `def fixup` and true immutability
|
||||
def to_bytes(self, offset:int) -> bytes:
|
||||
cid = self.header.header.chunk_id.type
|
||||
match cid:
|
||||
case _ if cid in {sqtt.SQTT_FILE_CHUNK_TYPE_ASIC_INFO, sqtt.SQTT_FILE_CHUNK_TYPE_CPU_INFO, sqtt.SQTT_FILE_CHUNK_TYPE_API_INFO, sqtt.SQTT_FILE_CHUNK_TYPE_SQTT_DESC}:
|
||||
self.header.header.size_in_bytes = ctypes.sizeof(self.header)
|
||||
return bytes(self.header)
|
||||
case sqtt.SQTT_FILE_CHUNK_TYPE_SQTT_DATA:
|
||||
assert isinstance(self.data, bytes)
|
||||
self.header.header.size_in_bytes = ctypes.sizeof(self.header) + len(self.data)
|
||||
self.header.offset = offset+ctypes.sizeof(self.header)
|
||||
self.header.size = len(self.data)
|
||||
return bytes(self.header) + self.data
|
||||
case sqtt.SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE:
|
||||
assert isinstance(self.data, list)
|
||||
data_codb = typing.cast(list[tuple[sqtt.struct_sqtt_code_object_database_record, bytes]], self.data)
|
||||
ret = bytearray()
|
||||
sz = ctypes.sizeof(self.header)+sum([ctypes.sizeof(record_hdr)+round_up(len(record_blob), 4) for record_hdr,record_blob in data_codb])
|
||||
self.header.header.size_in_bytes = sz
|
||||
self.header.offset = offset
|
||||
self.header.record_count = len(data_codb)
|
||||
self.header.size = sz
|
||||
ret += self.header
|
||||
for record_hdr,record_blob in data_codb:
|
||||
record_hdr.size = round_up(len(record_blob), 4)
|
||||
ret += record_hdr
|
||||
ret += record_blob.ljust(4, b'\x00')
|
||||
return ret
|
||||
case sqtt.SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS:
|
||||
assert isinstance(self.data, list)
|
||||
data_lev = typing.cast(list[tuple[sqtt.struct_sqtt_code_object_loader_events_record]], self.data)
|
||||
self.header.header.size_in_bytes = ctypes.sizeof(self.header)+ctypes.sizeof(sqtt.struct_sqtt_code_object_loader_events_record)*len(data_lev)
|
||||
self.header.offset = offset
|
||||
self.header.record_size = ctypes.sizeof(sqtt.struct_sqtt_code_object_loader_events_record)
|
||||
self.header.record_count = len(data_lev)
|
||||
return bytes(self.header) + b''.join(map(bytes, data_lev))
|
||||
case sqtt.SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION:
|
||||
assert isinstance(self.data, list)
|
||||
data_pso = typing.cast(list[tuple[sqtt.struct_sqtt_pso_correlation_record]], self.data)
|
||||
self.header.header.size_in_bytes = ctypes.sizeof(self.header)+ctypes.sizeof(sqtt.struct_sqtt_pso_correlation_record)*len(data_pso)
|
||||
self.header.offset = offset
|
||||
self.header.record_size = ctypes.sizeof(sqtt.struct_sqtt_pso_correlation_record)
|
||||
self.header.record_count = len(data_pso)
|
||||
return bytes(self.header) + b''.join(map(bytes, data_pso))
|
||||
case _: raise NotImplementedError(pretty(self.header))
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RGP:
|
||||
header: sqtt.struct_sqtt_file_header
|
||||
chunks: list[RGPChunk]
|
||||
@staticmethod
|
||||
def from_bytes(blob: bytes) -> RGP:
|
||||
file_header = sqtt.struct_sqtt_file_header.from_buffer_copy(blob)
|
||||
assert file_header.magic_number == sqtt.SQTT_FILE_MAGIC_NUMBER and file_header.version_major == sqtt.SQTT_FILE_VERSION_MAJOR
|
||||
i = file_header.chunk_offset
|
||||
chunks = []
|
||||
while i < len(blob):
|
||||
assert i%4==0, hex(i)
|
||||
hdr = sqtt.struct_sqtt_file_chunk_header.from_buffer_copy(blob, i)
|
||||
cid = hdr.chunk_id.type
|
||||
header: ctypes.Structure
|
||||
match cid:
|
||||
case _ if cid in {sqtt.SQTT_FILE_CHUNK_TYPE_RESERVED, sqtt.SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS, sqtt.SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION, sqtt.SQTT_FILE_CHUNK_TYPE_SPM_DB}:
|
||||
chunk = None
|
||||
case sqtt.SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE:
|
||||
header = sqtt.struct_sqtt_file_chunk_code_object_database.from_buffer_copy(blob, i)
|
||||
j = header.offset + ctypes.sizeof(header)
|
||||
data: list = []
|
||||
while j < header.offset + header.size:
|
||||
rec_hdr: ctypes.Structure = sqtt.struct_sqtt_code_object_database_record.from_buffer_copy(blob, j)
|
||||
data.append((rec_hdr, elf:=blob[j+ctypes.sizeof(rec_hdr):j+ctypes.sizeof(rec_hdr)+rec_hdr.size]))
|
||||
assert elf[:4] == b'\x7fELF', repr(elf[:16])
|
||||
j += ctypes.sizeof(rec_hdr)+rec_hdr.size
|
||||
assert len(data) == header.record_count
|
||||
chunk = RGPChunk(header, data)
|
||||
case sqtt.SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS:
|
||||
header = sqtt.struct_sqtt_file_chunk_code_object_loader_events.from_buffer_copy(blob, i)
|
||||
data = [sqtt.struct_sqtt_code_object_loader_events_record.from_buffer_copy(blob, header.offset+ctypes.sizeof(header)+j*header.record_size)
|
||||
for j in range(header.record_count)]
|
||||
chunk = RGPChunk(header, data)
|
||||
case sqtt.SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION:
|
||||
header = sqtt.struct_sqtt_file_chunk_pso_correlation.from_buffer_copy(blob, i)
|
||||
data = [sqtt.struct_sqtt_pso_correlation_record.from_buffer_copy(blob, header.offset+ctypes.sizeof(header)+j*header.record_size)
|
||||
for j in range(header.record_count)]
|
||||
chunk = RGPChunk(header, data)
|
||||
case sqtt.SQTT_FILE_CHUNK_TYPE_SQTT_DATA:
|
||||
header = sqtt.struct_sqtt_file_chunk_sqtt_data.from_buffer_copy(blob, i)
|
||||
chunk = RGPChunk(header, blob[header.offset:header.offset+header.size])
|
||||
case _ if cid in {sqtt.SQTT_FILE_CHUNK_TYPE_ASIC_INFO, sqtt.SQTT_FILE_CHUNK_TYPE_CPU_INFO, sqtt.SQTT_FILE_CHUNK_TYPE_API_INFO,
|
||||
sqtt.SQTT_FILE_CHUNK_TYPE_SQTT_DESC}:
|
||||
chunk = RGPChunk(CHUNK_CLASSES[cid].from_buffer_copy(blob, i))
|
||||
case _:
|
||||
chunk = None
|
||||
print(f"unknown chunk id {cid}")
|
||||
if chunk is not None: chunks.append(chunk)
|
||||
i += hdr.size_in_bytes
|
||||
assert i == len(blob), f'{i} != {len(blob)}'
|
||||
return RGP(file_header, chunks)
|
||||
@staticmethod
|
||||
def from_profile(profile_pickled, device:str|None=None):
|
||||
profile: list[ProfileEvent] = pickle.loads(profile_pickled)
|
||||
def _is_base_dev(d): return all(p.isdigit() for p in d.split(":")[1:])
|
||||
device_events = {x.device:x for x in profile if isinstance(x, ProfileDeviceEvent) and x.device.startswith('AMD') and _is_base_dev(x.device)}
|
||||
if device is None:
|
||||
if len(device_events) == 0: raise RuntimeError('No supported devices found in profile')
|
||||
if len(device_events) > 1: raise RuntimeError(f"More than one supported device found, select which one to export: {', '.join(device_events.keys())}")
|
||||
_, device_event = device_events.popitem()
|
||||
else:
|
||||
if device not in device_events: raise RuntimeError(f"Device {device} not found in profile, devices in profile: {', '.join(device_events.keys())} ")
|
||||
device_event = device_events[device]
|
||||
sqtt_events = [x for x in profile if isinstance(x, ProfileSQTTEvent) and x.device == device_event.device]
|
||||
device_props = device_event.props
|
||||
# merge events per SE
|
||||
merged_sqtt_events:dict[int, ProfileSQTTEvent] = {}
|
||||
for ev in sqtt_events:
|
||||
if ev.se not in merged_sqtt_events: merged_sqtt_events[ev.se] = ev
|
||||
else:
|
||||
merged_sqtt_events[ev.se] = ProfileSQTTEvent(
|
||||
device=ev.device,
|
||||
kern=ev.kern,
|
||||
se=ev.se,
|
||||
itrace=merged_sqtt_events[ev.se].itrace or ev.itrace,
|
||||
blob=merged_sqtt_events[ev.se].blob + ev.blob,
|
||||
exec_tag=0,
|
||||
)
|
||||
sqtt_events = list(merged_sqtt_events.values())
|
||||
|
||||
if len(sqtt_events) == 0: raise RuntimeError(f"Device {device_event.device} doesn't contain SQTT data")
|
||||
gfx_ver = device_props['gfx_target_version'] // 10000
|
||||
gfx_iplvl = getattr(sqtt, f"SQTT_GFXIP_LEVEL_GFXIP_{device_props['gfx_target_version']//10000}_{(device_props['gfx_target_version']//100)%100}",
|
||||
getattr(sqtt, f"SQTT_GFXIP_LEVEL_GFXIP_{device_props['gfx_target_version']//10000}", None))
|
||||
sqtt_itrace_enabled = any([event.itrace for event in sqtt_events])
|
||||
sqtt_itrace_masked = not all_same([event.itrace for event in sqtt_events])
|
||||
sqtt_itrace_se_mask = functools.reduce(lambda a,b: a|b, [int(event.itrace) << event.se for event in sqtt_events], 0) if sqtt_itrace_masked else 0
|
||||
load_events = [x for x in profile if isinstance(x, ProfileProgramEvent) and x.device == device_event.device]
|
||||
loads = [(event.base, struct.unpack('<Q', hashlib.md5(event.lib).digest()[:8])*2) for event in load_events if event.base is not None and event.lib is not None]
|
||||
code_objects = list(dict.fromkeys([x.lib for x in load_events if x.lib is not None]).keys())
|
||||
if len(loads) == 0: raise RuntimeError('No load events in profile')
|
||||
# TODO: tons of stuff hardcoded for 7900xtx
|
||||
file_header = sqtt.struct_sqtt_file_header(
|
||||
magic_number=sqtt.SQTT_FILE_MAGIC_NUMBER,
|
||||
version_major=sqtt.SQTT_FILE_VERSION_MAJOR,
|
||||
version_minor=sqtt.SQTT_FILE_VERSION_MINOR,
|
||||
flags=sqtt.struct_sqtt_file_header_flags(value=1,),
|
||||
chunk_offset=ctypes.sizeof(sqtt.struct_sqtt_file_header),
|
||||
)
|
||||
chunks = [
|
||||
RGPChunk(sqtt.struct_sqtt_file_chunk_cpu_info(
|
||||
header=sqtt.struct_sqtt_file_chunk_header(
|
||||
chunk_id=sqtt.struct_sqtt_file_chunk_id(type=sqtt.SQTT_FILE_CHUNK_TYPE_CPU_INFO),
|
||||
major_version=0, minor_version=0,
|
||||
),
|
||||
cpu_timestamp_freq=1000000000,
|
||||
clock_speed=2994, # in mhz???
|
||||
num_logical_cores=64,
|
||||
num_physical_cores=32,
|
||||
system_ram_size=256*1024, # in mb???
|
||||
)),
|
||||
RGPChunk(sqtt.struct_sqtt_file_chunk_asic_info(
|
||||
header=sqtt.struct_sqtt_file_chunk_header(
|
||||
chunk_id=sqtt.struct_sqtt_file_chunk_id(type=sqtt.SQTT_FILE_CHUNK_TYPE_ASIC_INFO),
|
||||
major_version=0, minor_version=5,
|
||||
),
|
||||
flags=0,
|
||||
trace_shader_core_clock=0x93f05080,
|
||||
trace_memory_clock=0x4a723a40,
|
||||
device_id={110000: 0x744c, 110003: 0x7480, 120001: 0x7550, 120000: 0x7550}[device_props['gfx_target_version']],
|
||||
device_revision_id=0xc8,
|
||||
vgprs_per_simd=1536,
|
||||
sgprs_per_simd=128*16,
|
||||
shader_engines=device_props['array_count'] // device_props['simd_arrays_per_engine'],
|
||||
compute_unit_per_shader_engine=device_props['simd_count'] // device_props['simd_per_cu'] // (device_props['array_count'] // device_props['simd_arrays_per_engine']),
|
||||
simd_per_compute_unit=device_props['simd_per_cu'],
|
||||
wavefronts_per_simd=device_props['max_waves_per_simd'],
|
||||
minimum_vgpr_alloc=4,
|
||||
vgpr_alloc_granularity=8,
|
||||
minimum_sgpr_alloc=128,
|
||||
sgpr_alloc_granularity=128,
|
||||
hardware_contexts=8,
|
||||
gpu_type=sqtt.SQTT_GPU_TYPE_DISCRETE,
|
||||
gfxip_level=gfx_iplvl,
|
||||
gpu_index=0,
|
||||
gds_size=0,
|
||||
gds_per_shader_engine=0,
|
||||
ce_ram_size=0,
|
||||
ce_ram_size_graphics=0,
|
||||
ce_ram_size_compute=0,
|
||||
max_number_of_dedicated_cus=0,
|
||||
vram_size=24 * 1024 * 1024 * 1024, # 24 GB
|
||||
vram_bus_width=384, # 384-bit
|
||||
l2_cache_size=6 * 1024 * 1024, # 6 MB
|
||||
l1_cache_size=32 * 1024, # 32 KB per SIMD (?)
|
||||
lds_size=device_props['lds_size_in_kb'] * 1024,
|
||||
gpu_name=b'NAVI31',
|
||||
alu_per_clock=0,
|
||||
texture_per_clock=0,
|
||||
prims_per_clock=6,
|
||||
pixels_per_clock=0,
|
||||
gpu_timestamp_frequency=100000000, # 100 MHz
|
||||
max_shader_core_clock=2500000000, # 2.5 GHz (boost clock)
|
||||
max_memory_clock=1250000000, # 1.25 GHz
|
||||
memory_ops_per_clock=16,
|
||||
memory_chip_type=sqtt.SQTT_MEMORY_TYPE_GDDR6,
|
||||
lds_granularity=512,
|
||||
cu_mask=((255, 255),)*6 + ((0,0),)*(32-6),
|
||||
gl1_cache_size=256 * 1024, # 256 KB
|
||||
instruction_cache_size=32 * 1024, # 32 KB
|
||||
scalar_cache_size=16 * 1024, # 16 KB
|
||||
mall_cache_size=96 * 1024 * 1024, # 96 MB
|
||||
)),
|
||||
RGPChunk(sqtt.struct_sqtt_file_chunk_api_info(
|
||||
header=sqtt.struct_sqtt_file_chunk_header(
|
||||
chunk_id=sqtt.struct_sqtt_file_chunk_id(type=sqtt.SQTT_FILE_CHUNK_TYPE_API_INFO),
|
||||
major_version=0,
|
||||
minor_version=2,
|
||||
),
|
||||
api_type=5, # HIP, not in enum
|
||||
major_version=12, minor_version=0,
|
||||
profiling_mode=sqtt.SQTT_PROFILING_MODE_PRESENT,
|
||||
instruction_trace_mode=sqtt.SQTT_INSTRUCTION_TRACE_FULL_FRAME if sqtt_itrace_enabled else sqtt.SQTT_INSTRUCTION_TRACE_DISABLED,
|
||||
instruction_trace_data=sqtt.union_sqtt_instruction_trace_data(
|
||||
shader_engine_filter=sqtt.union_sqtt_instruction_trace_data_shader_engine_filter(mask=sqtt_itrace_se_mask),
|
||||
),
|
||||
)),
|
||||
*flatten([(
|
||||
RGPChunk(sqtt.struct_sqtt_file_chunk_sqtt_desc(
|
||||
header=sqtt.struct_sqtt_file_chunk_header(
|
||||
chunk_id=sqtt.struct_sqtt_file_chunk_id(type=sqtt.SQTT_FILE_CHUNK_TYPE_SQTT_DESC, index=sqtt_event.se),
|
||||
major_version=0, minor_version=2,
|
||||
),
|
||||
shader_engine_index=sqtt_event.se,
|
||||
sqtt_version={11: sqtt.SQTT_VERSION_3_2, 12: sqtt.SQTT_VERSION_3_3}.get(gfx_ver),
|
||||
v1=sqtt.struct_sqtt_file_chunk_sqtt_desc_v1(
|
||||
instrumentation_spec_version=1,
|
||||
instrumentation_api_version=0,
|
||||
compute_unit_index=0,
|
||||
)
|
||||
)),
|
||||
RGPChunk(sqtt.struct_sqtt_file_chunk_sqtt_data(
|
||||
header=sqtt.struct_sqtt_file_chunk_header(
|
||||
chunk_id=sqtt.struct_sqtt_file_chunk_id(type=sqtt.SQTT_FILE_CHUNK_TYPE_SQTT_DATA, index=sqtt_event.se),
|
||||
major_version=0, minor_version=0,
|
||||
),
|
||||
), sqtt_event.blob),
|
||||
) for sqtt_event in sqtt_events]),
|
||||
RGPChunk(sqtt.struct_sqtt_file_chunk_code_object_database(
|
||||
header=sqtt.struct_sqtt_file_chunk_header(
|
||||
chunk_id=sqtt.struct_sqtt_file_chunk_id(type=sqtt.SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE),
|
||||
major_version=0, minor_version=0,
|
||||
),
|
||||
), [(sqtt.struct_sqtt_code_object_database_record(), lib) for lib in code_objects]),
|
||||
RGPChunk(sqtt.struct_sqtt_file_chunk_code_object_loader_events(
|
||||
header=sqtt.struct_sqtt_file_chunk_header(
|
||||
chunk_id=sqtt.struct_sqtt_file_chunk_id(type=sqtt.SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS),
|
||||
major_version=1, minor_version=0,
|
||||
),
|
||||
), [sqtt.struct_sqtt_code_object_loader_events_record(base_address=base, code_object_hash=hash) for base,hash in loads]),
|
||||
RGPChunk(sqtt.struct_sqtt_file_chunk_pso_correlation(
|
||||
header=sqtt.struct_sqtt_file_chunk_header(
|
||||
chunk_id=sqtt.struct_sqtt_file_chunk_id(type=sqtt.SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION),
|
||||
major_version=0, minor_version=0,
|
||||
),
|
||||
), [sqtt.struct_sqtt_pso_correlation_record(api_pso_hash=hash[0], pipeline_hash=hash) for _,hash in loads])
|
||||
]
|
||||
return RGP(file_header, chunks)
|
||||
def to_bytes(self) -> bytes:
|
||||
ret = bytearray()
|
||||
ret += self.header
|
||||
for chunk in self.chunks:
|
||||
ret += chunk.to_bytes(len(ret))
|
||||
return bytes(ret)
|
||||
def print(self):
|
||||
print(pretty(self.header))
|
||||
for chunk in self.chunks: chunk.print()
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(prog='rgptool', description='A tool to create (from pickled tinygrad profile), inspect and modify Radeon GPU Profiler files')
|
||||
parser.add_argument('command')
|
||||
parser.add_argument('input', nargs='?', default=temp("profile.pkl", append_user=True))
|
||||
parser.add_argument('-d', '--device')
|
||||
parser.add_argument('-o', '--output')
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.input, 'rb') as fd: input_bytes = fd.read()
|
||||
|
||||
match args.command:
|
||||
case 'print':
|
||||
rgp = RGP.from_bytes(input_bytes)
|
||||
rgp.print()
|
||||
case 'create':
|
||||
rgp = RGP.from_profile(input_bytes, device=args.device)
|
||||
# rgp.to_bytes() # fixup
|
||||
# rgp.print()
|
||||
case 'repl':
|
||||
rgp = RGP.from_bytes(input_bytes)
|
||||
code.interact(local=locals())
|
||||
case _: raise RuntimeError(args.command)
|
||||
|
||||
if args.output is not None:
|
||||
with open(args.output, 'wb+') as fd: fd.write(rgp.to_bytes())
|
||||
print(f"Saved to {args.output}")
|
||||
241
artifacts/package_sources/tinygrad/extra/sqtt/roc.py
Executable file
241
artifacts/package_sources/tinygrad/extra/sqtt/roc.py
Executable file
@@ -0,0 +1,241 @@
|
||||
#!/usr/bin/env python3
|
||||
import ctypes, pathlib, argparse, pickle, dataclasses, threading, itertools
|
||||
from decimal import Decimal
|
||||
from typing import Generator
|
||||
from tinygrad.helpers import temp, unwrap, DEBUG
|
||||
from tinygrad.runtime.ops_amd import ProfileSQTTEvent
|
||||
from tinygrad.runtime.autogen import rocprof
|
||||
from tinygrad.renderer.amd.dsl import Inst
|
||||
from tinygrad.helpers import ProfileEvent, ProfileRangeEvent, ProfilePointEvent
|
||||
from tinygrad.device import ProfileProgramEvent
|
||||
from test.amd.disasm import disasm
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class InstExec:
|
||||
typ:str
|
||||
pc:int
|
||||
stall:int
|
||||
dur:int
|
||||
time:int
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class WaveSlot:
|
||||
wave_id:int
|
||||
cu:int
|
||||
simd:int
|
||||
se:int
|
||||
@property
|
||||
def cu_loc(self) -> str: return f"SE:{self.se} CU:{self.cu}"
|
||||
@property
|
||||
def wave_loc(self) -> str: return f"{self.cu_loc} SIMD:{self.simd} W:{self.wave_id}"
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class WaveExec(WaveSlot):
|
||||
begin_time:int
|
||||
end_time:int
|
||||
insts:bytearray
|
||||
def unpack_insts(self) -> Generator[InstExec, None, None]:
|
||||
sz = ctypes.sizeof(struct:=rocprof.rocprofiler_thread_trace_decoder_inst_t)
|
||||
insts_array = (struct*(len(self.insts)//sz)).from_buffer(self.insts)
|
||||
for inst in insts_array:
|
||||
inst_typ = rocprof.enum_rocprofiler_thread_trace_decoder_inst_category_t.get(inst.category)
|
||||
yield InstExec(inst_typ, inst.pc.address, inst.stall, inst.duration, inst.time)
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class OccEvent(WaveSlot):
|
||||
time:int
|
||||
start:int
|
||||
|
||||
RunKey = tuple[str, int]
|
||||
|
||||
class _ROCParseCtx:
|
||||
def __init__(self, sqtt_evs:list[ProfileSQTTEvent], disasms:dict[str, dict[int, Inst]]):
|
||||
self.sqtt_evs, self.disasms = iter(sqtt_evs), {k:{k2:(disasm(v2), v2.size()) for k2,v2 in v.items()} for k,v in disasms.items()}
|
||||
self.inst_execs:dict[RunKey, list[WaveExec]] = {}
|
||||
self.occ_events:dict[RunKey, list[OccEvent]] = {}
|
||||
|
||||
def next_sqtt(self):
|
||||
x = next(self.sqtt_evs, None)
|
||||
self.active_run = (x.kern, x.exec_tag) if x is not None else None
|
||||
self.active_se = x.se if x is not None else None
|
||||
self.active_blob = (ctypes.c_ubyte * len(x.blob)).from_buffer_copy(x.blob) if x is not None else None
|
||||
return self.active_blob
|
||||
|
||||
def on_occupancy_ev(self, ev:rocprof.rocprofiler_thread_trace_decoder_occupancy_t):
|
||||
if DEBUG >= 5: print(f"OCC {ev.time=} {self.active_se=} {ev.cu=} {ev.simd=} {ev.wave_id=} {ev.start=}")
|
||||
self.occ_events.setdefault(unwrap(self.active_run), []).append(OccEvent(ev.wave_id, ev.cu, ev.simd, unwrap(self.active_se), ev.time, ev.start))
|
||||
|
||||
def on_wave_ev(self, ev:rocprof.rocprofiler_thread_trace_decoder_wave_t):
|
||||
if DEBUG >= 5: print(f"WAVE {ev.wave_id=} {self.active_se=} {ev.cu=} {ev.simd=} {ev.contexts=} {ev.begin_time=} {ev.end_time=}")
|
||||
# Skip wave events without instruction timings, occupancy events give the start and duration.
|
||||
if ev.instructions_size == 0: return
|
||||
|
||||
insts_blob = bytearray(sz:=ev.instructions_size * ctypes.sizeof(rocprof.rocprofiler_thread_trace_decoder_inst_t))
|
||||
ctypes.memmove((ctypes.c_char * sz).from_buffer(insts_blob), ev.instructions_array, sz)
|
||||
|
||||
self.inst_execs.setdefault(unwrap(self.active_run), []).append(WaveExec(ev.wave_id, ev.cu, ev.simd, unwrap(self.active_se), ev.begin_time,
|
||||
ev.end_time, insts_blob))
|
||||
|
||||
def decode(sqtt_evs:list[ProfileSQTTEvent], disasms:dict[str, dict[int, Inst]]) -> _ROCParseCtx:
|
||||
ROCParseCtx = _ROCParseCtx(sqtt_evs, disasms)
|
||||
|
||||
@rocprof.rocprof_trace_decoder_se_data_callback_t
|
||||
def copy_cb(buf, buf_size, _):
|
||||
if (prof_info:=ROCParseCtx.next_sqtt()) is None: return 0
|
||||
buf[0] = ctypes.cast(prof_info, ctypes.POINTER(ctypes.c_ubyte))
|
||||
buf_size[0] = len(prof_info)
|
||||
return len(prof_info)
|
||||
|
||||
@rocprof.rocprof_trace_decoder_trace_callback_t
|
||||
def trace_cb(record_type, events_ptr, n, _):
|
||||
match record_type:
|
||||
case rocprof.ROCPROFILER_THREAD_TRACE_DECODER_RECORD_OCCUPANCY:
|
||||
for ev in (rocprof.rocprofiler_thread_trace_decoder_occupancy_t * n).from_address(events_ptr): ROCParseCtx.on_occupancy_ev(ev)
|
||||
case rocprof.ROCPROFILER_THREAD_TRACE_DECODER_RECORD_WAVE:
|
||||
for ev in (rocprof.rocprofiler_thread_trace_decoder_wave_t * n).from_address(events_ptr): ROCParseCtx.on_wave_ev(ev)
|
||||
case rocprof.ROCPROFILER_THREAD_TRACE_DECODER_RECORD_REALTIME:
|
||||
if DEBUG >= 5:
|
||||
pairs = [(ev.shader_clock, ev.realtime_clock) for ev in (rocprof.rocprofiler_thread_trace_decoder_realtime_t * n).from_address(events_ptr)]
|
||||
print(f"REALTIME {pairs}")
|
||||
case _:
|
||||
if DEBUG >= 5: print(rocprof.enum_rocprofiler_thread_trace_decoder_record_type_t.get(record_type), events_ptr, n)
|
||||
return rocprof.ROCPROFILER_THREAD_TRACE_DECODER_STATUS_SUCCESS
|
||||
|
||||
@rocprof.rocprof_trace_decoder_isa_callback_t
|
||||
def isa_cb(instr_ptr, mem_size_ptr, size_ptr, pc, _):
|
||||
instr, mem_size_ptr[0] = ROCParseCtx.disasms[unwrap(ROCParseCtx.active_run)[0]][pc.address]
|
||||
|
||||
# this is the number of bytes to next instruction, set to 0 for end_pgm
|
||||
if instr == "s_endpgm": mem_size_ptr[0] = 0
|
||||
if (max_sz:=size_ptr[0]) == 0: return rocprof.ROCPROFILER_THREAD_TRACE_DECODER_STATUS_ERROR_OUT_OF_RESOURCES
|
||||
|
||||
# truncate the instr if it doesn't fit
|
||||
if (str_sz:=len(instr_bytes:=instr.encode()))+1 > max_sz: str_sz = max_sz
|
||||
ctypes.memmove(instr_ptr, instr_bytes, str_sz)
|
||||
size_ptr[0] = str_sz
|
||||
|
||||
return rocprof.ROCPROFILER_THREAD_TRACE_DECODER_STATUS_SUCCESS
|
||||
|
||||
exc:Exception|None = None
|
||||
def worker():
|
||||
nonlocal exc
|
||||
try: rocprof.rocprof_trace_decoder_parse_data(copy_cb, trace_cb, isa_cb, None)
|
||||
except AttributeError as e:
|
||||
exc = RuntimeError("Failed to find rocprof-trace-decoder. Run sudo ./extra/sqtt/install_rocprof_decoder.py to install")
|
||||
exc.__cause__ = e
|
||||
(t:=threading.Thread(target=worker, daemon=True)).start()
|
||||
t.join()
|
||||
if exc is not None:
|
||||
raise exc
|
||||
return ROCParseCtx
|
||||
|
||||
def unpack_occ(viz_data, i:int, j:int, key:tuple[str, int], data:list, p:ProfileProgramEvent, target:str) -> dict:
|
||||
from tinygrad.viz.serve import amd_decode, create_step, row_tuple
|
||||
steps = viz_data.ctxs[i]["steps"]
|
||||
if len(steps[j+1:]) > 0: return {"steps":[{k:v for k,v in s.items() if k != "data"} for s in steps[j+1:]]}
|
||||
base = unwrap(p.base)
|
||||
disasm:dict[int, Inst] = {addr+base:inst for addr,inst in amd_decode(unwrap(p.lib), target).items()}
|
||||
rctx = decode(data, {p.tag:disasm})
|
||||
cu_events:dict[str, list[ProfileEvent]] = {}
|
||||
# ** inst traces
|
||||
wave_insts:dict[str, dict[str, dict]] = {}
|
||||
inst_units:dict[str, itertools.count] = {}
|
||||
for w in rctx.inst_execs.get(key, []):
|
||||
if (u:=w.wave_loc) not in inst_units: inst_units[u] = itertools.count(0)
|
||||
n = next(inst_units[u])
|
||||
if (events:=cu_events.get(w.cu_loc)) is None: cu_events[w.cu_loc] = events = []
|
||||
events.append(ProfileRangeEvent(f"SIMD:{w.simd}", loc:=f"INST WAVE:{w.wave_id} N:{n}", Decimal(w.begin_time), Decimal(w.end_time)))
|
||||
wave_insts.setdefault(w.cu_loc, {})[f"{u} N:{n}"] = {"wave":w, "disasm":disasm, "prg":p, "run_number":n, "loc":loc}
|
||||
# ** occ traces (only WAVESTART/WAVEEND)
|
||||
units:dict[str, itertools.count] = {}
|
||||
wave_start:dict[str, int] = {}
|
||||
for occ in rctx.occ_events.get(key, []):
|
||||
if (u:=occ.wave_loc) not in units: units[u] = itertools.count(0)
|
||||
if u in inst_units: continue
|
||||
if occ.start: wave_start[u] = occ.time
|
||||
else:
|
||||
if (events:=cu_events.get(occ.cu_loc)) is None: cu_events[occ.cu_loc] = events = []
|
||||
events.append(ProfileRangeEvent(f"SIMD:{occ.simd}", f"OCC WAVE:{occ.wave_id} N:{next(units[u])}", Decimal(wave_start.pop(u)),Decimal(occ.time)))
|
||||
# ** split graph by CU
|
||||
for cu in sorted(cu_events, key=row_tuple):
|
||||
steps.append(create_step(f"{cu} {len(cu_events[cu])}", ("/cu-sqtt", i, len(steps)), depth=1,
|
||||
data=[ProfilePointEvent(unit, "start", unit, ts=Decimal(0)) for unit in units]+cu_events[cu]))
|
||||
for k in sorted(wave_insts.get(cu, []), key=row_tuple):
|
||||
wd = wave_insts[cu][k]
|
||||
steps.append(create_step(k.replace(cu, ""), ("/amd-sqtt-insts", i, len(steps)), loc=wd["loc"], depth=2,
|
||||
data={"fxn":unpack_insts, "args":(wd,)}))
|
||||
return {"steps":[{k:v for k,v in s.items() if k != "data"} for s in steps[j+1:]]}
|
||||
|
||||
def unpack_insts(viz_data, i:int, j:int, data:dict) -> dict:
|
||||
columns = ["PC", "Instruction", "Hits", "Cycles", "Stall", "Type"]
|
||||
inst_columns = ["N", "Clk", "Idle", "Dur", "Stall"]
|
||||
# Idle: The total time gap between the completion of previous instruction and the beginning of the current instruction.
|
||||
# The idle time can be caused by:
|
||||
# * Arbiter loss
|
||||
# * Source or destination register dependency
|
||||
# * Instruction cache miss
|
||||
# Stall: The total number of cycles the hardware pipe couldn't issue an instruction.
|
||||
# Duration: Total latency in cycles, defined as "Stall time + Issue time" for gfx9 or "Stall time + Execute time" for gfx10+.
|
||||
prev_instr = (w:=data["wave"]).begin_time
|
||||
pc_to_inst = data["disasm"]
|
||||
start_pc = None
|
||||
rows:dict[int, dict] = {}
|
||||
for pc, inst in pc_to_inst.items():
|
||||
if start_pc is None: start_pc = pc
|
||||
rows[pc] = {"pc":pc-start_pc, "inst":str(inst), "hit_count":0, "dur":0, "stall":0, "type":"", "hits":{"cols":inst_columns, "rows":[]}}
|
||||
for e in w.unpack_insts():
|
||||
if not (inst:=rows[e.pc]).get("type"): inst["type"] = str(e.typ).split("_")[-1]
|
||||
inst["hit_count"] += 1
|
||||
inst["dur"] += e.dur
|
||||
inst["stall"] += e.stall
|
||||
inst["hits"]["rows"].append((inst["hit_count"]-1, e.time, max(0, e.time-prev_instr), e.dur, e.stall))
|
||||
prev_instr = max(prev_instr, e.time + e.dur)
|
||||
summary = [{"label":"Total Cycles", "value":w.end_time-w.begin_time}, {"label":"SE", "value":w.se}, {"label":"CU", "value":w.cu},
|
||||
{"label":"SIMD", "value":w.simd}, {"label":"Wave ID", "value":w.wave_id}, {"label":"Run number", "value":data["run_number"]}]
|
||||
return {"rows":[tuple(v.values()) for v in rows.values()], "cols":columns, "metadata":[summary], "ref":viz_data.ref_map.get(data["prg"].name)}
|
||||
|
||||
def print_data(data:dict) -> None:
|
||||
from tabulate import tabulate
|
||||
# plaintext
|
||||
if "src" in data: print(data["src"])
|
||||
# table format
|
||||
elif "cols" in data:
|
||||
print(tabulate([r[:len(data["cols"])] for r in data["rows"]], headers=data["cols"], tablefmt="github"))
|
||||
|
||||
def main() -> None:
|
||||
import tinygrad.viz.serve as viz
|
||||
from tinygrad.uop.ops import RewriteTrace
|
||||
data = viz.VizData()
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--profile', type=pathlib.Path, metavar="PATH", help='Path to profile (optional file, default: latest profile)',
|
||||
default=pathlib.Path(temp("profile.pkl", append_user=True)))
|
||||
parser.add_argument('--kernel', type=str, default=None, metavar="NAME", help='Kernel to focus on (optional name, default: all kernels)')
|
||||
parser.add_argument('-n', type=int, default=3, metavar="NUM", help='Max traces to print (optional number, default: 3 traces)')
|
||||
args = parser.parse_args()
|
||||
|
||||
with args.profile.open("rb") as f: profile = pickle.load(f)
|
||||
|
||||
viz.get_profile(profile, data=data)
|
||||
|
||||
# List all kernels
|
||||
if args.kernel is None:
|
||||
for c in data.ctxs:
|
||||
print(c["name"])
|
||||
for s in c["steps"]: print(" "+s["name"])
|
||||
return None
|
||||
|
||||
# Find kernel trace
|
||||
trace = next((c for c in data.ctxs if c["name"] == f"SQTT {args.kernel}"), None)
|
||||
if not trace: raise RuntimeError(f"no matching trace for {args.kernel}")
|
||||
n = 0
|
||||
for s in trace["steps"]:
|
||||
if "PKTS" in s["name"]: continue
|
||||
print(s["name"])
|
||||
ret = viz.get_render(data, s["query"])
|
||||
print_data(ret)
|
||||
n += 1
|
||||
if n > args.n: break
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
845
artifacts/package_sources/tinygrad/extra/sqtt/sqtt.h
Normal file
845
artifacts/package_sources/tinygrad/extra/sqtt/sqtt.h
Normal file
@@ -0,0 +1,845 @@
|
||||
#include <stdint.h>
|
||||
|
||||
// Original definition in pal is in c++ and clang2py can't autogen it correctly
|
||||
// Most of this is copy pasted from mesa/src/amd/common/ac_rgp.{h, c}
|
||||
|
||||
/*
|
||||
* Copyright 2020 Advanced Micro Devices, Inc.
|
||||
* Copyright 2020 Valve Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define SQTT_FILE_MAGIC_NUMBER 0x50303042
|
||||
#define SQTT_FILE_VERSION_MAJOR 1
|
||||
#define SQTT_FILE_VERSION_MINOR 5
|
||||
|
||||
#define SQTT_GPU_NAME_MAX_SIZE 256
|
||||
#define SQTT_MAX_NUM_SE 32
|
||||
#define SQTT_SA_PER_SE 2
|
||||
#define SQTT_ACTIVE_PIXEL_PACKER_MASK_DWORDS 4
|
||||
|
||||
struct sqtt_data_info {
|
||||
uint32_t cur_offset;
|
||||
uint32_t trace_status;
|
||||
union {
|
||||
uint32_t gfx9_write_counter;
|
||||
uint32_t gfx10_dropped_cntr;
|
||||
};
|
||||
};
|
||||
|
||||
struct sqtt_data_se {
|
||||
struct sqtt_data_info info;
|
||||
void *data_ptr;
|
||||
uint32_t shader_engine;
|
||||
uint32_t compute_unit;
|
||||
};
|
||||
|
||||
|
||||
enum sqtt_version
|
||||
{
|
||||
SQTT_VERSION_NONE = 0x0,
|
||||
SQTT_VERSION_2_2 = 0x5, /* GFX8 */
|
||||
SQTT_VERSION_2_3 = 0x6, /* GFX9 */
|
||||
SQTT_VERSION_2_4 = 0x7, /* GFX10+ */
|
||||
SQTT_VERSION_3_2 = 0xb, /* GFX11+ */
|
||||
SQTT_VERSION_3_3 = 0xc, /* GFX12+ */
|
||||
};
|
||||
|
||||
enum sqtt_file_chunk_type
|
||||
{
|
||||
SQTT_FILE_CHUNK_TYPE_ASIC_INFO,
|
||||
SQTT_FILE_CHUNK_TYPE_SQTT_DESC,
|
||||
SQTT_FILE_CHUNK_TYPE_SQTT_DATA,
|
||||
SQTT_FILE_CHUNK_TYPE_API_INFO,
|
||||
SQTT_FILE_CHUNK_TYPE_RESERVED,
|
||||
SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS,
|
||||
SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION,
|
||||
SQTT_FILE_CHUNK_TYPE_CPU_INFO,
|
||||
SQTT_FILE_CHUNK_TYPE_SPM_DB,
|
||||
SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE,
|
||||
SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS,
|
||||
SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION,
|
||||
SQTT_FILE_CHUNK_TYPE_INSTRUMENTATION_TABLE,
|
||||
SQTT_FILE_CHUNK_TYPE_COUNT
|
||||
};
|
||||
|
||||
|
||||
struct sqtt_file_chunk_id {
|
||||
int32_t type : 8;
|
||||
int32_t index : 8;
|
||||
int32_t reserved : 16;
|
||||
};
|
||||
|
||||
struct sqtt_file_chunk_header {
|
||||
struct sqtt_file_chunk_id chunk_id;
|
||||
uint16_t minor_version;
|
||||
uint16_t major_version;
|
||||
int32_t size_in_bytes;
|
||||
int32_t padding;
|
||||
};
|
||||
|
||||
struct sqtt_file_header_flags {
|
||||
union {
|
||||
struct {
|
||||
uint32_t is_semaphore_queue_timing_etw : 1;
|
||||
uint32_t no_queue_semaphore_timestamps : 1;
|
||||
uint32_t reserved : 30;
|
||||
};
|
||||
|
||||
uint32_t value;
|
||||
};
|
||||
};
|
||||
|
||||
struct sqtt_file_header {
|
||||
uint32_t magic_number;
|
||||
uint32_t version_major;
|
||||
uint32_t version_minor;
|
||||
struct sqtt_file_header_flags flags;
|
||||
int32_t chunk_offset;
|
||||
int32_t second;
|
||||
int32_t minute;
|
||||
int32_t hour;
|
||||
int32_t day_in_month;
|
||||
int32_t month;
|
||||
int32_t year;
|
||||
int32_t day_in_week;
|
||||
int32_t day_in_year;
|
||||
int32_t is_daylight_savings;
|
||||
};
|
||||
|
||||
struct sqtt_file_chunk_cpu_info {
|
||||
struct sqtt_file_chunk_header header;
|
||||
uint32_t vendor_id[4];
|
||||
uint32_t processor_brand[12];
|
||||
uint32_t reserved[2];
|
||||
uint64_t cpu_timestamp_freq;
|
||||
uint32_t clock_speed;
|
||||
uint32_t num_logical_cores;
|
||||
uint32_t num_physical_cores;
|
||||
uint32_t system_ram_size;
|
||||
};
|
||||
|
||||
enum sqtt_file_chunk_asic_info_flags
|
||||
{
|
||||
SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING = (1 << 0),
|
||||
SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED = (1 << 1)
|
||||
};
|
||||
|
||||
enum sqtt_gpu_type
|
||||
{
|
||||
SQTT_GPU_TYPE_UNKNOWN = 0x0,
|
||||
SQTT_GPU_TYPE_INTEGRATED = 0x1,
|
||||
SQTT_GPU_TYPE_DISCRETE = 0x2,
|
||||
SQTT_GPU_TYPE_VIRTUAL = 0x3
|
||||
};
|
||||
|
||||
enum sqtt_gfxip_level
|
||||
{
|
||||
SQTT_GFXIP_LEVEL_NONE = 0x0,
|
||||
SQTT_GFXIP_LEVEL_GFXIP_6 = 0x1,
|
||||
SQTT_GFXIP_LEVEL_GFXIP_7 = 0x2,
|
||||
SQTT_GFXIP_LEVEL_GFXIP_8 = 0x3,
|
||||
SQTT_GFXIP_LEVEL_GFXIP_8_1 = 0x4,
|
||||
SQTT_GFXIP_LEVEL_GFXIP_9 = 0x5,
|
||||
SQTT_GFXIP_LEVEL_GFXIP_10_1 = 0x7,
|
||||
SQTT_GFXIP_LEVEL_GFXIP_10_3 = 0x9,
|
||||
SQTT_GFXIP_LEVEL_GFXIP_11_0 = 0xc,
|
||||
SQTT_GFXIP_LEVEL_GFXIP_11_5 = 0xd,
|
||||
SQTT_GFXIP_LEVEL_GFXIP_12 = 0x10,
|
||||
};
|
||||
|
||||
enum sqtt_memory_type
|
||||
{
|
||||
SQTT_MEMORY_TYPE_UNKNOWN = 0x0,
|
||||
SQTT_MEMORY_TYPE_DDR = 0x1,
|
||||
SQTT_MEMORY_TYPE_DDR2 = 0x2,
|
||||
SQTT_MEMORY_TYPE_DDR3 = 0x3,
|
||||
SQTT_MEMORY_TYPE_DDR4 = 0x4,
|
||||
SQTT_MEMORY_TYPE_DDR5 = 0x5,
|
||||
SQTT_MEMORY_TYPE_GDDR3 = 0x10,
|
||||
SQTT_MEMORY_TYPE_GDDR4 = 0x11,
|
||||
SQTT_MEMORY_TYPE_GDDR5 = 0x12,
|
||||
SQTT_MEMORY_TYPE_GDDR6 = 0x13,
|
||||
SQTT_MEMORY_TYPE_HBM = 0x20,
|
||||
SQTT_MEMORY_TYPE_HBM2 = 0x21,
|
||||
SQTT_MEMORY_TYPE_HBM3 = 0x22,
|
||||
SQTT_MEMORY_TYPE_LPDDR4 = 0x30,
|
||||
SQTT_MEMORY_TYPE_LPDDR5 = 0x31,
|
||||
};
|
||||
|
||||
struct sqtt_file_chunk_asic_info {
|
||||
struct sqtt_file_chunk_header header;
|
||||
uint64_t flags;
|
||||
uint64_t trace_shader_core_clock;
|
||||
uint64_t trace_memory_clock;
|
||||
int32_t device_id;
|
||||
int32_t device_revision_id;
|
||||
int32_t vgprs_per_simd;
|
||||
int32_t sgprs_per_simd;
|
||||
int32_t shader_engines;
|
||||
int32_t compute_unit_per_shader_engine;
|
||||
int32_t simd_per_compute_unit;
|
||||
int32_t wavefronts_per_simd;
|
||||
int32_t minimum_vgpr_alloc;
|
||||
int32_t vgpr_alloc_granularity;
|
||||
int32_t minimum_sgpr_alloc;
|
||||
int32_t sgpr_alloc_granularity;
|
||||
int32_t hardware_contexts;
|
||||
enum sqtt_gpu_type gpu_type;
|
||||
enum sqtt_gfxip_level gfxip_level;
|
||||
int32_t gpu_index;
|
||||
int32_t gds_size;
|
||||
int32_t gds_per_shader_engine;
|
||||
int32_t ce_ram_size;
|
||||
int32_t ce_ram_size_graphics;
|
||||
int32_t ce_ram_size_compute;
|
||||
int32_t max_number_of_dedicated_cus;
|
||||
int64_t vram_size;
|
||||
int32_t vram_bus_width;
|
||||
int32_t l2_cache_size;
|
||||
int32_t l1_cache_size;
|
||||
int32_t lds_size;
|
||||
char gpu_name[SQTT_GPU_NAME_MAX_SIZE];
|
||||
float alu_per_clock;
|
||||
float texture_per_clock;
|
||||
float prims_per_clock;
|
||||
float pixels_per_clock;
|
||||
uint64_t gpu_timestamp_frequency;
|
||||
uint64_t max_shader_core_clock;
|
||||
uint64_t max_memory_clock;
|
||||
uint32_t memory_ops_per_clock;
|
||||
enum sqtt_memory_type memory_chip_type;
|
||||
uint32_t lds_granularity;
|
||||
uint16_t cu_mask[SQTT_MAX_NUM_SE][SQTT_SA_PER_SE];
|
||||
char reserved1[128];
|
||||
uint32_t active_pixel_packer_mask[SQTT_ACTIVE_PIXEL_PACKER_MASK_DWORDS];
|
||||
char reserved2[16];
|
||||
uint32_t gl1_cache_size;
|
||||
uint32_t instruction_cache_size;
|
||||
uint32_t scalar_cache_size;
|
||||
uint32_t mall_cache_size;
|
||||
char padding[4];
|
||||
};
|
||||
|
||||
enum sqtt_api_type
|
||||
{
|
||||
SQTT_API_TYPE_DIRECTX_12,
|
||||
SQTT_API_TYPE_VULKAN,
|
||||
SQTT_API_TYPE_GENERIC,
|
||||
SQTT_API_TYPE_OPENCL
|
||||
};
|
||||
|
||||
enum sqtt_instruction_trace_mode
|
||||
{
|
||||
SQTT_INSTRUCTION_TRACE_DISABLED = 0x0,
|
||||
SQTT_INSTRUCTION_TRACE_FULL_FRAME = 0x1,
|
||||
SQTT_INSTRUCTION_TRACE_API_PSO = 0x2,
|
||||
};
|
||||
|
||||
enum sqtt_profiling_mode
|
||||
{
|
||||
SQTT_PROFILING_MODE_PRESENT = 0x0,
|
||||
SQTT_PROFILING_MODE_USER_MARKERS = 0x1,
|
||||
SQTT_PROFILING_MODE_INDEX = 0x2,
|
||||
SQTT_PROFILING_MODE_TAG = 0x3,
|
||||
};
|
||||
|
||||
union sqtt_profiling_mode_data {
|
||||
struct {
|
||||
char start[256];
|
||||
char end[256];
|
||||
} user_marker_profiling_data;
|
||||
|
||||
struct {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
} index_profiling_data;
|
||||
|
||||
struct {
|
||||
uint32_t begin_hi;
|
||||
uint32_t begin_lo;
|
||||
uint32_t end_hi;
|
||||
uint32_t end_lo;
|
||||
} tag_profiling_data;
|
||||
};
|
||||
|
||||
union sqtt_instruction_trace_data {
|
||||
struct {
|
||||
uint64_t api_pso_filter;
|
||||
} api_pso_data;
|
||||
|
||||
struct {
|
||||
uint32_t mask;
|
||||
} shader_engine_filter;
|
||||
};
|
||||
|
||||
struct sqtt_file_chunk_api_info {
|
||||
struct sqtt_file_chunk_header header;
|
||||
enum sqtt_api_type api_type;
|
||||
uint16_t major_version;
|
||||
uint16_t minor_version;
|
||||
enum sqtt_profiling_mode profiling_mode;
|
||||
uint32_t reserved;
|
||||
union sqtt_profiling_mode_data profiling_mode_data;
|
||||
enum sqtt_instruction_trace_mode instruction_trace_mode;
|
||||
uint32_t reserved2;
|
||||
union sqtt_instruction_trace_data instruction_trace_data;
|
||||
};
|
||||
|
||||
|
||||
struct sqtt_code_object_database_record {
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
struct sqtt_file_chunk_code_object_database {
|
||||
struct sqtt_file_chunk_header header;
|
||||
uint32_t offset;
|
||||
uint32_t flags;
|
||||
uint32_t size;
|
||||
uint32_t record_count;
|
||||
};
|
||||
|
||||
|
||||
struct sqtt_code_object_loader_events_record {
|
||||
uint32_t loader_event_type;
|
||||
uint32_t reserved;
|
||||
uint64_t base_address;
|
||||
uint64_t code_object_hash[2];
|
||||
uint64_t time_stamp;
|
||||
};
|
||||
|
||||
struct sqtt_file_chunk_code_object_loader_events {
|
||||
struct sqtt_file_chunk_header header;
|
||||
uint32_t offset;
|
||||
uint32_t flags;
|
||||
uint32_t record_size;
|
||||
uint32_t record_count;
|
||||
};
|
||||
|
||||
struct sqtt_pso_correlation_record {
|
||||
uint64_t api_pso_hash;
|
||||
uint64_t pipeline_hash[2];
|
||||
char api_level_obj_name[64];
|
||||
};
|
||||
|
||||
struct sqtt_file_chunk_pso_correlation {
|
||||
struct sqtt_file_chunk_header header;
|
||||
uint32_t offset;
|
||||
uint32_t flags;
|
||||
uint32_t record_size;
|
||||
uint32_t record_count;
|
||||
};
|
||||
|
||||
struct sqtt_file_chunk_sqtt_desc {
|
||||
struct sqtt_file_chunk_header header;
|
||||
int32_t shader_engine_index;
|
||||
enum sqtt_version sqtt_version;
|
||||
union {
|
||||
struct {
|
||||
int32_t instrumentation_version;
|
||||
} v0;
|
||||
struct {
|
||||
int16_t instrumentation_spec_version;
|
||||
int16_t instrumentation_api_version;
|
||||
int32_t compute_unit_index;
|
||||
} v1;
|
||||
};
|
||||
};
|
||||
|
||||
struct sqtt_file_chunk_sqtt_data {
|
||||
struct sqtt_file_chunk_header header;
|
||||
int32_t offset; /* in bytes */
|
||||
int32_t size; /* in bytes */
|
||||
};
|
||||
|
||||
struct sqtt_file_chunk_queue_event_timings {
|
||||
struct sqtt_file_chunk_header header;
|
||||
uint32_t queue_info_table_record_count;
|
||||
uint32_t queue_info_table_size;
|
||||
uint32_t queue_event_table_record_count;
|
||||
uint32_t queue_event_table_size;
|
||||
};
|
||||
|
||||
|
||||
enum sqtt_queue_type {
|
||||
SQTT_QUEUE_TYPE_UNKNOWN = 0x0,
|
||||
SQTT_QUEUE_TYPE_UNIVERSAL = 0x1,
|
||||
SQTT_QUEUE_TYPE_COMPUTE = 0x2,
|
||||
SQTT_QUEUE_TYPE_DMA = 0x3,
|
||||
};
|
||||
|
||||
enum sqtt_engine_type {
|
||||
SQTT_ENGINE_TYPE_UNKNOWN = 0x0,
|
||||
SQTT_ENGINE_TYPE_UNIVERSAL = 0x1,
|
||||
SQTT_ENGINE_TYPE_COMPUTE = 0x2,
|
||||
SQTT_ENGINE_TYPE_EXCLUSIVE_COMPUTE = 0x3,
|
||||
SQTT_ENGINE_TYPE_DMA = 0x4,
|
||||
SQTT_ENGINE_TYPE_HIGH_PRIORITY_UNIVERSAL = 0x7,
|
||||
SQTT_ENGINE_TYPE_HIGH_PRIORITY_GRAPHICS = 0x8,
|
||||
};
|
||||
|
||||
struct sqtt_queue_hardware_info {
|
||||
union {
|
||||
struct {
|
||||
int32_t queue_type : 8;
|
||||
int32_t engine_type : 8;
|
||||
uint32_t reserved : 16;
|
||||
};
|
||||
uint32_t value;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct sqtt_queue_info_record {
|
||||
uint64_t queue_id;
|
||||
uint64_t queue_context;
|
||||
struct sqtt_queue_hardware_info hardware_info;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
enum sqtt_queue_event_type {
|
||||
SQTT_QUEUE_TIMING_EVENT_CMDBUF_SUBMIT,
|
||||
SQTT_QUEUE_TIMING_EVENT_SIGNAL_SEMAPHORE,
|
||||
SQTT_QUEUE_TIMING_EVENT_WAIT_SEMAPHORE,
|
||||
SQTT_QUEUE_TIMING_EVENT_PRESENT
|
||||
};
|
||||
|
||||
struct sqtt_queue_event_record {
|
||||
enum sqtt_queue_event_type event_type;
|
||||
uint32_t sqtt_cb_id;
|
||||
uint64_t frame_index;
|
||||
uint32_t queue_info_index;
|
||||
uint32_t submit_sub_index;
|
||||
uint64_t api_id;
|
||||
uint64_t cpu_timestamp;
|
||||
uint64_t gpu_timestamps[2];
|
||||
};
|
||||
|
||||
struct sqtt_file_chunk_clock_calibration {
|
||||
struct sqtt_file_chunk_header header;
|
||||
uint64_t cpu_timestamp;
|
||||
uint64_t gpu_timestamp;
|
||||
uint64_t reserved;
|
||||
};
|
||||
|
||||
enum elf_gfxip_level
|
||||
{
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX1100 = 0x041,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX1150 = 0x043,
|
||||
EF_AMDGPU_MACH_AMDGCN_GFX1200 = 0x04e,
|
||||
};
|
||||
|
||||
struct sqtt_file_chunk_spm_db {
|
||||
struct sqtt_file_chunk_header header;
|
||||
uint32_t flags;
|
||||
uint32_t preamble_size;
|
||||
uint32_t num_timestamps;
|
||||
uint32_t num_spm_counter_info;
|
||||
uint32_t spm_counter_info_size;
|
||||
uint32_t sample_interval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Identifiers for RGP SQ thread-tracing markers (Table 1)
|
||||
*/
|
||||
enum rgp_sqtt_marker_identifier
|
||||
{
|
||||
RGP_SQTT_MARKER_IDENTIFIER_EVENT = 0x0,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_CB_START = 0x1,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_CB_END = 0x2,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_BARRIER_START = 0x3,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_BARRIER_END = 0x4,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_USER_EVENT = 0x5,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_GENERAL_API = 0x6,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_SYNC = 0x7,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_PRESENT = 0x8,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_LAYOUT_TRANSITION = 0x9,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_RENDER_PASS = 0xA,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_RESERVED2 = 0xB,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_BIND_PIPELINE = 0xC,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_RESERVED4 = 0xD,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_RESERVED5 = 0xE,
|
||||
RGP_SQTT_MARKER_IDENTIFIER_RESERVED6 = 0xF
|
||||
};
|
||||
|
||||
/**
|
||||
* Command buffer IDs used in RGP SQ thread-tracing markers (only 20 bits).
|
||||
*/
|
||||
union rgp_sqtt_marker_cb_id {
|
||||
struct {
|
||||
uint32_t per_frame : 1; /* Must be 1, frame-based command buffer ID. */
|
||||
uint32_t frame_index : 7;
|
||||
uint32_t cb_index : 12; /* Command buffer index within the frame. */
|
||||
uint32_t reserved : 12;
|
||||
} per_frame_cb_id;
|
||||
|
||||
struct {
|
||||
uint32_t per_frame : 1; /* Must be 0, global command buffer ID. */
|
||||
uint32_t cb_index : 19; /* Global command buffer index. */
|
||||
uint32_t reserved : 12;
|
||||
} global_cb_id;
|
||||
|
||||
uint32_t all;
|
||||
};
|
||||
|
||||
/**
|
||||
* RGP SQ thread-tracing marker for the start of a command buffer. (Table 2)
|
||||
*/
|
||||
struct rgp_sqtt_marker_cb_start {
|
||||
union {
|
||||
struct {
|
||||
uint32_t identifier : 4;
|
||||
uint32_t ext_dwords : 3;
|
||||
uint32_t cb_id : 20;
|
||||
uint32_t queue : 5;
|
||||
};
|
||||
uint32_t dword01;
|
||||
};
|
||||
union {
|
||||
uint32_t device_id_low;
|
||||
uint32_t dword02;
|
||||
};
|
||||
union {
|
||||
uint32_t device_id_high;
|
||||
uint32_t dword03;
|
||||
};
|
||||
union {
|
||||
uint32_t queue_flags;
|
||||
uint32_t dword04;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* RGP SQ thread-tracing marker for the end of a command buffer. (Table 3)
|
||||
*/
|
||||
struct rgp_sqtt_marker_cb_end {
|
||||
union {
|
||||
struct {
|
||||
uint32_t identifier : 4;
|
||||
uint32_t ext_dwords : 3;
|
||||
uint32_t cb_id : 20;
|
||||
uint32_t reserved : 5;
|
||||
};
|
||||
uint32_t dword01;
|
||||
};
|
||||
union {
|
||||
uint32_t device_id_low;
|
||||
uint32_t dword02;
|
||||
};
|
||||
union {
|
||||
uint32_t device_id_high;
|
||||
uint32_t dword03;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* API types used in RGP SQ thread-tracing markers for the "General API"
|
||||
* packet.
|
||||
*/
|
||||
enum rgp_sqtt_marker_general_api_type
|
||||
{
|
||||
ApiCmdBindPipeline = 0,
|
||||
ApiCmdBindDescriptorSets = 1,
|
||||
ApiCmdBindIndexBuffer = 2,
|
||||
ApiCmdBindVertexBuffers = 3,
|
||||
ApiCmdDraw = 4,
|
||||
ApiCmdDrawIndexed = 5,
|
||||
ApiCmdDrawIndirect = 6,
|
||||
ApiCmdDrawIndexedIndirect = 7,
|
||||
ApiCmdDrawIndirectCountAMD = 8,
|
||||
ApiCmdDrawIndexedIndirectCountAMD = 9,
|
||||
ApiCmdDispatch = 10,
|
||||
ApiCmdDispatchIndirect = 11,
|
||||
ApiCmdCopyBuffer = 12,
|
||||
ApiCmdCopyImage = 13,
|
||||
ApiCmdBlitImage = 14,
|
||||
ApiCmdCopyBufferToImage = 15,
|
||||
ApiCmdCopyImageToBuffer = 16,
|
||||
ApiCmdUpdateBuffer = 17,
|
||||
ApiCmdFillBuffer = 18,
|
||||
ApiCmdClearColorImage = 19,
|
||||
ApiCmdClearDepthStencilImage = 20,
|
||||
ApiCmdClearAttachments = 21,
|
||||
ApiCmdResolveImage = 22,
|
||||
ApiCmdWaitEvents = 23,
|
||||
ApiCmdPipelineBarrier = 24,
|
||||
ApiCmdBeginQuery = 25,
|
||||
ApiCmdEndQuery = 26,
|
||||
ApiCmdResetQueryPool = 27,
|
||||
ApiCmdWriteTimestamp = 28,
|
||||
ApiCmdCopyQueryPoolResults = 29,
|
||||
ApiCmdPushConstants = 30,
|
||||
ApiCmdBeginRenderPass = 31,
|
||||
ApiCmdNextSubpass = 32,
|
||||
ApiCmdEndRenderPass = 33,
|
||||
ApiCmdExecuteCommands = 34,
|
||||
ApiCmdSetViewport = 35,
|
||||
ApiCmdSetScissor = 36,
|
||||
ApiCmdSetLineWidth = 37,
|
||||
ApiCmdSetDepthBias = 38,
|
||||
ApiCmdSetBlendConstants = 39,
|
||||
ApiCmdSetDepthBounds = 40,
|
||||
ApiCmdSetStencilCompareMask = 41,
|
||||
ApiCmdSetStencilWriteMask = 42,
|
||||
ApiCmdSetStencilReference = 43,
|
||||
ApiCmdDrawIndirectCount = 44,
|
||||
ApiCmdDrawIndexedIndirectCount = 45,
|
||||
/* gap */
|
||||
ApiCmdDrawMeshTasksEXT = 47,
|
||||
ApiCmdDrawMeshTasksIndirectCountEXT = 48,
|
||||
ApiCmdDrawMeshTasksIndirectEXT = 49,
|
||||
|
||||
ApiRayTracingSeparateCompiled = 0x800000,
|
||||
ApiInvalid = 0xffffffff
|
||||
};
|
||||
|
||||
/**
|
||||
* RGP SQ thread-tracing marker for a "General API" instrumentation packet.
|
||||
*/
|
||||
struct rgp_sqtt_marker_general_api {
|
||||
union {
|
||||
struct {
|
||||
uint32_t identifier : 4;
|
||||
uint32_t ext_dwords : 3;
|
||||
uint32_t api_type : 20;
|
||||
uint32_t is_end : 1;
|
||||
uint32_t reserved : 4;
|
||||
};
|
||||
uint32_t dword01;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* API types used in RGP SQ thread-tracing markers (Table 16).
|
||||
*/
|
||||
enum rgp_sqtt_marker_event_type
|
||||
{
|
||||
EventCmdDraw = 0,
|
||||
EventCmdDrawIndexed = 1,
|
||||
EventCmdDrawIndirect = 2,
|
||||
EventCmdDrawIndexedIndirect = 3,
|
||||
EventCmdDrawIndirectCountAMD = 4,
|
||||
EventCmdDrawIndexedIndirectCountAMD = 5,
|
||||
EventCmdDispatch = 6,
|
||||
EventCmdDispatchIndirect = 7,
|
||||
EventCmdCopyBuffer = 8,
|
||||
EventCmdCopyImage = 9,
|
||||
EventCmdBlitImage = 10,
|
||||
EventCmdCopyBufferToImage = 11,
|
||||
EventCmdCopyImageToBuffer = 12,
|
||||
EventCmdUpdateBuffer = 13,
|
||||
EventCmdFillBuffer = 14,
|
||||
EventCmdClearColorImage = 15,
|
||||
EventCmdClearDepthStencilImage = 16,
|
||||
EventCmdClearAttachments = 17,
|
||||
EventCmdResolveImage = 18,
|
||||
EventCmdWaitEvents = 19,
|
||||
EventCmdPipelineBarrier = 20,
|
||||
EventCmdResetQueryPool = 21,
|
||||
EventCmdCopyQueryPoolResults = 22,
|
||||
EventRenderPassColorClear = 23,
|
||||
EventRenderPassDepthStencilClear = 24,
|
||||
EventRenderPassResolve = 25,
|
||||
EventInternalUnknown = 26,
|
||||
EventCmdDrawIndirectCount = 27,
|
||||
EventCmdDrawIndexedIndirectCount = 28,
|
||||
/* gap */
|
||||
EventCmdTraceRaysKHR = 30,
|
||||
EventCmdTraceRaysIndirectKHR = 31,
|
||||
EventCmdBuildAccelerationStructuresKHR = 32,
|
||||
EventCmdBuildAccelerationStructuresIndirectKHR = 33,
|
||||
EventCmdCopyAccelerationStructureKHR = 34,
|
||||
EventCmdCopyAccelerationStructureToMemoryKHR = 35,
|
||||
EventCmdCopyMemoryToAccelerationStructureKHR = 36,
|
||||
/* gap */
|
||||
EventCmdDrawMeshTasksEXT = 41,
|
||||
EventCmdDrawMeshTasksIndirectCountEXT = 42,
|
||||
EventCmdDrawMeshTasksIndirectEXT = 43,
|
||||
EventUnknown = 0x7fff,
|
||||
EventInvalid = 0xffffffff
|
||||
};
|
||||
|
||||
/**
|
||||
* "Event (Per-draw/dispatch)" RGP SQ thread-tracing marker. (Table 4)
|
||||
*/
|
||||
struct rgp_sqtt_marker_event {
|
||||
union {
|
||||
struct {
|
||||
uint32_t identifier : 4;
|
||||
uint32_t ext_dwords : 3;
|
||||
uint32_t api_type : 24;
|
||||
uint32_t has_thread_dims : 1;
|
||||
};
|
||||
uint32_t dword01;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint32_t cb_id : 20;
|
||||
uint32_t vertex_offset_reg_idx : 4;
|
||||
uint32_t instance_offset_reg_idx : 4;
|
||||
uint32_t draw_index_reg_idx : 4;
|
||||
};
|
||||
uint32_t dword02;
|
||||
};
|
||||
union {
|
||||
uint32_t cmd_id;
|
||||
uint32_t dword03;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Per-dispatch specific marker where workgroup dims are included.
|
||||
*/
|
||||
struct rgp_sqtt_marker_event_with_dims {
|
||||
struct rgp_sqtt_marker_event event;
|
||||
uint32_t thread_x;
|
||||
uint32_t thread_y;
|
||||
uint32_t thread_z;
|
||||
};
|
||||
|
||||
/**
|
||||
* "Barrier Start" RGP SQTT instrumentation marker (Table 5)
|
||||
*/
|
||||
struct rgp_sqtt_marker_barrier_start {
|
||||
union {
|
||||
struct {
|
||||
uint32_t identifier : 4;
|
||||
uint32_t ext_dwords : 3;
|
||||
uint32_t cb_id : 20;
|
||||
uint32_t reserved : 5;
|
||||
};
|
||||
uint32_t dword01;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint32_t driver_reason : 31;
|
||||
uint32_t internal : 1;
|
||||
};
|
||||
uint32_t dword02;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* "Barrier End" RGP SQTT instrumentation marker (Table 6)
|
||||
*/
|
||||
struct rgp_sqtt_marker_barrier_end {
|
||||
union {
|
||||
struct {
|
||||
uint32_t identifier : 4;
|
||||
uint32_t ext_dwords : 3;
|
||||
uint32_t cb_id : 20;
|
||||
uint32_t wait_on_eop_ts : 1;
|
||||
uint32_t vs_partial_flush : 1;
|
||||
uint32_t ps_partial_flush : 1;
|
||||
uint32_t cs_partial_flush : 1;
|
||||
uint32_t pfp_sync_me : 1;
|
||||
};
|
||||
uint32_t dword01;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint32_t sync_cp_dma : 1;
|
||||
uint32_t inval_tcp : 1;
|
||||
uint32_t inval_sqI : 1;
|
||||
uint32_t inval_sqK : 1;
|
||||
uint32_t flush_tcc : 1;
|
||||
uint32_t inval_tcc : 1;
|
||||
uint32_t flush_cb : 1;
|
||||
uint32_t inval_cb : 1;
|
||||
uint32_t flush_db : 1;
|
||||
uint32_t inval_db : 1;
|
||||
uint32_t num_layout_transitions : 16;
|
||||
uint32_t inval_gl1 : 1;
|
||||
uint32_t wait_on_ts : 1;
|
||||
uint32_t eop_ts_bottom_of_pipe : 1;
|
||||
uint32_t eos_ts_ps_done : 1;
|
||||
uint32_t eos_ts_cs_done : 1;
|
||||
uint32_t reserved : 1;
|
||||
};
|
||||
uint32_t dword02;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* "Layout Transition" RGP SQTT instrumentation marker (Table 7)
|
||||
*/
|
||||
struct rgp_sqtt_marker_layout_transition {
|
||||
union {
|
||||
struct {
|
||||
uint32_t identifier : 4;
|
||||
uint32_t ext_dwords : 3;
|
||||
uint32_t depth_stencil_expand : 1;
|
||||
uint32_t htile_hiz_range_expand : 1;
|
||||
uint32_t depth_stencil_resummarize : 1;
|
||||
uint32_t dcc_decompress : 1;
|
||||
uint32_t fmask_decompress : 1;
|
||||
uint32_t fast_clear_eliminate : 1;
|
||||
uint32_t fmask_color_expand : 1;
|
||||
uint32_t init_mask_ram : 1;
|
||||
uint32_t reserved1 : 17;
|
||||
};
|
||||
uint32_t dword01;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint32_t reserved2 : 32;
|
||||
};
|
||||
uint32_t dword02;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* "User Event" RGP SQTT instrumentation marker (Table 8)
|
||||
*/
|
||||
struct rgp_sqtt_marker_user_event {
|
||||
union {
|
||||
struct {
|
||||
uint32_t identifier : 4;
|
||||
uint32_t reserved0 : 8;
|
||||
uint32_t data_type : 8;
|
||||
uint32_t reserved1 : 12;
|
||||
};
|
||||
uint32_t dword01;
|
||||
};
|
||||
};
|
||||
struct rgp_sqtt_marker_user_event_with_length {
|
||||
struct rgp_sqtt_marker_user_event user_event;
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
enum rgp_sqtt_marker_user_event_type
|
||||
{
|
||||
UserEventTrigger = 0,
|
||||
UserEventPop,
|
||||
UserEventPush,
|
||||
UserEventObjectName,
|
||||
};
|
||||
|
||||
/**
|
||||
* "Pipeline bind" RGP SQTT instrumentation marker (Table 12)
|
||||
*/
|
||||
struct rgp_sqtt_marker_pipeline_bind {
|
||||
union {
|
||||
struct {
|
||||
uint32_t identifier : 4;
|
||||
uint32_t ext_dwords : 3;
|
||||
uint32_t bind_point : 1;
|
||||
uint32_t cb_id : 20;
|
||||
uint32_t reserved : 4;
|
||||
};
|
||||
uint32_t dword01;
|
||||
};
|
||||
union {
|
||||
uint32_t api_pso_hash[2];
|
||||
struct {
|
||||
uint32_t dword02;
|
||||
uint32_t dword03;
|
||||
};
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user