Cache D3D12 recording lookups without retaining game resources
This commit is contained in:
1 parent
73ee2e5ecc
commit
74aad12938
10 files changed
+268
-13
No files matched your search
@@ -53,6 +53,8 @@ command-list split/replay, submitted state publication and suffix completion.
|
|||||||
The recording interval measures NGX calls on the recording thread, not Present.
|
The recording interval measures NGX calls on the recording thread, not Present.
|
||||||
`-ProfileKernels` enables synchronizing HIP-event kernel profiling and changes
|
`-ProfileKernels` enables synchronizing HIP-event kernel profiling and changes
|
||||||
frame scheduling; use it separately from a production FPS measurement.
|
frame scheduling; use it separately from a production FPS measurement.
|
||||||
|
`-ProfileCommandHooks` samples one in 64 D3D12 interceptions to distinguish
|
||||||
|
tracking/lock waits from driver calls. It is disabled in ordinary runs.
|
||||||
The runner drains stdout/stderr concurrently as raw bytes; the earlier
|
The runner drains stdout/stderr concurrently as raw bytes; the earlier
|
||||||
line-oriented PowerShell collector imposed large per-frame delays. The optional
|
line-oriented PowerShell collector imposed large per-frame delays. The optional
|
||||||
ZLUDA kernel profiler is for diagnostics only. Measurements and reproduction
|
ZLUDA kernel profiler is for diagnostics only. Measurements and reproduction
|
||||||
|
|||||||
@@ -138,5 +138,39 @@ The installer accepts them with `-LocalTextureKernels` only after validation,
|
|||||||
checking the exact DLL identity, object and manifest hashes. M retains its
|
checking the exact DLL identity, object and manifest hashes. M retains its
|
||||||
independently validated FP16-equivalent baseline.
|
independently validated FP16-equivalent baseline.
|
||||||
|
|
||||||
|
The following no-debugger K/4K run completes 9982 frames and 9982 finite GPU
|
||||||
|
scans. Kernel event profiling is disabled; the validated private output tail
|
||||||
|
executes natively. The user reports 43-47 FPS. Mean NGX recording interval is
|
||||||
|
21.867 ms. No backend failure, CPU image copy or previous-frame output occurs.
|
||||||
|
|
||||||
|
Random one-in-64 hook samples then identify contention in the shared routing
|
||||||
|
table used by every intercepted D3D12 command. Per-thread weak lookup caches
|
||||||
|
now bypass that table on repeated calls to a list. Table mutations invalidate
|
||||||
|
cache generations; Reset/address reuse cannot route to a previous suffix, and
|
||||||
|
thread caches do not retain game resources. The per-list and submission locks
|
||||||
|
remain. A GPU regression resets and re-splits the exact same list with changed
|
||||||
|
root constants twice per iteration, checking both prefix and suffix results.
|
||||||
|
|
||||||
|
| Sampled command-hook access | Shared table | Per-thread weak cache |
|
||||||
|
| --- | ---: | ---: |
|
||||||
|
| Busiest recording thread, mean us/call | 0.203 | 0.066 |
|
||||||
|
| Estimated access + capture across threads, ms/s | 977.528 | 233.606 |
|
||||||
|
|
||||||
|
The latter estimate includes lock waits summed across concurrently running
|
||||||
|
threads, not CPU execution time or serial frame latency. The two game runs
|
||||||
|
have different thread populations (31 versus 29); there is no identical frame
|
||||||
|
trace. Generated forwarding methods have separate driver/capture markers;
|
||||||
|
special-case hooks contribute access samples but lack those body markers.
|
||||||
|
|
||||||
|
With the cache, 4770 complete K/4K frames and finite GPU scans pass, with zero
|
||||||
|
backend failures, CPU image copies or previous-frame output. Median NGX
|
||||||
|
recording interval is 19.473 ms. The user reports 49-51 FPS and 53% GPU usage
|
||||||
|
in the previously measured scene. These user readings are separate from the
|
||||||
|
sampled hook estimates and do not establish isolated WMMA utilization.
|
||||||
|
All sixteen CTest gates pass, including 64 same-object Reset/split checks in
|
||||||
|
each physical command-backend test and the software indirect-root regression.
|
||||||
|
Use `-ProfileCommandHooks -ProfileStages` to collect samples; the sampler is
|
||||||
|
disabled for ordinary play.
|
||||||
|
|
||||||
References: [HIP events](https://rocmdocs.amd.com/projects/HIP/en/develop/doxygen/html/group___event.html),
|
References: [HIP events](https://rocmdocs.amd.com/projects/HIP/en/develop/doxygen/html/group___event.html),
|
||||||
[HIP occupancy API](https://rocm.docs.amd.com/projects/HIP/en/latest/doxygen/html/group___occupancy.html).
|
[HIP occupancy API](https://rocm.docs.amd.com/projects/HIP/en/latest/doxygen/html/group___occupancy.html).
|
||||||
@@ -54,6 +54,27 @@ public ZIPs exclude these objects. Install/restore with private overrides
|
|||||||
restores sentinel DLL/config byte-exactly, without duplicate slash/backslash
|
restores sentinel DLL/config byte-exactly, without duplicate slash/backslash
|
||||||
manifest paths.
|
manifest paths.
|
||||||
|
|
||||||
|
Production K/4K with private output stores completes 9982 frames and 9982
|
||||||
|
finite GPU scans; the user reports 43-47 FPS. Random per-hook CPU sampling
|
||||||
|
then localizes contention to the shared command-list routing map. A per-thread
|
||||||
|
weak lookup cache bypasses that mutex for repeated calls, invalidating on map
|
||||||
|
mutations to preserve Reset/final Release/address reuse. Queue and per-list
|
||||||
|
synchronization remain. The regression resets/re-splits the same object twice
|
||||||
|
per iteration with different root constants and verifies both GPU outputs.
|
||||||
|
All sixteen CTest gates pass. The cached game run completes 4770 K/4K frames
|
||||||
|
and 4770 finite GPU scans, zero failures/CPU image copies/aged outputs. The user
|
||||||
|
reports 49-51 FPS and 53% GPU usage. Aggregated sampled access/capture time
|
||||||
|
falls from 977.528 to 233.606 ms/s across threads; it includes parallel lock
|
||||||
|
waits and must not be treated as serial frame time. Median recording interval
|
||||||
|
is 19.473 ms. `-ProfileCommandHooks` is optional and off during ordinary play.
|
||||||
|
Detailed scope and timings are in [windows-performance.md](windows-performance.md).
|
||||||
|
Post-cache full-pipeline checks also pass: three K/4K HDR frames and four M
|
||||||
|
512x288 frames match their previously validated controls with max absolute and
|
||||||
|
relative RGB error 0, all RGBA finite. Public archive validation checks all 63
|
||||||
|
entries and their SHA256 against package.json; NVIDIA DLLs and private texture
|
||||||
|
objects are absent. `package-windows-game.ps1 -ArchivePath <zip>` archives only
|
||||||
|
the staged manifest, including on Windows PowerShell 5.1.
|
||||||
|
|
||||||
Performance diagnostics (2026-10-01): the separate ZLUDA `b0161a4` runtime
|
Performance diagnostics (2026-10-01): the separate ZLUDA `b0161a4` runtime
|
||||||
passes 32 PTX launches in each context and all four native K/M frames with
|
passes 32 PTX launches in each context and all four native K/M frames with
|
||||||
bit-exact RGB against their controls. All thirteen exported patches (0002
|
bit-exact RGB against their controls. All thirteen exported patches (0002
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[string]$PackageRoot, [string]$DiagnosticRoot, [string]$OptiScalerRoot,
|
[string]$PackageRoot, [string]$DiagnosticRoot, [string]$OptiScalerRoot,
|
||||||
[string]$ZludaRoot, [string]$HipRoot, [string]$KernelKRoot, [string]$KernelMRoot
|
[string]$ZludaRoot, [string]$HipRoot, [string]$KernelKRoot, [string]$KernelMRoot,
|
||||||
|
[string]$ArchivePath
|
||||||
)
|
)
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
||||||
@@ -76,3 +77,21 @@ if (Get-ChildItem -LiteralPath $PackageRoot -Recurse -File | Where-Object { $_.N
|
|||||||
throw 'Proprietary NVIDIA binaries must not be in the package.'
|
throw 'Proprietary NVIDIA binaries must not be in the package.'
|
||||||
}
|
}
|
||||||
Write-Host "Windows game development package: $PackageRoot (NVIDIA DLLs excluded)"
|
Write-Host "Windows game development package: $PackageRoot (NVIDIA DLLs excluded)"
|
||||||
|
if ($ArchivePath) {
|
||||||
|
$ArchivePath=[IO.Path]::GetFullPath($ArchivePath)
|
||||||
|
if ($ArchivePath.StartsWith($PackageRoot+'\',[StringComparison]::OrdinalIgnoreCase)) { throw 'Place the ZIP outside the package directory.' }
|
||||||
|
Add-Type -AssemblyName System.IO.Compression,System.IO.Compression.FileSystem
|
||||||
|
New-Item -ItemType Directory -Force (Split-Path $ArchivePath) | Out-Null
|
||||||
|
$stream=[IO.File]::Open($ArchivePath,[IO.FileMode]::Create,[IO.FileAccess]::ReadWrite,[IO.FileShare]::None)
|
||||||
|
$archive=$null
|
||||||
|
try {
|
||||||
|
$archive=[IO.Compression.ZipArchive]::new($stream,[IO.Compression.ZipArchiveMode]::Create)
|
||||||
|
# Never archive caches, results, private texture outputs or a local DLL
|
||||||
|
# merely because it happens to be somewhere under PackageRoot.
|
||||||
|
foreach ($relative in @($stagedFiles)+@('package.json')) {
|
||||||
|
[void][IO.Compression.ZipFileExtensions]::CreateEntryFromFile($archive,
|
||||||
|
(Join-Path $PackageRoot $relative),$relative.Replace('\','/'),[IO.Compression.CompressionLevel]::Optimal)
|
||||||
|
}
|
||||||
|
} finally { if ($archive) { $archive.Dispose() }; $stream.Dispose() }
|
||||||
|
Write-Host "Public package archive: $ArchivePath"
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ param(
|
|||||||
[switch]$ValidateOutput,
|
[switch]$ValidateOutput,
|
||||||
[switch]$ProfileStages,
|
[switch]$ProfileStages,
|
||||||
[switch]$ProfileKernels,
|
[switch]$ProfileKernels,
|
||||||
|
[switch]$ProfileCommandHooks,
|
||||||
[switch]$VerboseRuntime,
|
[switch]$VerboseRuntime,
|
||||||
[switch]$CaptureExceptions,
|
[switch]$CaptureExceptions,
|
||||||
[string[]]$GameArguments = @('-dx12'),
|
[string[]]$GameArguments = @('-dx12'),
|
||||||
@@ -176,6 +177,7 @@ $settings = @{
|
|||||||
D4R_VALIDATE_OUTPUT=$(if ($ValidateOutput) { '1' } else { $null });
|
D4R_VALIDATE_OUTPUT=$(if ($ValidateOutput) { '1' } else { $null });
|
||||||
D4R_PROFILE_STAGES=$(if ($ProfileStages) { '1' } else { $null });
|
D4R_PROFILE_STAGES=$(if ($ProfileStages) { '1' } else { $null });
|
||||||
D4R_ZLUDA_PROFILE=$(if ($ProfileKernels) { '1' } else { $null });
|
D4R_ZLUDA_PROFILE=$(if ($ProfileKernels) { '1' } else { $null });
|
||||||
|
D4R_PROFILE_COMMAND_HOOKS=$(if ($ProfileCommandHooks) { '1' } else { $null });
|
||||||
D4R_DIAG_DIR=$OutputDirectory; ZLUDA_LOG_DIR=(Join-Path $OutputDirectory 'zluda-trace');
|
D4R_DIAG_DIR=$OutputDirectory; ZLUDA_LOG_DIR=(Join-Path $OutputDirectory 'zluda-trace');
|
||||||
ZLUDA_CACHE_DIR=$CacheDirectory; PATH=((GamePath 'd4r/hip/bin') + ';' + (GamePath 'd4r/zluda') + ';' + $env:PATH)
|
ZLUDA_CACHE_DIR=$CacheDirectory; PATH=((GamePath 'd4r/hip/bin') + ';' + (GamePath 'd4r/zluda') + ';' + $env:PATH)
|
||||||
}
|
}
|
||||||
@@ -258,7 +260,7 @@ try {
|
|||||||
outputGpuChecks=$checks.Count; nonfiniteOutputs=$nonfinite; kernels=$kernels;
|
outputGpuChecks=$checks.Count; nonfiniteOutputs=$nonfinite; kernels=$kernels;
|
||||||
previousFrameOutputs=@($frames | Where-Object { $_.Groups[2].Value -ne '0' }).Count;
|
previousFrameOutputs=@($frames | Where-Object { $_.Groups[2].Value -ne '0' }).Count;
|
||||||
cpuImageCopyFrames=@($frames | Where-Object { $_.Groups[1].Value -ne '0' }).Count;
|
cpuImageCopyFrames=@($frames | Where-Object { $_.Groups[1].Value -ne '0' }).Count;
|
||||||
failures=([regex]::Matches($stderr, 'D4R_WINDOWS_FAILURE|D4R_COMMAND_FAILURE')).Count} |
|
failures=([regex]::Matches($stderr, 'D4R_[A-Z0-9_]*FAILURE\b')).Count} |
|
||||||
ConvertTo-Json -Depth 6 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
|
ConvertTo-Json -Depth 6 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
|
||||||
Compress-Archive -LiteralPath $OutputDirectory -DestinationPath ($OutputDirectory + '.zip') -Force
|
Compress-Archive -LiteralPath $OutputDirectory -DestinationPath ($OutputDirectory + '.zip') -Force
|
||||||
Write-Host "Game diagnostic bundle: $OutputDirectory.zip"
|
Write-Host "Game diagnostic bundle: $OutputDirectory.zip"
|
||||||
|
|||||||
@@ -60,28 +60,93 @@ struct Recording {
|
|||||||
explicit Recording(ID3D12GraphicsCommandList* list) : original(list) {}
|
explicit Recording(ID3D12GraphicsCommandList* list) : original(list) {}
|
||||||
};
|
};
|
||||||
std::unordered_map<ID3D12GraphicsCommandList*, std::shared_ptr<Recording>> recordings;
|
std::unordered_map<ID3D12GraphicsCommandList*, std::shared_ptr<Recording>> recordings;
|
||||||
|
std::atomic<uint64_t> recording_generation{0};
|
||||||
|
struct RecordingCache {
|
||||||
|
ID3D12GraphicsCommandList* list = nullptr;
|
||||||
|
uint64_t generation = 0;
|
||||||
|
// A thread's last lookup must not retain suffix lists, allocators or game
|
||||||
|
// resources after Reset/final Release. Address reuse also needs a new
|
||||||
|
// generation, even if the old Recording is alive in a submit callback.
|
||||||
|
std::weak_ptr<Recording> value;
|
||||||
|
};
|
||||||
|
thread_local RecordingCache recording_cache;
|
||||||
std::shared_ptr<Recording> get_recording(ID3D12GraphicsCommandList* self, bool create = true) {
|
std::shared_ptr<Recording> get_recording(ID3D12GraphicsCommandList* self, bool create = true) {
|
||||||
if (internal) return {};
|
if (internal) return {};
|
||||||
|
const auto generation = recording_generation.load(std::memory_order_acquire);
|
||||||
|
if (recording_cache.list == self && recording_cache.generation == generation) {
|
||||||
|
if (auto value = recording_cache.value.lock()) return value;
|
||||||
|
}
|
||||||
std::lock_guard<std::mutex> lock(map_mutex);
|
std::lock_guard<std::mutex> lock(map_mutex);
|
||||||
auto found = recordings.find(self);
|
auto found = recordings.find(self);
|
||||||
if (found != recordings.end()) return found->second;
|
std::shared_ptr<Recording> value;
|
||||||
if (!create) return {};
|
if (found != recordings.end()) value = found->second;
|
||||||
auto value = std::make_shared<Recording>(self);
|
else {
|
||||||
recordings.emplace(self, value); return value;
|
if (!create) return {};
|
||||||
|
value = std::make_shared<Recording>(self);
|
||||||
|
recordings.emplace(self, value);
|
||||||
|
recording_generation.fetch_add(1, std::memory_order_release);
|
||||||
|
}
|
||||||
|
recording_cache.list = self;
|
||||||
|
recording_cache.value = value;
|
||||||
|
recording_cache.generation = recording_generation.load(std::memory_order_relaxed);
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
void forget(ID3D12GraphicsCommandList* self) {
|
void forget(ID3D12GraphicsCommandList* self) {
|
||||||
std::shared_ptr<Recording> released;
|
std::shared_ptr<Recording> released;
|
||||||
{ std::lock_guard<std::mutex> lock(map_mutex);
|
{ std::lock_guard<std::mutex> lock(map_mutex);
|
||||||
auto it = recordings.find(self);
|
auto it = recordings.find(self);
|
||||||
if (it != recordings.end()) { released = std::move(it->second); recordings.erase(it); } }
|
if (it != recordings.end()) {
|
||||||
|
released = std::move(it->second); recordings.erase(it);
|
||||||
|
recording_generation.fetch_add(1, std::memory_order_release);
|
||||||
|
} }
|
||||||
// Release retained COM objects without holding the map mutex.
|
// Release retained COM objects without holding the map mutex.
|
||||||
}
|
}
|
||||||
|
struct HookSample {
|
||||||
|
uint32_t random = GetCurrentThreadId() | 1u;
|
||||||
|
uint64_t calls = 0, samples = 0, marked = 0;
|
||||||
|
double access_ms = 0, capture_ms = 0, driver_ms = 0;
|
||||||
|
Clock::time_point since = Clock::now();
|
||||||
|
bool choose() {
|
||||||
|
++calls; random ^= random << 13; random ^= random >> 17; random ^= random << 5;
|
||||||
|
return !(random & 63u);
|
||||||
|
}
|
||||||
|
void flush() {
|
||||||
|
const double elapsed = milliseconds(since);
|
||||||
|
if (elapsed < 2000) return;
|
||||||
|
std::printf("D4R_COMMAND_HOOK_SAMPLE thread=%lu period_ms=%.3f calls=%llu samples=%llu marked=%llu access_sum_ms=%.6f capture_sum_ms=%.6f driver_sum_ms=%.6f sampling=64\n",
|
||||||
|
GetCurrentThreadId(), elapsed, (unsigned long long)calls, (unsigned long long)samples,
|
||||||
|
(unsigned long long)marked, access_ms, capture_ms, driver_ms);
|
||||||
|
calls = samples = marked = 0; access_ms = capture_ms = driver_ms = 0; since = Clock::now();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
thread_local HookSample hook_sample;
|
||||||
|
bool sample_hooks() { static const bool enabled = std::getenv("D4R_PROFILE_COMMAND_HOOKS") != nullptr; return enabled; }
|
||||||
struct Access {
|
struct Access {
|
||||||
std::shared_ptr<Recording> recording;
|
std::shared_ptr<Recording> recording;
|
||||||
std::unique_lock<std::recursive_mutex> lock;
|
std::unique_lock<std::recursive_mutex> lock;
|
||||||
ID3D12GraphicsCommandList* self;
|
ID3D12GraphicsCommandList* self;
|
||||||
explicit Access(ID3D12GraphicsCommandList* list) : recording(get_recording(list)), self(list) {
|
bool sampled = false;
|
||||||
|
Clock::time_point begin{}, acquired{}, driver{};
|
||||||
|
explicit Access(ID3D12GraphicsCommandList* list) : self(list) {
|
||||||
|
sampled = !internal && sample_hooks() && hook_sample.choose();
|
||||||
|
if (sampled) begin = Clock::now();
|
||||||
|
recording = get_recording(list);
|
||||||
if (recording) lock = std::unique_lock<std::recursive_mutex>(recording->mutex);
|
if (recording) lock = std::unique_lock<std::recursive_mutex>(recording->mutex);
|
||||||
|
if (sampled) acquired = Clock::now();
|
||||||
|
}
|
||||||
|
void driver_call() {
|
||||||
|
if (sampled) driver = Clock::now();
|
||||||
|
}
|
||||||
|
~Access() {
|
||||||
|
if (!sampled) return;
|
||||||
|
++hook_sample.samples;
|
||||||
|
hook_sample.access_ms += std::chrono::duration<double, std::milli>(acquired - begin).count();
|
||||||
|
if (driver != Clock::time_point{}) {
|
||||||
|
++hook_sample.marked;
|
||||||
|
hook_sample.capture_ms += std::chrono::duration<double, std::milli>(driver - acquired).count();
|
||||||
|
hook_sample.driver_ms += milliseconds(driver);
|
||||||
|
}
|
||||||
|
hook_sample.flush();
|
||||||
}
|
}
|
||||||
ID3D12GraphicsCommandList* target() const {
|
ID3D12GraphicsCommandList* target() const {
|
||||||
return recording && recording->current ? recording->current.Get() : self;
|
return recording && recording->current ? recording->current.Get() : self;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ using Fn_DrawInstanced = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* sel
|
|||||||
static Fn_DrawInstanced original_DrawInstanced = nullptr;
|
static Fn_DrawInstanced original_DrawInstanced = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_DrawInstanced(ID3D12GraphicsCommandList* self, UINT vertex_count_per_instance, UINT instance_count, UINT start_vertex_location, UINT start_instance_location) {
|
static void STDMETHODCALLTYPE hook_DrawInstanced(ID3D12GraphicsCommandList* self, UINT vertex_count_per_instance, UINT instance_count, UINT start_vertex_location, UINT start_instance_location) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_DrawInstanced(access.target(), vertex_count_per_instance, instance_count, start_vertex_location, start_instance_location);
|
return original_DrawInstanced(access.target(), vertex_count_per_instance, instance_count, start_vertex_location, start_instance_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,6 +24,7 @@ using Fn_DrawIndexedInstanced = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandLi
|
|||||||
static Fn_DrawIndexedInstanced original_DrawIndexedInstanced = nullptr;
|
static Fn_DrawIndexedInstanced original_DrawIndexedInstanced = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_DrawIndexedInstanced(ID3D12GraphicsCommandList* self, UINT index_count_per_instance, UINT instance_count, UINT start_vertex_location, INT base_vertex_location, UINT start_instance_location) {
|
static void STDMETHODCALLTYPE hook_DrawIndexedInstanced(ID3D12GraphicsCommandList* self, UINT index_count_per_instance, UINT instance_count, UINT start_vertex_location, INT base_vertex_location, UINT start_instance_location) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_DrawIndexedInstanced(access.target(), index_count_per_instance, instance_count, start_vertex_location, base_vertex_location, start_instance_location);
|
return original_DrawIndexedInstanced(access.target(), index_count_per_instance, instance_count, start_vertex_location, base_vertex_location, start_instance_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,6 +32,7 @@ using Fn_Dispatch = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* self, UI
|
|||||||
static Fn_Dispatch original_Dispatch = nullptr;
|
static Fn_Dispatch original_Dispatch = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_Dispatch(ID3D12GraphicsCommandList* self, UINT x, UINT u, UINT z) {
|
static void STDMETHODCALLTYPE hook_Dispatch(ID3D12GraphicsCommandList* self, UINT x, UINT u, UINT z) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_Dispatch(access.target(), x, u, z);
|
return original_Dispatch(access.target(), x, u, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,6 +40,7 @@ using Fn_CopyBufferRegion = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList*
|
|||||||
static Fn_CopyBufferRegion original_CopyBufferRegion = nullptr;
|
static Fn_CopyBufferRegion original_CopyBufferRegion = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_CopyBufferRegion(ID3D12GraphicsCommandList* self, ID3D12Resource *dst_buffer, UINT64 dst_offset, ID3D12Resource *src_buffer, UINT64 src_offset, UINT64 byte_count) {
|
static void STDMETHODCALLTYPE hook_CopyBufferRegion(ID3D12GraphicsCommandList* self, ID3D12Resource *dst_buffer, UINT64 dst_offset, ID3D12Resource *src_buffer, UINT64 src_offset, UINT64 byte_count) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_CopyBufferRegion(access.target(), dst_buffer, dst_offset, src_buffer, src_offset, byte_count);
|
return original_CopyBufferRegion(access.target(), dst_buffer, dst_offset, src_buffer, src_offset, byte_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +48,7 @@ using Fn_CopyTextureRegion = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList*
|
|||||||
static Fn_CopyTextureRegion original_CopyTextureRegion = nullptr;
|
static Fn_CopyTextureRegion original_CopyTextureRegion = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_CopyTextureRegion(ID3D12GraphicsCommandList* self, const D3D12_TEXTURE_COPY_LOCATION *dst, UINT dst_x, UINT dst_y, UINT dst_z, const D3D12_TEXTURE_COPY_LOCATION *src, const D3D12_BOX *src_box) {
|
static void STDMETHODCALLTYPE hook_CopyTextureRegion(ID3D12GraphicsCommandList* self, const D3D12_TEXTURE_COPY_LOCATION *dst, UINT dst_x, UINT dst_y, UINT dst_z, const D3D12_TEXTURE_COPY_LOCATION *src, const D3D12_BOX *src_box) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_CopyTextureRegion(access.target(), dst, dst_x, dst_y, dst_z, src, src_box);
|
return original_CopyTextureRegion(access.target(), dst, dst_x, dst_y, dst_z, src, src_box);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +56,7 @@ using Fn_CopyResource = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* self
|
|||||||
static Fn_CopyResource original_CopyResource = nullptr;
|
static Fn_CopyResource original_CopyResource = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_CopyResource(ID3D12GraphicsCommandList* self, ID3D12Resource *dst_resource, ID3D12Resource *src_resource) {
|
static void STDMETHODCALLTYPE hook_CopyResource(ID3D12GraphicsCommandList* self, ID3D12Resource *dst_resource, ID3D12Resource *src_resource) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_CopyResource(access.target(), dst_resource, src_resource);
|
return original_CopyResource(access.target(), dst_resource, src_resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +64,7 @@ using Fn_CopyTiles = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* self, I
|
|||||||
static Fn_CopyTiles original_CopyTiles = nullptr;
|
static Fn_CopyTiles original_CopyTiles = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_CopyTiles(ID3D12GraphicsCommandList* self, ID3D12Resource *tiled_resource, const D3D12_TILED_RESOURCE_COORDINATE *tile_region_start_coordinate, const D3D12_TILE_REGION_SIZE *tile_region_size, ID3D12Resource *buffer, UINT64 buffer_offset, D3D12_TILE_COPY_FLAGS flags) {
|
static void STDMETHODCALLTYPE hook_CopyTiles(ID3D12GraphicsCommandList* self, ID3D12Resource *tiled_resource, const D3D12_TILED_RESOURCE_COORDINATE *tile_region_start_coordinate, const D3D12_TILE_REGION_SIZE *tile_region_size, ID3D12Resource *buffer, UINT64 buffer_offset, D3D12_TILE_COPY_FLAGS flags) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_CopyTiles(access.target(), tiled_resource, tile_region_start_coordinate, tile_region_size, buffer, buffer_offset, flags);
|
return original_CopyTiles(access.target(), tiled_resource, tile_region_start_coordinate, tile_region_size, buffer, buffer_offset, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +72,7 @@ using Fn_ResolveSubresource = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList
|
|||||||
static Fn_ResolveSubresource original_ResolveSubresource = nullptr;
|
static Fn_ResolveSubresource original_ResolveSubresource = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_ResolveSubresource(ID3D12GraphicsCommandList* self, ID3D12Resource *dst_resource, UINT dst_sub_resource, ID3D12Resource *src_resource, UINT src_sub_resource, DXGI_FORMAT format) {
|
static void STDMETHODCALLTYPE hook_ResolveSubresource(ID3D12GraphicsCommandList* self, ID3D12Resource *dst_resource, UINT dst_sub_resource, ID3D12Resource *src_resource, UINT src_sub_resource, DXGI_FORMAT format) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_ResolveSubresource(access.target(), dst_resource, dst_sub_resource, src_resource, src_sub_resource, format);
|
return original_ResolveSubresource(access.target(), dst_resource, dst_sub_resource, src_resource, src_sub_resource, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +83,7 @@ static void STDMETHODCALLTYPE hook_IASetPrimitiveTopology(ID3D12GraphicsCommandL
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_IASetPrimitiveTopology(target, primitive_topology);
|
original_IASetPrimitiveTopology(target, primitive_topology);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_IASetPrimitiveTopology(access.target(), primitive_topology);
|
return original_IASetPrimitiveTopology(access.target(), primitive_topology);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +95,7 @@ static void STDMETHODCALLTYPE hook_RSSetViewports(ID3D12GraphicsCommandList* sel
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_RSSetViewports(target, viewport_count, values_pointer(saved_viewports));
|
original_RSSetViewports(target, viewport_count, values_pointer(saved_viewports));
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_RSSetViewports(access.target(), viewport_count, viewports);
|
return original_RSSetViewports(access.target(), viewport_count, viewports);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +107,7 @@ static void STDMETHODCALLTYPE hook_RSSetScissorRects(ID3D12GraphicsCommandList*
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_RSSetScissorRects(target, rect_count, values_pointer(saved_rects));
|
original_RSSetScissorRects(target, rect_count, values_pointer(saved_rects));
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_RSSetScissorRects(access.target(), rect_count, rects);
|
return original_RSSetScissorRects(access.target(), rect_count, rects);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +119,7 @@ static void STDMETHODCALLTYPE hook_OMSetBlendFactor(ID3D12GraphicsCommandList* s
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_OMSetBlendFactor(target, values_pointer(saved_blend_factor));
|
original_OMSetBlendFactor(target, values_pointer(saved_blend_factor));
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_OMSetBlendFactor(access.target(), blend_factor);
|
return original_OMSetBlendFactor(access.target(), blend_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +130,7 @@ static void STDMETHODCALLTYPE hook_OMSetStencilRef(ID3D12GraphicsCommandList* se
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_OMSetStencilRef(target, stencil_ref);
|
original_OMSetStencilRef(target, stencil_ref);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_OMSetStencilRef(access.target(), stencil_ref);
|
return original_OMSetStencilRef(access.target(), stencil_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +142,7 @@ static void STDMETHODCALLTYPE hook_SetPipelineState(ID3D12GraphicsCommandList* s
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetPipelineState(target, saved_pipeline_state.Get());
|
original_SetPipelineState(target, saved_pipeline_state.Get());
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetPipelineState(access.target(), pipeline_state);
|
return original_SetPipelineState(access.target(), pipeline_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,6 +162,7 @@ static void STDMETHODCALLTYPE hook_SetDescriptorHeaps(ID3D12GraphicsCommandList*
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetDescriptorHeaps(target, heap_count, saved_heaps.raw.data());
|
original_SetDescriptorHeaps(target, heap_count, saved_heaps.raw.data());
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetDescriptorHeaps(access.target(), heap_count, heaps);
|
return original_SetDescriptorHeaps(access.target(), heap_count, heaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +174,7 @@ static void STDMETHODCALLTYPE hook_SetComputeRootSignature(ID3D12GraphicsCommand
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetComputeRootSignature(target, saved_root_signature.Get());
|
original_SetComputeRootSignature(target, saved_root_signature.Get());
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetComputeRootSignature(access.target(), root_signature);
|
return original_SetComputeRootSignature(access.target(), root_signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +186,7 @@ static void STDMETHODCALLTYPE hook_SetGraphicsRootSignature(ID3D12GraphicsComman
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetGraphicsRootSignature(target, saved_root_signature.Get());
|
original_SetGraphicsRootSignature(target, saved_root_signature.Get());
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetGraphicsRootSignature(access.target(), root_signature);
|
return original_SetGraphicsRootSignature(access.target(), root_signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +197,7 @@ static void STDMETHODCALLTYPE hook_SetComputeRootDescriptorTable(ID3D12GraphicsC
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetComputeRootDescriptorTable(target, root_parameter_index, base_descriptor);
|
original_SetComputeRootDescriptorTable(target, root_parameter_index, base_descriptor);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetComputeRootDescriptorTable(access.target(), root_parameter_index, base_descriptor);
|
return original_SetComputeRootDescriptorTable(access.target(), root_parameter_index, base_descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +208,7 @@ static void STDMETHODCALLTYPE hook_SetGraphicsRootDescriptorTable(ID3D12Graphics
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetGraphicsRootDescriptorTable(target, root_parameter_index, base_descriptor);
|
original_SetGraphicsRootDescriptorTable(target, root_parameter_index, base_descriptor);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetGraphicsRootDescriptorTable(access.target(), root_parameter_index, base_descriptor);
|
return original_SetGraphicsRootDescriptorTable(access.target(), root_parameter_index, base_descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +219,7 @@ static void STDMETHODCALLTYPE hook_SetComputeRoot32BitConstant(ID3D12GraphicsCom
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetComputeRoot32BitConstant(target, root_parameter_index, data, dst_offset);
|
original_SetComputeRoot32BitConstant(target, root_parameter_index, data, dst_offset);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetComputeRoot32BitConstant(access.target(), root_parameter_index, data, dst_offset);
|
return original_SetComputeRoot32BitConstant(access.target(), root_parameter_index, data, dst_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,6 +230,7 @@ static void STDMETHODCALLTYPE hook_SetGraphicsRoot32BitConstant(ID3D12GraphicsCo
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetGraphicsRoot32BitConstant(target, root_parameter_index, data, dst_offset);
|
original_SetGraphicsRoot32BitConstant(target, root_parameter_index, data, dst_offset);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetGraphicsRoot32BitConstant(access.target(), root_parameter_index, data, dst_offset);
|
return original_SetGraphicsRoot32BitConstant(access.target(), root_parameter_index, data, dst_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +242,7 @@ static void STDMETHODCALLTYPE hook_SetComputeRoot32BitConstants(ID3D12GraphicsCo
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetComputeRoot32BitConstants(target, root_parameter_index, constant_count, values_pointer(saved_data), dst_offset);
|
original_SetComputeRoot32BitConstants(target, root_parameter_index, constant_count, values_pointer(saved_data), dst_offset);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetComputeRoot32BitConstants(access.target(), root_parameter_index, constant_count, data, dst_offset);
|
return original_SetComputeRoot32BitConstants(access.target(), root_parameter_index, constant_count, data, dst_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,6 +254,7 @@ static void STDMETHODCALLTYPE hook_SetGraphicsRoot32BitConstants(ID3D12GraphicsC
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetGraphicsRoot32BitConstants(target, root_parameter_index, constant_count, values_pointer(saved_data), dst_offset);
|
original_SetGraphicsRoot32BitConstants(target, root_parameter_index, constant_count, values_pointer(saved_data), dst_offset);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetGraphicsRoot32BitConstants(access.target(), root_parameter_index, constant_count, data, dst_offset);
|
return original_SetGraphicsRoot32BitConstants(access.target(), root_parameter_index, constant_count, data, dst_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,6 +265,7 @@ static void STDMETHODCALLTYPE hook_SetComputeRootConstantBufferView(ID3D12Graphi
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetComputeRootConstantBufferView(target, root_parameter_index, address);
|
original_SetComputeRootConstantBufferView(target, root_parameter_index, address);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetComputeRootConstantBufferView(access.target(), root_parameter_index, address);
|
return original_SetComputeRootConstantBufferView(access.target(), root_parameter_index, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,6 +276,7 @@ static void STDMETHODCALLTYPE hook_SetGraphicsRootConstantBufferView(ID3D12Graph
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetGraphicsRootConstantBufferView(target, root_parameter_index, address);
|
original_SetGraphicsRootConstantBufferView(target, root_parameter_index, address);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetGraphicsRootConstantBufferView(access.target(), root_parameter_index, address);
|
return original_SetGraphicsRootConstantBufferView(access.target(), root_parameter_index, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,6 +287,7 @@ static void STDMETHODCALLTYPE hook_SetComputeRootShaderResourceView(ID3D12Graphi
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetComputeRootShaderResourceView(target, root_parameter_index, address);
|
original_SetComputeRootShaderResourceView(target, root_parameter_index, address);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetComputeRootShaderResourceView(access.target(), root_parameter_index, address);
|
return original_SetComputeRootShaderResourceView(access.target(), root_parameter_index, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,6 +298,7 @@ static void STDMETHODCALLTYPE hook_SetGraphicsRootShaderResourceView(ID3D12Graph
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetGraphicsRootShaderResourceView(target, root_parameter_index, address);
|
original_SetGraphicsRootShaderResourceView(target, root_parameter_index, address);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetGraphicsRootShaderResourceView(access.target(), root_parameter_index, address);
|
return original_SetGraphicsRootShaderResourceView(access.target(), root_parameter_index, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,6 +309,7 @@ static void STDMETHODCALLTYPE hook_SetComputeRootUnorderedAccessView(ID3D12Graph
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetComputeRootUnorderedAccessView(target, root_parameter_index, address);
|
original_SetComputeRootUnorderedAccessView(target, root_parameter_index, address);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetComputeRootUnorderedAccessView(access.target(), root_parameter_index, address);
|
return original_SetComputeRootUnorderedAccessView(access.target(), root_parameter_index, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,6 +320,7 @@ static void STDMETHODCALLTYPE hook_SetGraphicsRootUnorderedAccessView(ID3D12Grap
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetGraphicsRootUnorderedAccessView(target, root_parameter_index, address);
|
original_SetGraphicsRootUnorderedAccessView(target, root_parameter_index, address);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetGraphicsRootUnorderedAccessView(access.target(), root_parameter_index, address);
|
return original_SetGraphicsRootUnorderedAccessView(access.target(), root_parameter_index, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,6 +332,7 @@ static void STDMETHODCALLTYPE hook_IASetIndexBuffer(ID3D12GraphicsCommandList* s
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_IASetIndexBuffer(target, values_pointer(saved_view));
|
original_IASetIndexBuffer(target, values_pointer(saved_view));
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_IASetIndexBuffer(access.target(), view);
|
return original_IASetIndexBuffer(access.target(), view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,6 +344,7 @@ static void STDMETHODCALLTYPE hook_IASetVertexBuffers(ID3D12GraphicsCommandList*
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_IASetVertexBuffers(target, start_slot, view_count, values_pointer(saved_views));
|
original_IASetVertexBuffers(target, start_slot, view_count, values_pointer(saved_views));
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_IASetVertexBuffers(access.target(), start_slot, view_count, views);
|
return original_IASetVertexBuffers(access.target(), start_slot, view_count, views);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,6 +356,7 @@ static void STDMETHODCALLTYPE hook_SOSetTargets(ID3D12GraphicsCommandList* self,
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SOSetTargets(target, start_slot, view_count, values_pointer(saved_views));
|
original_SOSetTargets(target, start_slot, view_count, values_pointer(saved_views));
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SOSetTargets(access.target(), start_slot, view_count, views);
|
return original_SOSetTargets(access.target(), start_slot, view_count, views);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,6 +369,7 @@ static void STDMETHODCALLTYPE hook_OMSetRenderTargets(ID3D12GraphicsCommandList*
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_OMSetRenderTargets(target, render_target_descriptor_count, values_pointer(saved_render_target_descriptors), single_descriptor_handle, values_pointer(saved_depth_stencil_descriptor));
|
original_OMSetRenderTargets(target, render_target_descriptor_count, values_pointer(saved_render_target_descriptors), single_descriptor_handle, values_pointer(saved_depth_stencil_descriptor));
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_OMSetRenderTargets(access.target(), render_target_descriptor_count, render_target_descriptors, single_descriptor_handle, depth_stencil_descriptor);
|
return original_OMSetRenderTargets(access.target(), render_target_descriptor_count, render_target_descriptors, single_descriptor_handle, depth_stencil_descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,6 +377,7 @@ using Fn_ClearDepthStencilView = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandL
|
|||||||
static Fn_ClearDepthStencilView original_ClearDepthStencilView = nullptr;
|
static Fn_ClearDepthStencilView original_ClearDepthStencilView = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_ClearDepthStencilView(ID3D12GraphicsCommandList* self, D3D12_CPU_DESCRIPTOR_HANDLE dsv, D3D12_CLEAR_FLAGS flags, FLOAT depth, UINT8 stencil, UINT rect_count, const D3D12_RECT *rects) {
|
static void STDMETHODCALLTYPE hook_ClearDepthStencilView(ID3D12GraphicsCommandList* self, D3D12_CPU_DESCRIPTOR_HANDLE dsv, D3D12_CLEAR_FLAGS flags, FLOAT depth, UINT8 stencil, UINT rect_count, const D3D12_RECT *rects) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_ClearDepthStencilView(access.target(), dsv, flags, depth, stencil, rect_count, rects);
|
return original_ClearDepthStencilView(access.target(), dsv, flags, depth, stencil, rect_count, rects);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,6 +385,7 @@ using Fn_ClearRenderTargetView = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandL
|
|||||||
static Fn_ClearRenderTargetView original_ClearRenderTargetView = nullptr;
|
static Fn_ClearRenderTargetView original_ClearRenderTargetView = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_ClearRenderTargetView(ID3D12GraphicsCommandList* self, D3D12_CPU_DESCRIPTOR_HANDLE rtv, const FLOAT color[4], UINT rect_count, const D3D12_RECT *rects) {
|
static void STDMETHODCALLTYPE hook_ClearRenderTargetView(ID3D12GraphicsCommandList* self, D3D12_CPU_DESCRIPTOR_HANDLE rtv, const FLOAT color[4], UINT rect_count, const D3D12_RECT *rects) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_ClearRenderTargetView(access.target(), rtv, color, rect_count, rects);
|
return original_ClearRenderTargetView(access.target(), rtv, color, rect_count, rects);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,6 +393,7 @@ using Fn_ClearUnorderedAccessViewUint = void(STDMETHODCALLTYPE*)(ID3D12GraphicsC
|
|||||||
static Fn_ClearUnorderedAccessViewUint original_ClearUnorderedAccessViewUint = nullptr;
|
static Fn_ClearUnorderedAccessViewUint original_ClearUnorderedAccessViewUint = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_ClearUnorderedAccessViewUint(ID3D12GraphicsCommandList* self, D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, ID3D12Resource *resource, const UINT values[4], UINT rect_count, const D3D12_RECT *rects) {
|
static void STDMETHODCALLTYPE hook_ClearUnorderedAccessViewUint(ID3D12GraphicsCommandList* self, D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, ID3D12Resource *resource, const UINT values[4], UINT rect_count, const D3D12_RECT *rects) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_ClearUnorderedAccessViewUint(access.target(), gpu_handle, cpu_handle, resource, values, rect_count, rects);
|
return original_ClearUnorderedAccessViewUint(access.target(), gpu_handle, cpu_handle, resource, values, rect_count, rects);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,6 +401,7 @@ using Fn_ClearUnorderedAccessViewFloat = void(STDMETHODCALLTYPE*)(ID3D12Graphics
|
|||||||
static Fn_ClearUnorderedAccessViewFloat original_ClearUnorderedAccessViewFloat = nullptr;
|
static Fn_ClearUnorderedAccessViewFloat original_ClearUnorderedAccessViewFloat = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_ClearUnorderedAccessViewFloat(ID3D12GraphicsCommandList* self, D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, ID3D12Resource *resource, const float values[4], UINT rect_count, const D3D12_RECT *rects) {
|
static void STDMETHODCALLTYPE hook_ClearUnorderedAccessViewFloat(ID3D12GraphicsCommandList* self, D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, ID3D12Resource *resource, const float values[4], UINT rect_count, const D3D12_RECT *rects) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_ClearUnorderedAccessViewFloat(access.target(), gpu_handle, cpu_handle, resource, values, rect_count, rects);
|
return original_ClearUnorderedAccessViewFloat(access.target(), gpu_handle, cpu_handle, resource, values, rect_count, rects);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,6 +409,7 @@ using Fn_DiscardResource = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* s
|
|||||||
static Fn_DiscardResource original_DiscardResource = nullptr;
|
static Fn_DiscardResource original_DiscardResource = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_DiscardResource(ID3D12GraphicsCommandList* self, ID3D12Resource *resource, const D3D12_DISCARD_REGION *region) {
|
static void STDMETHODCALLTYPE hook_DiscardResource(ID3D12GraphicsCommandList* self, ID3D12Resource *resource, const D3D12_DISCARD_REGION *region) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_DiscardResource(access.target(), resource, region);
|
return original_DiscardResource(access.target(), resource, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,6 +425,7 @@ using Fn_ResolveQueryData = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList*
|
|||||||
static Fn_ResolveQueryData original_ResolveQueryData = nullptr;
|
static Fn_ResolveQueryData original_ResolveQueryData = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_ResolveQueryData(ID3D12GraphicsCommandList* self, ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT start_index, UINT query_count, ID3D12Resource *dst_buffer, UINT64 aligned_dst_buffer_offset) {
|
static void STDMETHODCALLTYPE hook_ResolveQueryData(ID3D12GraphicsCommandList* self, ID3D12QueryHeap *heap, D3D12_QUERY_TYPE type, UINT start_index, UINT query_count, ID3D12Resource *dst_buffer, UINT64 aligned_dst_buffer_offset) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_ResolveQueryData(access.target(), heap, type, start_index, query_count, dst_buffer, aligned_dst_buffer_offset);
|
return original_ResolveQueryData(access.target(), heap, type, start_index, query_count, dst_buffer, aligned_dst_buffer_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,6 +437,7 @@ using Fn_SetMarker = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* self, U
|
|||||||
static Fn_SetMarker original_SetMarker = nullptr;
|
static Fn_SetMarker original_SetMarker = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_SetMarker(ID3D12GraphicsCommandList* self, UINT metadata, const void *data, UINT size) {
|
static void STDMETHODCALLTYPE hook_SetMarker(ID3D12GraphicsCommandList* self, UINT metadata, const void *data, UINT size) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_SetMarker(access.target(), metadata, data, size);
|
return original_SetMarker(access.target(), metadata, data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,6 +457,7 @@ using Fn_AtomicCopyBufferUINT = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandLi
|
|||||||
static Fn_AtomicCopyBufferUINT original_AtomicCopyBufferUINT = nullptr;
|
static Fn_AtomicCopyBufferUINT original_AtomicCopyBufferUINT = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_AtomicCopyBufferUINT(ID3D12GraphicsCommandList* self, ID3D12Resource *dst_buffer, UINT64 dst_offset, ID3D12Resource *src_buffer, UINT64 src_offset, UINT dependent_resource_count, ID3D12Resource *const *dependent_resources, const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges) {
|
static void STDMETHODCALLTYPE hook_AtomicCopyBufferUINT(ID3D12GraphicsCommandList* self, ID3D12Resource *dst_buffer, UINT64 dst_offset, ID3D12Resource *src_buffer, UINT64 src_offset, UINT dependent_resource_count, ID3D12Resource *const *dependent_resources, const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_AtomicCopyBufferUINT(access.target(), dst_buffer, dst_offset, src_buffer, src_offset, dependent_resource_count, dependent_resources, dependent_sub_resource_ranges);
|
return original_AtomicCopyBufferUINT(access.target(), dst_buffer, dst_offset, src_buffer, src_offset, dependent_resource_count, dependent_resources, dependent_sub_resource_ranges);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,6 +465,7 @@ using Fn_AtomicCopyBufferUINT64 = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommand
|
|||||||
static Fn_AtomicCopyBufferUINT64 original_AtomicCopyBufferUINT64 = nullptr;
|
static Fn_AtomicCopyBufferUINT64 original_AtomicCopyBufferUINT64 = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_AtomicCopyBufferUINT64(ID3D12GraphicsCommandList* self, ID3D12Resource *dst_buffer, UINT64 dst_offset, ID3D12Resource *src_buffer, UINT64 src_offset, UINT dependent_resource_count, ID3D12Resource *const *dependent_resources, const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges) {
|
static void STDMETHODCALLTYPE hook_AtomicCopyBufferUINT64(ID3D12GraphicsCommandList* self, ID3D12Resource *dst_buffer, UINT64 dst_offset, ID3D12Resource *src_buffer, UINT64 src_offset, UINT dependent_resource_count, ID3D12Resource *const *dependent_resources, const D3D12_SUBRESOURCE_RANGE_UINT64 *dependent_sub_resource_ranges) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_AtomicCopyBufferUINT64(access.target(), dst_buffer, dst_offset, src_buffer, src_offset, dependent_resource_count, dependent_resources, dependent_sub_resource_ranges);
|
return original_AtomicCopyBufferUINT64(access.target(), dst_buffer, dst_offset, src_buffer, src_offset, dependent_resource_count, dependent_resources, dependent_sub_resource_ranges);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,6 +476,7 @@ static void STDMETHODCALLTYPE hook_OMSetDepthBounds(ID3D12GraphicsCommandList* s
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_OMSetDepthBounds(target, min, max);
|
original_OMSetDepthBounds(target, min, max);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_OMSetDepthBounds(access.target(), min, max);
|
return original_OMSetDepthBounds(access.target(), min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,6 +488,7 @@ static void STDMETHODCALLTYPE hook_SetSamplePositions(ID3D12GraphicsCommandList*
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetSamplePositions(target, sample_count, pixel_count, values_pointer(saved_sample_positions));
|
original_SetSamplePositions(target, sample_count, pixel_count, values_pointer(saved_sample_positions));
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetSamplePositions(access.target(), sample_count, pixel_count, sample_positions);
|
return original_SetSamplePositions(access.target(), sample_count, pixel_count, sample_positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,6 +496,7 @@ using Fn_ResolveSubresourceRegion = void(STDMETHODCALLTYPE*)(ID3D12GraphicsComma
|
|||||||
static Fn_ResolveSubresourceRegion original_ResolveSubresourceRegion = nullptr;
|
static Fn_ResolveSubresourceRegion original_ResolveSubresourceRegion = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_ResolveSubresourceRegion(ID3D12GraphicsCommandList* self, ID3D12Resource *dst_resource, UINT dst_sub_resource_idx, UINT dst_x, UINT dst_y, ID3D12Resource *src_resource, UINT src_sub_resource_idx, D3D12_RECT *src_rect, DXGI_FORMAT format, D3D12_RESOLVE_MODE mode) {
|
static void STDMETHODCALLTYPE hook_ResolveSubresourceRegion(ID3D12GraphicsCommandList* self, ID3D12Resource *dst_resource, UINT dst_sub_resource_idx, UINT dst_x, UINT dst_y, ID3D12Resource *src_resource, UINT src_sub_resource_idx, D3D12_RECT *src_rect, DXGI_FORMAT format, D3D12_RESOLVE_MODE mode) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_ResolveSubresourceRegion(access.target(), dst_resource, dst_sub_resource_idx, dst_x, dst_y, src_resource, src_sub_resource_idx, src_rect, format, mode);
|
return original_ResolveSubresourceRegion(access.target(), dst_resource, dst_sub_resource_idx, dst_x, dst_y, src_resource, src_sub_resource_idx, src_rect, format, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,6 +507,7 @@ static void STDMETHODCALLTYPE hook_SetViewInstanceMask(ID3D12GraphicsCommandList
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetViewInstanceMask(target, mask);
|
original_SetViewInstanceMask(target, mask);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetViewInstanceMask(access.target(), mask);
|
return original_SetViewInstanceMask(access.target(), mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,6 +515,7 @@ using Fn_WriteBufferImmediate = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandLi
|
|||||||
static Fn_WriteBufferImmediate original_WriteBufferImmediate = nullptr;
|
static Fn_WriteBufferImmediate original_WriteBufferImmediate = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_WriteBufferImmediate(ID3D12GraphicsCommandList* self, UINT count, const D3D12_WRITEBUFFERIMMEDIATE_PARAMETER *parameters, const D3D12_WRITEBUFFERIMMEDIATE_MODE *modes) {
|
static void STDMETHODCALLTYPE hook_WriteBufferImmediate(ID3D12GraphicsCommandList* self, UINT count, const D3D12_WRITEBUFFERIMMEDIATE_PARAMETER *parameters, const D3D12_WRITEBUFFERIMMEDIATE_MODE *modes) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_WriteBufferImmediate(access.target(), count, parameters, modes);
|
return original_WriteBufferImmediate(access.target(), count, parameters, modes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,6 +527,7 @@ static void STDMETHODCALLTYPE hook_SetProtectedResourceSession(ID3D12GraphicsCom
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetProtectedResourceSession(target, saved_protected_resource_session.Get());
|
original_SetProtectedResourceSession(target, saved_protected_resource_session.Get());
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetProtectedResourceSession(access.target(), protected_resource_session);
|
return original_SetProtectedResourceSession(access.target(), protected_resource_session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,6 +543,7 @@ using Fn_InitializeMetaCommand = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandL
|
|||||||
static Fn_InitializeMetaCommand original_InitializeMetaCommand = nullptr;
|
static Fn_InitializeMetaCommand original_InitializeMetaCommand = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_InitializeMetaCommand(ID3D12GraphicsCommandList* self, ID3D12MetaCommand *meta_command, const void *initialization_parameters_data, SIZE_T initialization_parameters_data_size_in_bytes) {
|
static void STDMETHODCALLTYPE hook_InitializeMetaCommand(ID3D12GraphicsCommandList* self, ID3D12MetaCommand *meta_command, const void *initialization_parameters_data, SIZE_T initialization_parameters_data_size_in_bytes) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_InitializeMetaCommand(access.target(), meta_command, initialization_parameters_data, initialization_parameters_data_size_in_bytes);
|
return original_InitializeMetaCommand(access.target(), meta_command, initialization_parameters_data, initialization_parameters_data_size_in_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,6 +551,7 @@ using Fn_ExecuteMetaCommand = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList
|
|||||||
static Fn_ExecuteMetaCommand original_ExecuteMetaCommand = nullptr;
|
static Fn_ExecuteMetaCommand original_ExecuteMetaCommand = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_ExecuteMetaCommand(ID3D12GraphicsCommandList* self, ID3D12MetaCommand *meta_command, const void *execution_parameters_data, SIZE_T execution_parameters_data_size_in_bytes) {
|
static void STDMETHODCALLTYPE hook_ExecuteMetaCommand(ID3D12GraphicsCommandList* self, ID3D12MetaCommand *meta_command, const void *execution_parameters_data, SIZE_T execution_parameters_data_size_in_bytes) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_ExecuteMetaCommand(access.target(), meta_command, execution_parameters_data, execution_parameters_data_size_in_bytes);
|
return original_ExecuteMetaCommand(access.target(), meta_command, execution_parameters_data, execution_parameters_data_size_in_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,6 +559,7 @@ using Fn_BuildRaytracingAccelerationStructure = void(STDMETHODCALLTYPE*)(ID3D12G
|
|||||||
static Fn_BuildRaytracingAccelerationStructure original_BuildRaytracingAccelerationStructure = nullptr;
|
static Fn_BuildRaytracingAccelerationStructure original_BuildRaytracingAccelerationStructure = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_BuildRaytracingAccelerationStructure(ID3D12GraphicsCommandList* self, const D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC *desc, UINT postbuild_info_descs_count, const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC *postbuild_info_descs) {
|
static void STDMETHODCALLTYPE hook_BuildRaytracingAccelerationStructure(ID3D12GraphicsCommandList* self, const D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC *desc, UINT postbuild_info_descs_count, const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC *postbuild_info_descs) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_BuildRaytracingAccelerationStructure(access.target(), desc, postbuild_info_descs_count, postbuild_info_descs);
|
return original_BuildRaytracingAccelerationStructure(access.target(), desc, postbuild_info_descs_count, postbuild_info_descs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,6 +567,7 @@ using Fn_EmitRaytracingAccelerationStructurePostbuildInfo = void(STDMETHODCALLTY
|
|||||||
static Fn_EmitRaytracingAccelerationStructurePostbuildInfo original_EmitRaytracingAccelerationStructurePostbuildInfo = nullptr;
|
static Fn_EmitRaytracingAccelerationStructurePostbuildInfo original_EmitRaytracingAccelerationStructurePostbuildInfo = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_EmitRaytracingAccelerationStructurePostbuildInfo(ID3D12GraphicsCommandList* self, const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC *desc, UINT src_acceleration_structures_count, const D3D12_GPU_VIRTUAL_ADDRESS *src_acceleration_structure_data) {
|
static void STDMETHODCALLTYPE hook_EmitRaytracingAccelerationStructurePostbuildInfo(ID3D12GraphicsCommandList* self, const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC *desc, UINT src_acceleration_structures_count, const D3D12_GPU_VIRTUAL_ADDRESS *src_acceleration_structure_data) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_EmitRaytracingAccelerationStructurePostbuildInfo(access.target(), desc, src_acceleration_structures_count, src_acceleration_structure_data);
|
return original_EmitRaytracingAccelerationStructurePostbuildInfo(access.target(), desc, src_acceleration_structures_count, src_acceleration_structure_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,6 +575,7 @@ using Fn_CopyRaytracingAccelerationStructure = void(STDMETHODCALLTYPE*)(ID3D12Gr
|
|||||||
static Fn_CopyRaytracingAccelerationStructure original_CopyRaytracingAccelerationStructure = nullptr;
|
static Fn_CopyRaytracingAccelerationStructure original_CopyRaytracingAccelerationStructure = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_CopyRaytracingAccelerationStructure(ID3D12GraphicsCommandList* self, D3D12_GPU_VIRTUAL_ADDRESS dst_acceleration_structure_data, D3D12_GPU_VIRTUAL_ADDRESS src_acceleration_structure_data, D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE mode) {
|
static void STDMETHODCALLTYPE hook_CopyRaytracingAccelerationStructure(ID3D12GraphicsCommandList* self, D3D12_GPU_VIRTUAL_ADDRESS dst_acceleration_structure_data, D3D12_GPU_VIRTUAL_ADDRESS src_acceleration_structure_data, D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE mode) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_CopyRaytracingAccelerationStructure(access.target(), dst_acceleration_structure_data, src_acceleration_structure_data, mode);
|
return original_CopyRaytracingAccelerationStructure(access.target(), dst_acceleration_structure_data, src_acceleration_structure_data, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,6 +587,7 @@ static void STDMETHODCALLTYPE hook_SetPipelineState1(ID3D12GraphicsCommandList*
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_SetPipelineState1(target, saved_state_object.Get());
|
original_SetPipelineState1(target, saved_state_object.Get());
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_SetPipelineState1(access.target(), state_object);
|
return original_SetPipelineState1(access.target(), state_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,6 +595,7 @@ using Fn_DispatchRays = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* self
|
|||||||
static Fn_DispatchRays original_DispatchRays = nullptr;
|
static Fn_DispatchRays original_DispatchRays = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_DispatchRays(ID3D12GraphicsCommandList* self, const D3D12_DISPATCH_RAYS_DESC *desc) {
|
static void STDMETHODCALLTYPE hook_DispatchRays(ID3D12GraphicsCommandList* self, const D3D12_DISPATCH_RAYS_DESC *desc) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_DispatchRays(access.target(), desc);
|
return original_DispatchRays(access.target(), desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,6 +607,7 @@ static void STDMETHODCALLTYPE hook_RSSetShadingRate(ID3D12GraphicsCommandList* s
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_RSSetShadingRate(target, base_shading_rate, values_pointer(saved_combiners));
|
original_RSSetShadingRate(target, base_shading_rate, values_pointer(saved_combiners));
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_RSSetShadingRate(access.target(), base_shading_rate, combiners);
|
return original_RSSetShadingRate(access.target(), base_shading_rate, combiners);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,6 +619,7 @@ static void STDMETHODCALLTYPE hook_RSSetShadingRateImage(ID3D12GraphicsCommandLi
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {
|
||||||
original_RSSetShadingRateImage(target, saved_shading_rate_image.Get());
|
original_RSSetShadingRateImage(target, saved_shading_rate_image.Get());
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
return original_RSSetShadingRateImage(access.target(), shading_rate_image);
|
return original_RSSetShadingRateImage(access.target(), shading_rate_image);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,6 +627,7 @@ using Fn_DispatchMesh = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* self
|
|||||||
static Fn_DispatchMesh original_DispatchMesh = nullptr;
|
static Fn_DispatchMesh original_DispatchMesh = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_DispatchMesh(ID3D12GraphicsCommandList* self, UINT thread_group_count_x, UINT thread_group_count_y, UINT thread_group_count_z) {
|
static void STDMETHODCALLTYPE hook_DispatchMesh(ID3D12GraphicsCommandList* self, UINT thread_group_count_x, UINT thread_group_count_y, UINT thread_group_count_z) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
return original_DispatchMesh(access.target(), thread_group_count_x, thread_group_count_y, thread_group_count_z);
|
return original_DispatchMesh(access.target(), thread_group_count_x, thread_group_count_y, thread_group_count_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,6 +642,7 @@ static void STDMETHODCALLTYPE hook_OMSetFrontAndBackStencilRef(ID3D12GraphicsCom
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) {
|
||||||
original_OMSetFrontAndBackStencilRef(target, front_stencil, back_stencil);
|
original_OMSetFrontAndBackStencilRef(target, front_stencil, back_stencil);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
original_OMSetFrontAndBackStencilRef(access.target(), front_stencil, back_stencil);
|
original_OMSetFrontAndBackStencilRef(access.target(), front_stencil, back_stencil);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,6 +653,7 @@ static void STDMETHODCALLTYPE hook_RSSetDepthBias(ID3D12GraphicsCommandList* sel
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) {
|
||||||
original_RSSetDepthBias(target, depth_bias, clamp, slope);
|
original_RSSetDepthBias(target, depth_bias, clamp, slope);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
original_RSSetDepthBias(access.target(), depth_bias, clamp, slope);
|
original_RSSetDepthBias(access.target(), depth_bias, clamp, slope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,6 +664,7 @@ static void STDMETHODCALLTYPE hook_IASetIndexBufferStripCutValue(ID3D12GraphicsC
|
|||||||
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) {
|
if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) {
|
||||||
original_IASetIndexBufferStripCutValue(target, value);
|
original_IASetIndexBufferStripCutValue(target, value);
|
||||||
});
|
});
|
||||||
|
access.driver_call();
|
||||||
original_IASetIndexBufferStripCutValue(access.target(), value);
|
original_IASetIndexBufferStripCutValue(access.target(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,6 +676,7 @@ using Fn_DispatchGraph = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* sel
|
|||||||
static Fn_DispatchGraph original_DispatchGraph = nullptr;
|
static Fn_DispatchGraph original_DispatchGraph = nullptr;
|
||||||
static void STDMETHODCALLTYPE hook_DispatchGraph(ID3D12GraphicsCommandList* self, const void* desc) {
|
static void STDMETHODCALLTYPE hook_DispatchGraph(ID3D12GraphicsCommandList* self, const void* desc) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
access.driver_call();
|
||||||
original_DispatchGraph(access.target(), desc);
|
original_DispatchGraph(access.target(), desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ struct Callback {
|
|||||||
ID3D12Resource* readback;
|
ID3D12Resource* readback;
|
||||||
uint32_t expected_seed = seed;
|
uint32_t expected_seed = seed;
|
||||||
bool prefix_verified = false;
|
bool prefix_verified = false;
|
||||||
|
uint32_t expected_multiplier = 17, expected_addend = 10;
|
||||||
};
|
};
|
||||||
void WINAPI boundary(ID3D12CommandQueue* queue, void* context) {
|
void WINAPI boundary(ID3D12CommandQueue* queue, void* context) {
|
||||||
auto& callback = *static_cast<Callback*>(context);
|
auto& callback = *static_cast<Callback*>(context);
|
||||||
@@ -93,7 +94,8 @@ void WINAPI boundary(ID3D12CommandQueue* queue, void* context) {
|
|||||||
list.list->CopyResource(callback.input, callback.replacement);
|
list.list->CopyResource(callback.input, callback.replacement);
|
||||||
transition(list.list.Get(), callback.input, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
transition(list.list.Get(), callback.input, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
||||||
list.submit(callback.device, queue);
|
list.submit(callback.device, queue);
|
||||||
callback.prefix_verified = verify(callback.readback, 17, 10, callback.expected_seed);
|
callback.prefix_verified = verify(callback.readback, callback.expected_multiplier,
|
||||||
|
callback.expected_addend, callback.expected_seed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,13 +265,38 @@ int main(int argc, char** argv) {
|
|||||||
ID3D12CommandList* batch[] = {a.list.Get(), b.list.Get(), c.list.Get()};
|
ID3D12CommandList* batch[] = {a.list.Get(), b.list.Get(), c.list.Get()};
|
||||||
queue->ExecuteCommandLists(no_hooks ? 2 : 3, batch + (no_hooks ? 1 : 0)); drain(device.Get(), queue.Get());
|
queue->ExecuteCommandLists(no_hooks ? 2 : 3, batch + (no_hooks ? 1 : 0)); drain(device.Get(), queue.Get());
|
||||||
if (!callback.prefix_verified || !verify(readback.Get(), 25, 100, expected_seed)) throw std::runtime_error("Queue order or suffix root state mismatch");
|
if (!callback.prefix_verified || !verify(readback.Get(), 25, 100, expected_seed)) throw std::runtime_error("Queue order or suffix root state mismatch");
|
||||||
|
if (!no_hooks) for (unsigned reuse = 0; reuse < 2; ++reuse) {
|
||||||
|
// Populate the same thread's routing cache with a split
|
||||||
|
// list, Reset that exact COM object, then split again with
|
||||||
|
// different root state. A cached previous Recording would
|
||||||
|
// keep targeting the old suffix or replay the old Seed.
|
||||||
|
dx(b.allocator->Reset(), "Reset reused allocator");
|
||||||
|
dx(b.list->Reset(b.allocator.Get(), initial_pso ? pso.Get() : nullptr), "Reset reused logical list");
|
||||||
|
b.list->SetComputeRootSignature(root.Get());
|
||||||
|
if (!initial_pso) b.list->SetPipelineState(pso.Get());
|
||||||
|
b.list->SetComputeRootUnorderedAccessView(0, output->GetGPUVirtualAddress());
|
||||||
|
b.list->SetComputeRootShaderResourceView(1, input->GetGPUVirtualAddress());
|
||||||
|
callback.expected_seed = seed + iteration + reuse + 1;
|
||||||
|
callback.expected_multiplier = 25; callback.expected_addend = 100;
|
||||||
|
callback.prefix_verified = false;
|
||||||
|
b.list->SetComputeRoot32BitConstant(2, callback.expected_seed, 0);
|
||||||
|
b.list->Dispatch(count / 64, 1, 1);
|
||||||
|
if (record(b.list.Get(), boundary, &callback) != 1) throw std::runtime_error("Record reused split failed");
|
||||||
|
b.list->Dispatch(count / 64, 1, 1);
|
||||||
|
transition(b.list.Get(), output.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
||||||
|
b.list->CopyResource(readback.Get(), output.Get());
|
||||||
|
transition(b.list.Get(), output.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
|
||||||
|
b.submit(device.Get(), queue.Get());
|
||||||
|
if (!callback.prefix_verified || !verify(readback.Get(), 25, 100, callback.expected_seed))
|
||||||
|
throw std::runtime_error("Reset reused logical list retained stale routing/root state");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (live() != 0) throw std::runtime_error("D3D12 recording metadata leaked after command-list Release");
|
if (live() != 0) throw std::runtime_error("D3D12 recording metadata leaked after command-list Release");
|
||||||
}
|
}
|
||||||
const bool warp = std::getenv("D4R_COMMAND_PROBE_WARP") != nullptr;
|
const bool warp = std::getenv("D4R_COMMAND_PROBE_WARP") != nullptr;
|
||||||
std::printf("PASS D3D12_COMMAND_BACKEND adapter=%s architecture=%s backend=%u iterations=%u batch_order=1 root_state=1 deep_copy=1 indirect=%u indirect_reset=%u live_recordings=0 frame_age=0\n",
|
std::printf("PASS D3D12_COMMAND_BACKEND adapter=%s architecture=%s backend=%u iterations=%u batch_order=1 root_state=1 deep_copy=1 indirect=%u indirect_reset=%u reset_reuse=%u live_recordings=0 frame_age=0\n",
|
||||||
warp ? "WARP" : "AMD", warp ? "software" : no_hip ? "not_queried" : "gfx1201", !no_hooks,
|
warp ? "WARP" : "AMD", warp ? "software" : no_hip ? "not_queried" : "gfx1201", !no_hooks,
|
||||||
args.iterations, indirect_enabled, root_indirect);
|
args.iterations, indirect_enabled, root_indirect, no_hooks ? 0 : 2 * args.iterations);
|
||||||
return 0;
|
return 0;
|
||||||
} catch (const std::exception& failure) {
|
} catch (const std::exception& failure) {
|
||||||
std::fprintf(stderr, "FAIL D3D12_COMMAND_BACKEND %s\n", failure.what());
|
std::fprintf(stderr, "FAIL D3D12_COMMAND_BACKEND %s\n", failure.what());
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ def generate(source):
|
|||||||
captured.append(argument)
|
captured.append(argument)
|
||||||
lines += [' if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {',
|
lines += [' if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) mutable {',
|
||||||
f' original_{name}(' + ', '.join(['target'] + captured) + ');', ' });']
|
f' original_{name}(' + ', '.join(['target'] + captured) + ');', ' });']
|
||||||
lines += [f' return original_{name}({call});', '}']
|
lines += [' access.driver_call();', f' return original_{name}({call});', '}']
|
||||||
registrations.append(f' attach_method(table[{slot}], reinterpret_cast<void*>(hook_{name}), reinterpret_cast<void**>(&original_{name}), "{name}");')
|
registrations.append(f' attach_method(table[{slot}], reinterpret_cast<void*>(hook_{name}), reinterpret_cast<void**>(&original_{name}), "{name}");')
|
||||||
registrations[-1] = f' if (version >= {version})' + registrations[-1][3:]
|
registrations[-1] = f' if (version >= {version})' + registrations[-1][3:]
|
||||||
slot += 1
|
slot += 1
|
||||||
@@ -112,7 +112,7 @@ def generate(source):
|
|||||||
if name != 'DispatchGraph':
|
if name != 'DispatchGraph':
|
||||||
lines += [' if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) {',
|
lines += [' if (access.recording) access.recording->state.emplace_back([=](ID3D12GraphicsCommandList* target) {',
|
||||||
f' original_{name}(' + ', '.join(['target'] + names) + ');', ' });']
|
f' original_{name}(' + ', '.join(['target'] + names) + ');', ' });']
|
||||||
lines += [f' original_{name}(' + ', '.join(['access.target()'] + names) + ');', '}']
|
lines += [' access.driver_call();', f' original_{name}(' + ', '.join(['access.target()'] + names) + ');', '}']
|
||||||
registrations.append(f' if (version >= {version}) attach_method(table[{slot}], reinterpret_cast<void*>(hook_{name}), reinterpret_cast<void**>(&original_{name}), "{name}");')
|
registrations.append(f' if (version >= {version}) attach_method(table[{slot}], reinterpret_cast<void*>(hook_{name}), reinterpret_cast<void**>(&original_{name}), "{name}");')
|
||||||
slot += 1
|
slot += 1
|
||||||
lines.append('')
|
lines.append('')
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ def report(directory, metadata_directory=None):
|
|||||||
stages = collections.defaultdict(list)
|
stages = collections.defaultdict(list)
|
||||||
commands = collections.defaultdict(list)
|
commands = collections.defaultdict(list)
|
||||||
kernels = collections.defaultdict(list)
|
kernels = collections.defaultdict(list)
|
||||||
|
hook_threads = collections.defaultdict(list)
|
||||||
for path in sorted(directory.glob('*.log')):
|
for path in sorted(directory.glob('*.log')):
|
||||||
text = path.read_text(encoding='utf-8-sig', errors='replace')
|
text = path.read_text(encoding='utf-8-sig', errors='replace')
|
||||||
for name, value in re.findall(r'D4R_STAGE name=(\S+) cpu_ms=([0-9.]+)', text):
|
for name, value in re.findall(r'D4R_STAGE name=(\S+) cpu_ms=([0-9.]+)', text):
|
||||||
@@ -51,18 +52,37 @@ def report(directory, metadata_directory=None):
|
|||||||
if name != 'interval_ms' or number > 0:
|
if name != 'interval_ms' or number > 0:
|
||||||
commands[kind.lower() + '.' + name].append(number)
|
commands[kind.lower() + '.' + name].append(number)
|
||||||
for line in text.splitlines():
|
for line in text.splitlines():
|
||||||
|
if line.startswith('D4R_COMMAND_HOOK_SAMPLE '):
|
||||||
|
fields = dict(re.findall(r'(\w+)=(\S+)', line))
|
||||||
|
if all(name in fields for name in ('thread', 'period_ms', 'calls', 'samples', 'marked',
|
||||||
|
'access_sum_ms', 'capture_sum_ms', 'driver_sum_ms')):
|
||||||
|
hook_threads[fields['thread']].append(fields)
|
||||||
if not line.startswith('D4R_KERNEL_PROFILE '):
|
if not line.startswith('D4R_KERNEL_PROFILE '):
|
||||||
continue
|
continue
|
||||||
fields = dict(re.findall(r'(\w+)=("[^"]+"|\S+)', line))
|
fields = dict(re.findall(r'(\w+)=("[^"]+"|\S+)', line))
|
||||||
kernels[(fields['kernel'].strip('"'), fields['backend'], fields['phase'])].append(fields)
|
kernels[(fields['kernel'].strip('"'), fields['backend'], fields['phase'])].append(fields)
|
||||||
result = dict(cpuStages={name: stats(values) for name, values in stages.items()},
|
result = dict(cpuStages={name: stats(values) for name, values in stages.items()},
|
||||||
commandStages={name: stats(values) for name, values in commands.items()},
|
commandStages={name: stats(values) for name, values in commands.items()},
|
||||||
|
commandHookSamples=[],
|
||||||
kernels=[], notes=[
|
kernels=[], notes=[
|
||||||
'CPU stage times include waits and host work; they are not isolated GPU timings.',
|
'CPU stage times include waits and host work; they are not isolated GPU timings.',
|
||||||
'Command record intervals are between NGX recording calls on one thread, not Present/FPS.',
|
'Command record intervals are between NGX recording calls on one thread, not Present/FPS.',
|
||||||
|
'Hook estimates use random one-in-64 samples; driver timing covers generated forwarding methods only.',
|
||||||
|
'Hook access includes lock waits; summing threads does not measure serial frame latency or CPU execution time.',
|
||||||
'HIP-event profiling synchronizes every sampled launch and changes scheduling.',
|
'HIP-event profiling synchronizes every sampled launch and changes scheduling.',
|
||||||
'Occupancy is an API prediction, not a measured hardware counter.',
|
'Occupancy is an API prediction, not a measured hardware counter.',
|
||||||
'Bandwidth and WMMA utilization require additional supported hardware tooling.'])
|
'Bandwidth and WMMA utilization require additional supported hardware tooling.'])
|
||||||
|
for thread, rows in hook_threads.items():
|
||||||
|
sums = {name: sum(float(row[name]) for row in rows) for name in
|
||||||
|
('period_ms', 'calls', 'samples', 'marked', 'access_sum_ms', 'capture_sum_ms', 'driver_sum_ms')}
|
||||||
|
if not sums['samples'] or not sums['period_ms']:
|
||||||
|
continue
|
||||||
|
scale = sums['calls'] / sums['samples']
|
||||||
|
estimate = scale * (sums['access_sum_ms'] + sums['capture_sum_ms'])
|
||||||
|
result['commandHookSamples'].append(dict(thread=int(thread), periods=len(rows), **sums,
|
||||||
|
accessMeanUs=1000 * sums['access_sum_ms'] / sums['samples'],
|
||||||
|
captureMeanUsPerSample=1000 * sums['capture_sum_ms'] / sums['samples'],
|
||||||
|
estimatedAccessCaptureMs=estimate, estimatedAccessCaptureMsPerSecond=1000 * estimate / sums['period_ms']))
|
||||||
for (name, backend, phase), rows in kernels.items():
|
for (name, backend, phase), rows in kernels.items():
|
||||||
item = dict(kernel=name, backend=backend, phase=phase,
|
item = dict(kernel=name, backend=backend, phase=phase,
|
||||||
gpuMs=stats([float(row['gpu_ms']) for row in rows]),
|
gpuMs=stats([float(row['gpu_ms']) for row in rows]),
|
||||||
@@ -93,6 +113,9 @@ def main():
|
|||||||
print(f"CPU {name}: n={row['samples']} mean={row['mean']:.3f} ms median={row['median']:.3f} ms p95={row['p95']:.3f} ms")
|
print(f"CPU {name}: n={row['samples']} mean={row['mean']:.3f} ms median={row['median']:.3f} ms p95={row['p95']:.3f} ms")
|
||||||
for name, row in result['commandStages'].items():
|
for name, row in result['commandStages'].items():
|
||||||
print(f"COMMAND {name}: n={row['samples']} mean={row['mean']:.3f} ms median={row['median']:.3f} ms p95={row['p95']:.3f} ms")
|
print(f"COMMAND {name}: n={row['samples']} mean={row['mean']:.3f} ms median={row['median']:.3f} ms p95={row['p95']:.3f} ms")
|
||||||
|
for row in result['commandHookSamples']:
|
||||||
|
print(f"HOOK thread={row['thread']} samples={int(row['samples'])} access={row['accessMeanUs']:.3f} us "
|
||||||
|
f"capture={row['captureMeanUsPerSample']:.3f} us estimated_cpu={row['estimatedAccessCaptureMsPerSecond']:.3f} ms/s")
|
||||||
for row in result['kernels']:
|
for row in result['kernels']:
|
||||||
times = row['gpuMs']
|
times = row['gpuMs']
|
||||||
print(f"GPU {row['kernel']} {row['backend']} {row['phase']}: n={times['samples']} mean={times['mean']:.6f} ms total={times['total']:.3f} ms")
|
print(f"GPU {row['kernel']} {row['backend']} {row['phase']}: n={times['samples']} mean={times['mean']:.6f} ms total={times['total']:.3f} ms")
|
||||||
|
|||||||
Reference in new issue
Block a user