Preserve initial PSO and enhanced texture layouts in Windows interop
This commit is contained in:
1 parent
e9eec6d4e0
commit
6ddf740877
15 files changed
+224
-32
No files matched your search
@@ -192,9 +192,15 @@ include(CTest)
|
|||||||
add_test(NAME d3d12_gpu_pixel_formats COMMAND d4r_d3d12_pixel_probe
|
add_test(NAME d3d12_gpu_pixel_formats COMMAND d4r_d3d12_pixel_probe
|
||||||
--hip-root "${D4R_HIP_ROOT}" --module "${pixel_object}" --iterations 2)
|
--hip-root "${D4R_HIP_ROOT}" --module "${pixel_object}" --iterations 2)
|
||||||
set_tests_properties(d3d12_gpu_pixel_formats PROPERTIES TIMEOUT 120 LABELS "hardware;gfx1201;formats")
|
set_tests_properties(d3d12_gpu_pixel_formats PROPERTIES TIMEOUT 120 LABELS "hardware;gfx1201;formats")
|
||||||
|
add_test(NAME d3d12_gpu_enhanced_formats COMMAND d4r_d3d12_pixel_probe
|
||||||
|
--hip-root "${D4R_HIP_ROOT}" --module "${pixel_object}" --interop-mode enhanced --iterations 2)
|
||||||
|
set_tests_properties(d3d12_gpu_enhanced_formats PROPERTIES TIMEOUT 120 LABELS "hardware;gfx1201;formats;enhanced_barriers")
|
||||||
add_test(NAME d3d12_command_backend COMMAND d4r_d3d12_command_probe
|
add_test(NAME d3d12_command_backend COMMAND d4r_d3d12_command_probe
|
||||||
--hip-root "${D4R_HIP_ROOT}" --module "$<TARGET_FILE:d4r_nvngx_windows>" --interop-mode indirect --iterations 32)
|
--hip-root "${D4R_HIP_ROOT}" --module "$<TARGET_FILE:d4r_nvngx_windows>" --interop-mode indirect --iterations 32)
|
||||||
set_tests_properties(d3d12_command_backend PROPERTIES TIMEOUT 120 LABELS "hardware;d3d12;command_lists;lifetime")
|
set_tests_properties(d3d12_command_backend PROPERTIES TIMEOUT 120 LABELS "hardware;d3d12;command_lists;lifetime")
|
||||||
|
add_test(NAME d3d12_command_initial_pso COMMAND d4r_d3d12_command_probe
|
||||||
|
--hip-root "${D4R_HIP_ROOT}" --module "$<TARGET_FILE:d4r_nvngx_windows>" --interop-mode initial-pso --iterations 32)
|
||||||
|
set_tests_properties(d3d12_command_initial_pso PROPERTIES TIMEOUT 120 LABELS "hardware;d3d12;command_lists;lifetime")
|
||||||
add_test(NAME d3d12_command_root_reset_warp COMMAND d4r_d3d12_command_probe
|
add_test(NAME d3d12_command_root_reset_warp COMMAND d4r_d3d12_command_probe
|
||||||
--hip-root "${D4R_HIP_ROOT}" --module "$<TARGET_FILE:d4r_nvngx_windows>" --interop-mode indirect-root-reset --iterations 32)
|
--hip-root "${D4R_HIP_ROOT}" --module "$<TARGET_FILE:d4r_nvngx_windows>" --interop-mode indirect-root-reset --iterations 32)
|
||||||
set_tests_properties(d3d12_command_root_reset_warp PROPERTIES TIMEOUT 120 LABELS "software;d3d12;command_lists;lifetime"
|
set_tests_properties(d3d12_command_root_reset_warp PROPERTIES TIMEOUT 120 LABELS "software;d3d12;command_lists;lifetime"
|
||||||
|
|||||||
@@ -38,6 +38,44 @@ Do not integrate NGX until the integer PTX workload is stable on the real GPU.
|
|||||||
| M8: standalone Windows D3D12 NGX harness | PASS for ordinary recorded EvaluateFeature and explicit boundaries: K/M, four frames each, no shim CPU image copies; both bit-exact against explicit boundary baselines |
|
| M8: standalone Windows D3D12 NGX harness | PASS for ordinary recorded EvaluateFeature and explicit boundaries: K/M, four frames each, no shim CPU image copies; both bit-exact against explicit boundary baselines |
|
||||||
| M9: OptiScaler integration, profiling, installation | Pending |
|
| M9: OptiScaler integration, profiling, installation | Pending |
|
||||||
|
|
||||||
|
## Initial PSO and enhanced texture layouts (2026-10-01)
|
||||||
|
|
||||||
|
The backend now captures the initial PSO supplied to public CreateCommandList,
|
||||||
|
in addition to Reset and SetPipelineState. Its suffix can dispatch without
|
||||||
|
rebinding that PSO. The public foundation probe's `initial-pso` mode passes
|
||||||
|
32 native RX 9070 XT iterations; the WARP diagnostic passes too. The runtime
|
||||||
|
now installs 81 documented method hooks, including CreateCommandList.
|
||||||
|
|
||||||
|
Resource tracking distinguishes legacy states from enhanced texture layouts
|
||||||
|
for mip/array/plane zero. Barriers on unrelated subresources do not overwrite
|
||||||
|
that state. An unfinished split barrier on an NGX texture explicitly rejects
|
||||||
|
Evaluate. The queued snapshot owns the layout/access metadata. Native interop
|
||||||
|
uses CommandList7 texture barriers to enter COPY_SOURCE/COPY_DEST and restore
|
||||||
|
the exact enhanced layout and access class; it does not reinterpret enhanced
|
||||||
|
layouts as legacy states. Legacy texture copies also affect only subresource
|
||||||
|
zero. Shared linear buffers continue to use their own legacy COMMON/copy states.
|
||||||
|
This follows [Microsoft's enhanced barrier interoperability rules](https://microsoft.github.io/DirectX-Specs/d3d/D3D12EnhancedBarriers.html).
|
||||||
|
|
||||||
|
`d3d12_gpu_enhanced_formats` independently tests all nineteen storage/plane
|
||||||
|
cases with a D3D12 enhanced producer and consumer. Full build and CTest pass
|
||||||
|
16/16 gates (`enhanced-final-ctest.log`, fifteen hardware and one WARP).
|
||||||
|
`d3d12-m-enhanced-packed.zip` and `d3d12-k-enhanced-packed.zip` each pass four
|
||||||
|
recorded NGX frames with their complete native transformer. Enhanced snapshot
|
||||||
|
logs report shader-resource layout 21 and unordered-access layout 20. All
|
||||||
|
four RGB images in both runs exactly match their independently quantised
|
||||||
|
FP16 baselines, max absolute/relative error 0. Frame age and shim CPU image
|
||||||
|
copy counts remain zero. Add `-BarrierMode enhanced` to the packed-run command
|
||||||
|
below to reproduce. The explicit harness can also supply layout metadata.
|
||||||
|
|
||||||
|
Tracking currently observes the evaluated list's barriers. A texture whose
|
||||||
|
state was established only in a different list uses the caller-supplied state
|
||||||
|
or the legacy NGX default; queue-wide state inheritance remains an integration
|
||||||
|
gate. Unknown pre-initialization indirect signatures are still rejected.
|
||||||
|
OptiScaler's default restore hotfixes are false; integration will keep
|
||||||
|
RestoreComputeSignature, RestoreGraphicSignature and ExtendedStateRestore
|
||||||
|
false because their original-method trampolines can bypass logical-list routing.
|
||||||
|
Actual OptiScaler execution remains untested; no game files have been changed.
|
||||||
|
|
||||||
## Native GPU resource-format conversion (2026-10-01)
|
## Native GPU resource-format conversion (2026-10-01)
|
||||||
|
|
||||||
`pixel_convert_gfx1201.hsaco` converts imported D3D12 copy footprints to NGX's
|
`pixel_convert_gfx1201.hsaco` converts imported D3D12 copy footprints to NGX's
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ param(
|
|||||||
[switch]$DebugLayer,
|
[switch]$DebugLayer,
|
||||||
[switch]$Warp,
|
[switch]$Warp,
|
||||||
[switch]$NoHip,
|
[switch]$NoHip,
|
||||||
[ValidateSet('basic','indirect','indirect-root-reset')][string]$Mode = 'indirect',
|
[ValidateSet('basic','indirect','indirect-root-reset','initial-pso')][string]$Mode = 'indirect',
|
||||||
[string]$OutputDirectory = 'test-results/d3d12-command-development'
|
[string]$OutputDirectory = 'test-results/d3d12-command-development'
|
||||||
)
|
)
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ param(
|
|||||||
[switch]$RequireNativeNetwork,
|
[switch]$RequireNativeNetwork,
|
||||||
[switch]$CommandListBackend,
|
[switch]$CommandListBackend,
|
||||||
[ValidateSet('baseline','packed','unorm')][string]$PixelProfile = 'baseline',
|
[ValidateSet('baseline','packed','unorm')][string]$PixelProfile = 'baseline',
|
||||||
|
[ValidateSet('legacy','enhanced')][string]$BarrierMode = 'legacy',
|
||||||
[int]$Iterations = 32,
|
[int]$Iterations = 32,
|
||||||
[int]$TimeoutSeconds = 180
|
[int]$TimeoutSeconds = 180
|
||||||
)
|
)
|
||||||
@@ -258,7 +259,7 @@ try {
|
|||||||
$localShim = Join-Path $ngxRuntimeDirectory 'd4r_nvngx.dll'
|
$localShim = Join-Path $ngxRuntimeDirectory 'd4r_nvngx.dll'
|
||||||
Copy-Item -LiteralPath (Join-Path $bin 'd4r_nvngx.dll') -Destination $localShim
|
Copy-Item -LiteralPath (Join-Path $bin 'd4r_nvngx.dll') -Destination $localShim
|
||||||
Copy-Item -LiteralPath (Join-Path $bin 'pixel_convert_gfx1201.hsaco') -Destination $ngxRuntimeDirectory
|
Copy-Item -LiteralPath (Join-Path $bin 'pixel_convert_gfx1201.hsaco') -Destination $ngxRuntimeDirectory
|
||||||
$ngxArguments += @('--module', $localShim, '--pixel-profile', $PixelProfile)
|
$ngxArguments += @('--module', $localShim, '--pixel-profile', $PixelProfile, '--barrier-mode', $BarrierMode)
|
||||||
if ($CommandListBackend) { $ngxArguments += @('--interop-mode', 'command-list') }
|
if ($CommandListBackend) { $ngxArguments += @('--interop-mode', 'command-list') }
|
||||||
}
|
}
|
||||||
$ngxName = if ($NgxMode -eq 'evaluate') { "ngx-evaluate-preset-$Preset" } elseif ($NgxMode -eq 'd3d12') { "d3d12-evaluate-preset-$Preset" } else { 'ngx-init' }
|
$ngxName = if ($NgxMode -eq 'evaluate') { "ngx-evaluate-preset-$Preset" } elseif ($NgxMode -eq 'd3d12') { "d3d12-evaluate-preset-$Preset" } else { 'ngx-init' }
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ struct Recording {
|
|||||||
std::vector<Segment> segments;
|
std::vector<Segment> segments;
|
||||||
std::vector<State> state;
|
std::vector<State> state;
|
||||||
std::vector<Event> events;
|
std::vector<Event> events;
|
||||||
std::unordered_map<ID3D12Resource*, D3D12_RESOURCE_STATES> resource_states;
|
std::unordered_map<ID3D12Resource*, ResourceAccess> resource_states;
|
||||||
unsigned active_queries = 0;
|
unsigned active_queries = 0;
|
||||||
bool render_pass = false, predication = false, indirect_state_unknown = false, closed = false;
|
bool render_pass = false, predication = false, indirect_state_unknown = false, closed = false;
|
||||||
explicit Recording(ID3D12GraphicsCommandList* list) : original(list) {}
|
explicit Recording(ID3D12GraphicsCommandList* list) : original(list) {}
|
||||||
@@ -91,6 +91,31 @@ void attach_method(void* target, void* replacement, void** original, const char*
|
|||||||
static constexpr GUID signature_description_tag = {0xbdda6148,0x46f0,0x4d82,{0xa1,0x90,0x08,0x47,0x7e,0xda,0x32,0x12}};
|
static constexpr GUID signature_description_tag = {0xbdda6148,0x46f0,0x4d82,{0xa1,0x90,0x08,0x47,0x7e,0xda,0x32,0x12}};
|
||||||
using SignatureFn = HRESULT(STDMETHODCALLTYPE*)(ID3D12Device*, const D3D12_COMMAND_SIGNATURE_DESC*, ID3D12RootSignature*, REFIID, void**);
|
using SignatureFn = HRESULT(STDMETHODCALLTYPE*)(ID3D12Device*, const D3D12_COMMAND_SIGNATURE_DESC*, ID3D12RootSignature*, REFIID, void**);
|
||||||
SignatureFn original_signature = nullptr;
|
SignatureFn original_signature = nullptr;
|
||||||
|
using CreateListFn = HRESULT(STDMETHODCALLTYPE*)(ID3D12Device*, UINT, D3D12_COMMAND_LIST_TYPE,
|
||||||
|
ID3D12CommandAllocator*, ID3D12PipelineState*, REFIID, void**);
|
||||||
|
CreateListFn original_create_list = nullptr;
|
||||||
|
HRESULT STDMETHODCALLTYPE hook_create_list(ID3D12Device* device, UINT node, D3D12_COMMAND_LIST_TYPE type,
|
||||||
|
ID3D12CommandAllocator* allocator, ID3D12PipelineState* initial, REFIID iid, void** out) {
|
||||||
|
const auto result = original_create_list(device, node, type, allocator, initial, iid, out);
|
||||||
|
if (!internal && SUCCEEDED(result) && out && *out) try {
|
||||||
|
ComPtr<ID3D12GraphicsCommandList> list;
|
||||||
|
if (SUCCEEDED(static_cast<IUnknown*>(*out)->QueryInterface(IID_PPV_ARGS(list.GetAddressOf())))) {
|
||||||
|
auto recording = get_recording(list.Get());
|
||||||
|
std::lock_guard<std::recursive_mutex> lock(recording->mutex);
|
||||||
|
auto pipeline = retain(initial);
|
||||||
|
if (pipeline) recording->state.emplace_back([pipeline](ID3D12GraphicsCommandList* target) {
|
||||||
|
original_SetPipelineState(target, pipeline.Get());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (const std::exception& failure) {
|
||||||
|
// A public Create must retain its result even if tracking runs out of
|
||||||
|
// memory. A later split must fail explicitly instead of replaying an
|
||||||
|
// incomplete initial state.
|
||||||
|
{ std::lock_guard<std::mutex> lock(error_mutex); last_error = failure.what(); }
|
||||||
|
std::fprintf(stderr, "D4R_CREATE_LIST_TRACK_FAILURE %s\n", failure.what());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
HRESULT STDMETHODCALLTYPE hook_signature(ID3D12Device* device, const D3D12_COMMAND_SIGNATURE_DESC* desc, ID3D12RootSignature* root, REFIID iid, void** out) {
|
HRESULT STDMETHODCALLTYPE hook_signature(ID3D12Device* device, const D3D12_COMMAND_SIGNATURE_DESC* desc, ID3D12RootSignature* root, REFIID iid, void** out) {
|
||||||
const auto result = original_signature(device, desc, root, iid, out);
|
const auto result = original_signature(device, desc, root, iid, out);
|
||||||
if (SUCCEEDED(result) && out && *out && desc && desc->NumArgumentDescs <= 4096) try {
|
if (SUCCEEDED(result) && out && *out && desc && desc->NumArgumentDescs <= 4096) try {
|
||||||
@@ -160,14 +185,28 @@ void STDMETHODCALLTYPE hook_ClearState(ID3D12GraphicsCommandList* self, ID3D12Pi
|
|||||||
void STDMETHODCALLTYPE hook_ResourceBarrier(ID3D12GraphicsCommandList* self, UINT barrier_count, const D3D12_RESOURCE_BARRIER* barriers) {
|
void STDMETHODCALLTYPE hook_ResourceBarrier(ID3D12GraphicsCommandList* self, UINT barrier_count, const D3D12_RESOURCE_BARRIER* barriers) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
if (access.recording) for (UINT i = 0; i < barrier_count; ++i)
|
if (access.recording) for (UINT i = 0; i < barrier_count; ++i)
|
||||||
if (barriers[i].Type == D3D12_RESOURCE_BARRIER_TYPE_TRANSITION && barriers[i].Flags != D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY)
|
if (barriers[i].Type == D3D12_RESOURCE_BARRIER_TYPE_TRANSITION &&
|
||||||
access.recording->resource_states[barriers[i].Transition.pResource] = barriers[i].Transition.StateAfter;
|
(barriers[i].Transition.Subresource == 0 || barriers[i].Transition.Subresource == D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES)) {
|
||||||
|
auto& state = access.recording->resource_states[barriers[i].Transition.pResource];
|
||||||
|
state = ResourceAccess(barriers[i].Transition.StateAfter);
|
||||||
|
state.pending_split = barriers[i].Flags == D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY;
|
||||||
|
}
|
||||||
original_ResourceBarrier(access.target(), barrier_count, barriers);
|
original_ResourceBarrier(access.target(), barrier_count, barriers);
|
||||||
}
|
}
|
||||||
void STDMETHODCALLTYPE hook_Barrier(ID3D12GraphicsCommandList* self, UINT32 barrier_groups_count, const D3D12_BARRIER_GROUP* barrier_groups) {
|
void STDMETHODCALLTYPE hook_Barrier(ID3D12GraphicsCommandList* self, UINT32 barrier_groups_count, const D3D12_BARRIER_GROUP* barrier_groups) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
|
if (access.recording) for (UINT32 g = 0; g < barrier_groups_count; ++g) if (barrier_groups[g].Type == D3D12_BARRIER_TYPE_TEXTURE)
|
||||||
|
for (UINT32 b = 0; b < barrier_groups[g].NumBarriers; ++b) {
|
||||||
|
const auto& barrier = barrier_groups[g].pTextureBarriers[b]; const auto& range = barrier.Subresources;
|
||||||
|
const bool containsZero = range.NumMipLevels == 0 ? (range.IndexOrFirstMipLevel == 0 || range.IndexOrFirstMipLevel == UINT32_MAX) :
|
||||||
|
range.IndexOrFirstMipLevel == 0 && range.FirstArraySlice == 0 && range.FirstPlane == 0;
|
||||||
|
if (containsZero) {
|
||||||
|
auto& state = access.recording->resource_states[barrier.pResource]; state.enhanced = true;
|
||||||
|
state.layout = barrier.LayoutAfter; state.access = barrier.AccessAfter; state.sync = barrier.SyncAfter;
|
||||||
|
state.pending_split = barrier.SyncAfter == D3D12_BARRIER_SYNC_SPLIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
original_Barrier(access.target(), barrier_groups_count, barrier_groups);
|
original_Barrier(access.target(), barrier_groups_count, barrier_groups);
|
||||||
// Enhanced layout-to-legacy conversion is an explicit subsequent gate.
|
|
||||||
}
|
}
|
||||||
void STDMETHODCALLTYPE hook_BeginEvent(ID3D12GraphicsCommandList* self, UINT metadata, const void* data, UINT size) {
|
void STDMETHODCALLTYPE hook_BeginEvent(ID3D12GraphicsCommandList* self, UINT metadata, const void* data, UINT size) {
|
||||||
Access access(self);
|
Access access(self);
|
||||||
@@ -319,6 +358,11 @@ InternalScope::~InternalScope() { internal = previous; }
|
|||||||
std::string error() { std::lock_guard<std::mutex> lock(error_mutex); return last_error; }
|
std::string error() { std::lock_guard<std::mutex> lock(error_mutex); return last_error; }
|
||||||
size_t live_recordings() { std::lock_guard<std::mutex> lock(map_mutex); return recordings.size(); }
|
size_t live_recordings() { std::lock_guard<std::mutex> lock(map_mutex); return recordings.size(); }
|
||||||
D3D12_RESOURCE_STATES resource_state(ID3D12GraphicsCommandList* list, ID3D12Resource* resource, D3D12_RESOURCE_STATES fallback) {
|
D3D12_RESOURCE_STATES resource_state(ID3D12GraphicsCommandList* list, ID3D12Resource* resource, D3D12_RESOURCE_STATES fallback) {
|
||||||
|
const auto state = resource_access(list, resource, ResourceAccess(fallback));
|
||||||
|
if (state.enhanced) throw std::runtime_error("Enhanced texture layout cannot be treated as a legacy state");
|
||||||
|
return state.legacy;
|
||||||
|
}
|
||||||
|
ResourceAccess resource_access(ID3D12GraphicsCommandList* list, ID3D12Resource* resource, ResourceAccess fallback) {
|
||||||
auto recording = get_recording(list, false);
|
auto recording = get_recording(list, false);
|
||||||
if (!recording) return fallback;
|
if (!recording) return fallback;
|
||||||
std::lock_guard<std::recursive_mutex> lock(recording->mutex);
|
std::lock_guard<std::recursive_mutex> lock(recording->mutex);
|
||||||
@@ -362,6 +406,7 @@ void install(ID3D12Device* device) {
|
|||||||
// CopyTileMappings precede ExecuteCommandLists in the public SDK.
|
// CopyTileMappings precede ExecuteCommandLists in the public SDK.
|
||||||
attach_method(queueTable[10], reinterpret_cast<void*>(hook_execute), reinterpret_cast<void**>(&original_execute), "ExecuteCommandLists");
|
attach_method(queueTable[10], reinterpret_cast<void*>(hook_execute), reinterpret_cast<void**>(&original_execute), "ExecuteCommandLists");
|
||||||
auto deviceTable = *reinterpret_cast<void***>(device);
|
auto deviceTable = *reinterpret_cast<void***>(device);
|
||||||
|
attach_method(deviceTable[device_command_list_slot], reinterpret_cast<void*>(hook_create_list), reinterpret_cast<void**>(&original_create_list), "CreateCommandList");
|
||||||
attach_method(deviceTable[device_signature_slot], reinterpret_cast<void*>(hook_signature), reinterpret_cast<void**>(&original_signature), "CreateCommandSignature");
|
attach_method(deviceTable[device_signature_slot], reinterpret_cast<void*>(hook_signature), reinterpret_cast<void**>(&original_signature), "CreateCommandSignature");
|
||||||
for (const auto& hook : attached) {
|
for (const auto& hook : attached) {
|
||||||
const auto result = MH_QueueEnableHook(hook.target);
|
const auto result = MH_QueueEnableHook(hook.target);
|
||||||
|
|||||||
@@ -699,3 +699,4 @@ static void attach_recording_methods(void** table, unsigned version) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static constexpr unsigned device_signature_slot = 41;
|
static constexpr unsigned device_signature_slot = 41;
|
||||||
|
static constexpr unsigned device_command_list_slot = 12;
|
||||||
@@ -13,6 +13,7 @@ void record_boundary(ID3D12GraphicsCommandList* list, Boundary callback);
|
|||||||
std::string error();
|
std::string error();
|
||||||
size_t live_recordings();
|
size_t live_recordings();
|
||||||
D3D12_RESOURCE_STATES resource_state(ID3D12GraphicsCommandList* list, ID3D12Resource* resource, D3D12_RESOURCE_STATES fallback);
|
D3D12_RESOURCE_STATES resource_state(ID3D12GraphicsCommandList* list, ID3D12Resource* resource, D3D12_RESOURCE_STATES fallback);
|
||||||
|
ResourceAccess resource_access(ID3D12GraphicsCommandList* list, ID3D12Resource* resource, ResourceAccess fallback);
|
||||||
// Internal copies and callback submissions must bypass logical list routing.
|
// Internal copies and callback submissions must bypass logical list routing.
|
||||||
struct InternalScope {
|
struct InternalScope {
|
||||||
bool previous;
|
bool previous;
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ void drain(ID3D12Device* device, ID3D12CommandQueue* queue) {
|
|||||||
struct NativeList {
|
struct NativeList {
|
||||||
ComPtr<ID3D12CommandAllocator> allocator;
|
ComPtr<ID3D12CommandAllocator> allocator;
|
||||||
ComPtr<ID3D12GraphicsCommandList> list;
|
ComPtr<ID3D12GraphicsCommandList> list;
|
||||||
explicit NativeList(ID3D12Device* device) {
|
explicit NativeList(ID3D12Device* device, ID3D12PipelineState* initial = nullptr) {
|
||||||
dx(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(allocator.GetAddressOf())), "Probe allocator");
|
dx(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(allocator.GetAddressOf())), "Probe allocator");
|
||||||
dx(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocator.Get(), nullptr, IID_PPV_ARGS(list.GetAddressOf())), "Probe command list");
|
dx(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocator.Get(), initial, IID_PPV_ARGS(list.GetAddressOf())), "Probe command list");
|
||||||
}
|
}
|
||||||
void submit(ID3D12Device* device, ID3D12CommandQueue* queue) {
|
void submit(ID3D12Device* device, ID3D12CommandQueue* queue) {
|
||||||
dx(list->Close(), "Close probe list"); ID3D12CommandList* lists[] = {list.Get()};
|
dx(list->Close(), "Close probe list"); ID3D12CommandList* lists[] = {list.Get()};
|
||||||
@@ -164,9 +164,10 @@ int main(int argc, char** argv) {
|
|||||||
auto record = shim.symbol<Record>("d4r_D3D12_RecordDiagnosticBoundary");
|
auto record = shim.symbol<Record>("d4r_D3D12_RecordDiagnosticBoundary");
|
||||||
auto live = shim.symbol<Live>("d4r_D3D12_LiveRecordings");
|
auto live = shim.symbol<Live>("d4r_D3D12_LiveRecordings");
|
||||||
const bool root_indirect = args.interop_mode == "indirect-root-reset";
|
const bool root_indirect = args.interop_mode == "indirect-root-reset";
|
||||||
const bool indirect_enabled = args.interop_mode != "basic";
|
const bool initial_pso = args.interop_mode == "initial-pso";
|
||||||
if (args.interop_mode != "direct" && args.interop_mode != "basic" && args.interop_mode != "indirect" && !root_indirect)
|
const bool indirect_enabled = args.interop_mode == "indirect" || root_indirect;
|
||||||
throw std::runtime_error("Command probe mode must be basic, indirect, or indirect-root-reset");
|
if (args.interop_mode != "direct" && args.interop_mode != "basic" && args.interop_mode != "indirect" && !root_indirect && !initial_pso)
|
||||||
|
throw std::runtime_error("Command probe mode must be basic, indirect, indirect-root-reset or initial-pso");
|
||||||
D3D12_INDIRECT_ARGUMENT_DESC arguments[2]{};
|
D3D12_INDIRECT_ARGUMENT_DESC arguments[2]{};
|
||||||
arguments[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
|
arguments[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
|
||||||
arguments[0].Constant.RootParameterIndex = 2;
|
arguments[0].Constant.RootParameterIndex = 2;
|
||||||
@@ -202,11 +203,11 @@ int main(int argc, char** argv) {
|
|||||||
input->GetGPUVirtualAddress(), output->GetGPUVirtualAddress(), indirect_buffer->GetGPUVirtualAddress());
|
input->GetGPUVirtualAddress(), output->GetGPUVirtualAddress(), indirect_buffer->GetGPUVirtualAddress());
|
||||||
upload(first.Get(), 17, 10); upload(second.Get(), 25, 100);
|
upload(first.Get(), 17, 10); upload(second.Get(), 25, 100);
|
||||||
{
|
{
|
||||||
NativeList a(device.Get()), b(device.Get()), c(device.Get());
|
NativeList a(device.Get()), b(device.Get(), initial_pso ? pso.Get() : nullptr), c(device.Get());
|
||||||
a.list->CopyResource(input.Get(), first.Get());
|
a.list->CopyResource(input.Get(), first.Get());
|
||||||
transition(a.list.Get(), input.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
transition(a.list.Get(), input.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
||||||
dx(a.list->Close(), "Close predecessor A");
|
dx(a.list->Close(), "Close predecessor A");
|
||||||
b.list->SetComputeRootSignature(root.Get()); b.list->SetPipelineState(pso.Get());
|
b.list->SetComputeRootSignature(root.Get()); if (!initial_pso) b.list->SetPipelineState(pso.Get());
|
||||||
b.list->SetComputeRootUnorderedAccessView(0, output->GetGPUVirtualAddress());
|
b.list->SetComputeRootUnorderedAccessView(0, output->GetGPUVirtualAddress());
|
||||||
b.list->SetComputeRootShaderResourceView(1, input->GetGPUVirtualAddress());
|
b.list->SetComputeRootShaderResourceView(1, input->GetGPUVirtualAddress());
|
||||||
uint32_t temporary = seed;
|
uint32_t temporary = seed;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ int main(int argc, char** argv) {
|
|||||||
const std::filesystem::path directory(diagDir ? wide(diagDir) : std::filesystem::current_path().wstring());
|
const std::filesystem::path directory(diagDir ? wide(diagDir) : std::filesystem::current_path().wstring());
|
||||||
std::filesystem::create_directories(directory);
|
std::filesystem::create_directories(directory);
|
||||||
const bool commandBackend = args.interop_mode == "command-list";
|
const bool commandBackend = args.interop_mode == "command-list";
|
||||||
|
const bool enhanced = args.barrier_mode == "enhanced";
|
||||||
if (args.interop_mode == "images" && args.pixel_profile != "baseline") throw std::runtime_error("Raw CUDA image diagnostic requires baseline formats");
|
if (args.interop_mode == "images" && args.pixel_profile != "baseline") throw std::runtime_error("Raw CUDA image diagnostic requires baseline formats");
|
||||||
std::printf("D3D12_PIXEL_PROFILE %s\n", args.pixel_profile.c_str());
|
std::printf("D3D12_PIXEL_PROFILE %s\n", args.pixel_profile.c_str());
|
||||||
if (commandBackend && _putenv_s("D4R_D3D12_COMMAND_BACKEND", "1")) throw std::runtime_error("Cannot enable command backend");
|
if (commandBackend && _putenv_s("D4R_D3D12_COMMAND_BACKEND", "1")) throw std::runtime_error("Cannot enable command backend");
|
||||||
@@ -38,6 +39,17 @@ int main(int argc, char** argv) {
|
|||||||
if (!found) throw std::runtime_error("HIP adapter missing from DXGI");
|
if (!found) throw std::runtime_error("HIP adapter missing from DXGI");
|
||||||
ComPtr<ID3D12Device> device;
|
ComPtr<ID3D12Device> device;
|
||||||
dx(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(device.GetAddressOf())), "D3D12CreateDevice");
|
dx(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(device.GetAddressOf())), "D3D12CreateDevice");
|
||||||
|
if (enhanced) { D3D12_FEATURE_DATA_D3D12_OPTIONS12 support{}; dx(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS12, &support, sizeof(support)), "Enhanced barrier support"); if (!support.EnhancedBarriersSupported) throw std::runtime_error("Enhanced barriers unavailable"); }
|
||||||
|
auto enhancedBarrier = [&](ID3D12GraphicsCommandList* command, ID3D12Resource* texture, unsigned plane, bool initial) {
|
||||||
|
ComPtr<ID3D12GraphicsCommandList7> newer; dx(command->QueryInterface(IID_PPV_ARGS(newer.GetAddressOf())), "Harness enhanced list");
|
||||||
|
D3D12_TEXTURE_BARRIER barrier{}; barrier.pResource = texture;
|
||||||
|
barrier.LayoutAfter = plane == 3 ? D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS : D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE;
|
||||||
|
barrier.LayoutBefore = initial ? D3D12_BARRIER_LAYOUT_COMMON : barrier.LayoutAfter;
|
||||||
|
barrier.AccessAfter = plane == 3 ? D3D12_BARRIER_ACCESS_UNORDERED_ACCESS : D3D12_BARRIER_ACCESS_SHADER_RESOURCE;
|
||||||
|
barrier.AccessBefore = initial ? D3D12_BARRIER_ACCESS_COMMON : barrier.AccessAfter;
|
||||||
|
barrier.SyncBefore = barrier.SyncAfter = D3D12_BARRIER_SYNC_ALL;
|
||||||
|
D3D12_BARRIER_GROUP group{}; group.Type = D3D12_BARRIER_TYPE_TEXTURE; group.NumBarriers = 1; group.pTextureBarriers = &barrier; newer->Barrier(1, &group);
|
||||||
|
};
|
||||||
ComPtr<ID3D12CommandQueue> queue;
|
ComPtr<ID3D12CommandQueue> queue;
|
||||||
D3D12_COMMAND_QUEUE_DESC qd{}; qd.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
D3D12_COMMAND_QUEUE_DESC qd{}; qd.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||||
dx(device->CreateCommandQueue(&qd, IID_PPV_ARGS(queue.GetAddressOf())), "CreateCommandQueue");
|
dx(device->CreateCommandQueue(&qd, IID_PPV_ARGS(queue.GetAddressOf())), "CreateCommandQueue");
|
||||||
@@ -104,7 +116,8 @@ int main(int argc, char** argv) {
|
|||||||
dst.pResource = texture.image.Get(); dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
dst.pResource = texture.image.Get(); dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||||
list->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
|
list->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
|
||||||
transition(list.Get(), texture.image.Get(), D3D12_RESOURCE_STATE_COPY_DEST,
|
transition(list.Get(), texture.image.Get(), D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
i == 3 ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
enhanced ? D3D12_RESOURCE_STATE_COMMON : i == 3 ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
||||||
|
if (enhanced) enhancedBarrier(list.Get(), texture.image.Get(), i, true);
|
||||||
}
|
}
|
||||||
dx(list->Close(), "Close(synthetic producers)"); ID3D12CommandList* producer[] = {list.Get()};
|
dx(list->Close(), "Close(synthetic producers)"); ID3D12CommandList* producer[] = {list.Get()};
|
||||||
if (!commandBackend) { queue->ExecuteCommandLists(1, producer); drain(); }
|
if (!commandBackend) { queue->ExecuteCommandLists(1, producer); drain(); }
|
||||||
@@ -176,6 +189,12 @@ int main(int argc, char** argv) {
|
|||||||
struct FeatureCleanup { Release fn; void* h; ~FeatureCleanup() { (void)fn(h); } } featureCleanup{release, handle};
|
struct FeatureCleanup { Release fn; void* h; ~FeatureCleanup() { (void)fn(h); } } featureCleanup{release, handle};
|
||||||
static const char* names[] = {"Color", "Depth", "MotionVectors", "Output", "ExposureTexture"};
|
static const char* names[] = {"Color", "Depth", "MotionVectors", "Output", "ExposureTexture"};
|
||||||
for (unsigned i = 0; i < 5; ++i) d4r_ngx_set_d3d12_resource(parameters, names[i], textures[i].image.Get());
|
for (unsigned i = 0; i < 5; ++i) d4r_ngx_set_d3d12_resource(parameters, names[i], textures[i].image.Get());
|
||||||
|
if (enhanced && !commandBackend) {
|
||||||
|
const char* states[] = {"D4R.Color.State", "D4R.Depth.State", "D4R.Motion.State", "D4R.Output.State", "D4R.Exposure.State"};
|
||||||
|
for (unsigned i = 0; i < 5; ++i) { const std::string prefix(states[i]); d4r_ngx_set_uint(parameters,(prefix+".Enhanced").c_str(),1);
|
||||||
|
d4r_ngx_set_uint(parameters,(prefix+".Layout").c_str(), i == 3 ? D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS : D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE);
|
||||||
|
d4r_ngx_set_uint(parameters,(prefix+".Access").c_str(), i == 3 ? D3D12_BARRIER_ACCESS_UNORDERED_ACCESS : D3D12_BARRIER_ACCESS_SHADER_RESOURCE); }
|
||||||
|
}
|
||||||
d4r_ngx_set_int(parameters, "Disable.Watermark", 1);
|
d4r_ngx_set_int(parameters, "Disable.Watermark", 1);
|
||||||
auto readback = make_buffer(device.Get(), textures[3].bytes, D3D12_HEAP_TYPE_READBACK, D3D12_HEAP_FLAG_NONE, D3D12_RESOURCE_STATE_COPY_DEST);
|
auto readback = make_buffer(device.Get(), textures[3].bytes, D3D12_HEAP_TYPE_READBACK, D3D12_HEAP_FLAG_NONE, D3D12_RESOURCE_STATE_COPY_DEST);
|
||||||
ComPtr<ID3D12GraphicsCommandList> predecessor;
|
ComPtr<ID3D12GraphicsCommandList> predecessor;
|
||||||
@@ -193,6 +212,7 @@ int main(int argc, char** argv) {
|
|||||||
d4r_ngx_set_int(parameters, "Reset", frame == 0 ? 1 : 0);
|
d4r_ngx_set_int(parameters, "Reset", frame == 0 ? 1 : 0);
|
||||||
if (commandBackend) {
|
if (commandBackend) {
|
||||||
dx(allocator->Reset(), "Reset(game-style allocator)"); dx(list->Reset(allocator.Get(), nullptr), "Reset(game-style list)");
|
dx(allocator->Reset(), "Reset(game-style allocator)"); dx(list->Reset(allocator.Get(), nullptr), "Reset(game-style list)");
|
||||||
|
if (enhanced) for (unsigned i = 0; i < 5; ++i) enhancedBarrier(list.Get(), textures[i].image.Get(), i, false);
|
||||||
using RecordedEvaluate = unsigned(*)(ID3D12GraphicsCommandList*, void*, void*, void*);
|
using RecordedEvaluate = unsigned(*)(ID3D12GraphicsCommandList*, void*, void*, void*);
|
||||||
check(shim.symbol<RecordedEvaluate>("NVSDK_NGX_D3D12_EvaluateFeature")(list.Get(), handle, parameters, nullptr), "D3D12 recorded same-frame Evaluate");
|
check(shim.symbol<RecordedEvaluate>("NVSDK_NGX_D3D12_EvaluateFeature")(list.Get(), handle, parameters, nullptr), "D3D12 recorded same-frame Evaluate");
|
||||||
// The caller may reuse/mutate its parameter object as soon as
|
// The caller may reuse/mutate its parameter object as soon as
|
||||||
@@ -203,12 +223,14 @@ int main(int argc, char** argv) {
|
|||||||
check(shim.symbol<Evaluate>("d4r_D3D12_EvaluateAtBoundary")(queue.Get(), handle, parameters), "D3D12 same-frame Evaluate");
|
check(shim.symbol<Evaluate>("d4r_D3D12_EvaluateAtBoundary")(queue.Get(), handle, parameters), "D3D12 same-frame Evaluate");
|
||||||
dx(allocator->Reset(), "Reset(harness allocator)"); dx(list->Reset(allocator.Get(), nullptr), "Reset(harness list)");
|
dx(allocator->Reset(), "Reset(harness allocator)"); dx(list->Reset(allocator.Get(), nullptr), "Reset(harness list)");
|
||||||
}
|
}
|
||||||
transition(list.Get(), textures[3].image.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
ResourceAccess outputAccess(D3D12_RESOURCE_STATE_UNORDERED_ACCESS); outputAccess.enhanced = enhanced;
|
||||||
|
outputAccess.layout = D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS; outputAccess.access = D3D12_BARRIER_ACCESS_UNORDERED_ACCESS;
|
||||||
|
texture_copy_barrier(list.Get(), textures[3].image.Get(), outputAccess, false, false);
|
||||||
D3D12_TEXTURE_COPY_LOCATION src{}, dst{};
|
D3D12_TEXTURE_COPY_LOCATION src{}, dst{};
|
||||||
src.pResource = textures[3].image.Get(); src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
src.pResource = textures[3].image.Get(); src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||||
dst.pResource = readback.Get(); dst.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; dst.PlacedFootprint = textures[3].footprint;
|
dst.pResource = readback.Get(); dst.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; dst.PlacedFootprint = textures[3].footprint;
|
||||||
list->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
|
list->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
|
||||||
transition(list.Get(), textures[3].image.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
|
texture_copy_barrier(list.Get(), textures[3].image.Get(), outputAccess, false, true);
|
||||||
dx(list->Close(), "Close(verification)");
|
dx(list->Close(), "Close(verification)");
|
||||||
if (commandBackend && frame == 0) {
|
if (commandBackend && frame == 0) {
|
||||||
ID3D12CommandList* batch[] = {predecessor.Get(), list.Get()}; queue->ExecuteCommandLists(2, batch);
|
ID3D12CommandList* batch[] = {predecessor.Get(), list.Get()}; queue->ExecuteCommandLists(2, batch);
|
||||||
@@ -255,8 +277,8 @@ int main(int argc, char** argv) {
|
|||||||
if (variance < 1e-6) throw std::runtime_error("D3D12 output lost the synthetic pattern");
|
if (variance < 1e-6) throw std::runtime_error("D3D12 output lost the synthetic pattern");
|
||||||
}
|
}
|
||||||
loaded_modules();
|
loaded_modules();
|
||||||
std::printf("PASS D3D12_DLSS architecture=gfx1201 preset=%u frames=%u fast_path_cpu_copies=0 frame_age=0 queue_integration=%s\n",
|
std::printf("PASS D3D12_DLSS architecture=gfx1201 preset=%u frames=%u fast_path_cpu_copies=0 frame_age=0 enhanced=%u queue_integration=%s\n",
|
||||||
args.preset, args.iterations, commandBackend ? "recorded_command_list" : "explicit_harness");
|
args.preset, args.iterations, enhanced, commandBackend ? "recorded_command_list" : "explicit_harness");
|
||||||
return 0;
|
return 0;
|
||||||
} catch (const std::exception& error) { std::fprintf(stderr, "FAIL D3D12_DLSS %s\n", error.what()); loaded_modules(); return 4; }
|
} catch (const std::exception& error) { std::fprintf(stderr, "FAIL D3D12_DLSS %s\n", error.what()); loaded_modules(); return 4; }
|
||||||
}
|
}
|
||||||
@@ -65,6 +65,40 @@ inline void transition(ID3D12GraphicsCommandList* list, ID3D12Resource* resource
|
|||||||
barrier.Transition = {resource, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, before, after};
|
barrier.Transition = {resource, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, before, after};
|
||||||
list->ResourceBarrier(1, &barrier);
|
list->ResourceBarrier(1, &barrier);
|
||||||
}
|
}
|
||||||
|
struct ResourceAccess {
|
||||||
|
D3D12_RESOURCE_STATES legacy = D3D12_RESOURCE_STATE_COMMON;
|
||||||
|
bool enhanced = false, pending_split = false;
|
||||||
|
D3D12_BARRIER_LAYOUT layout = D3D12_BARRIER_LAYOUT_COMMON;
|
||||||
|
D3D12_BARRIER_ACCESS access = D3D12_BARRIER_ACCESS_COMMON;
|
||||||
|
D3D12_BARRIER_SYNC sync = D3D12_BARRIER_SYNC_ALL;
|
||||||
|
ResourceAccess() = default;
|
||||||
|
ResourceAccess(D3D12_RESOURCE_STATES state) : legacy(state) {}
|
||||||
|
};
|
||||||
|
inline void texture_copy_barrier(ID3D12GraphicsCommandList* list, ID3D12Resource* texture,
|
||||||
|
const ResourceAccess& original, bool output, bool restore) {
|
||||||
|
if (original.pending_split) throw std::runtime_error("Cannot use a texture inside an unfinished split barrier");
|
||||||
|
if (!original.enhanced) {
|
||||||
|
const auto copy = output ? D3D12_RESOURCE_STATE_COPY_DEST : D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||||
|
if (original.legacy == copy) return;
|
||||||
|
D3D12_RESOURCE_BARRIER barrier{}; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||||
|
barrier.Transition = {texture, 0, restore ? copy : original.legacy, restore ? original.legacy : copy};
|
||||||
|
list->ResourceBarrier(1, &barrier); return;
|
||||||
|
}
|
||||||
|
ComPtr<ID3D12GraphicsCommandList7> newer;
|
||||||
|
dx(list->QueryInterface(IID_PPV_ARGS(newer.GetAddressOf())), "Enhanced interop command list");
|
||||||
|
D3D12_TEXTURE_BARRIER barrier{}; barrier.pResource = texture;
|
||||||
|
barrier.LayoutBefore = restore ? (output ? D3D12_BARRIER_LAYOUT_COPY_DEST : D3D12_BARRIER_LAYOUT_COPY_SOURCE) : original.layout;
|
||||||
|
barrier.LayoutAfter = restore ? original.layout : (output ? D3D12_BARRIER_LAYOUT_COPY_DEST : D3D12_BARRIER_LAYOUT_COPY_SOURCE);
|
||||||
|
barrier.AccessBefore = restore ? (output ? D3D12_BARRIER_ACCESS_COPY_DEST : D3D12_BARRIER_ACCESS_COPY_SOURCE) : original.access;
|
||||||
|
barrier.AccessAfter = restore ? original.access : (output ? D3D12_BARRIER_ACCESS_COPY_DEST : D3D12_BARRIER_ACCESS_COPY_SOURCE);
|
||||||
|
// Interop runs in a separate submitted direct list. ALL is a conservative
|
||||||
|
// synchronization scope for the app's original access class/layout.
|
||||||
|
barrier.SyncBefore = restore ? D3D12_BARRIER_SYNC_COPY : D3D12_BARRIER_SYNC_ALL;
|
||||||
|
barrier.SyncAfter = restore ? D3D12_BARRIER_SYNC_ALL : D3D12_BARRIER_SYNC_COPY;
|
||||||
|
barrier.Subresources.IndexOrFirstMipLevel = 0; // Single subresource 0.
|
||||||
|
D3D12_BARRIER_GROUP group{}; group.Type = D3D12_BARRIER_TYPE_TEXTURE; group.NumBarriers = 1; group.pTextureBarriers = &barrier;
|
||||||
|
newer->Barrier(1, &group);
|
||||||
|
}
|
||||||
|
|
||||||
class SharedPlane {
|
class SharedPlane {
|
||||||
ExternalApi& api_;
|
ExternalApi& api_;
|
||||||
@@ -108,25 +142,25 @@ public:
|
|||||||
}
|
}
|
||||||
SharedPlane(const SharedPlane&) = delete;
|
SharedPlane(const SharedPlane&) = delete;
|
||||||
~SharedPlane() { release(); }
|
~SharedPlane() { release(); }
|
||||||
void copy_input(ID3D12GraphicsCommandList* list, ID3D12Resource* texture, D3D12_RESOURCE_STATES state) {
|
void copy_input(ID3D12GraphicsCommandList* list, ID3D12Resource* texture, ResourceAccess state) {
|
||||||
transition(list, texture, state, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
texture_copy_barrier(list, texture, state, false, false);
|
||||||
transition(list, buffer.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST);
|
transition(list, buffer.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST);
|
||||||
D3D12_TEXTURE_COPY_LOCATION source{}, dest{};
|
D3D12_TEXTURE_COPY_LOCATION source{}, dest{};
|
||||||
source.pResource = texture; source.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
source.pResource = texture; source.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||||
dest.pResource = buffer.Get(); dest.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; dest.PlacedFootprint = footprint;
|
dest.pResource = buffer.Get(); dest.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; dest.PlacedFootprint = footprint;
|
||||||
list->CopyTextureRegion(&dest, 0, 0, 0, &source, nullptr);
|
list->CopyTextureRegion(&dest, 0, 0, 0, &source, nullptr);
|
||||||
transition(list, buffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COMMON);
|
transition(list, buffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COMMON);
|
||||||
transition(list, texture, D3D12_RESOURCE_STATE_COPY_SOURCE, state);
|
texture_copy_barrier(list, texture, state, false, true);
|
||||||
}
|
}
|
||||||
void copy_output(ID3D12GraphicsCommandList* list, ID3D12Resource* texture, D3D12_RESOURCE_STATES state) {
|
void copy_output(ID3D12GraphicsCommandList* list, ID3D12Resource* texture, ResourceAccess state) {
|
||||||
transition(list, texture, state, D3D12_RESOURCE_STATE_COPY_DEST);
|
texture_copy_barrier(list, texture, state, true, false);
|
||||||
transition(list, buffer.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
transition(list, buffer.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
||||||
D3D12_TEXTURE_COPY_LOCATION source{}, dest{};
|
D3D12_TEXTURE_COPY_LOCATION source{}, dest{};
|
||||||
source.pResource = buffer.Get(); source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; source.PlacedFootprint = footprint;
|
source.pResource = buffer.Get(); source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; source.PlacedFootprint = footprint;
|
||||||
dest.pResource = texture; dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
dest.pResource = texture; dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||||
list->CopyTextureRegion(&dest, 0, 0, 0, &source, nullptr);
|
list->CopyTextureRegion(&dest, 0, 0, 0, &source, nullptr);
|
||||||
transition(list, buffer.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COMMON);
|
transition(list, buffer.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COMMON);
|
||||||
transition(list, texture, D3D12_RESOURCE_STATE_COPY_DEST, state);
|
texture_copy_barrier(list, texture, state, true, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,17 @@ ComPtr<ID3D12Resource> uav_buffer(ID3D12Device* device) {
|
|||||||
dx(device->CreateCommittedResource(&heap, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
|
dx(device->CreateCommittedResource(&heap, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
|
||||||
nullptr, IID_PPV_ARGS(result.GetAddressOf())), "Pixel reference buffer"); return result;
|
nullptr, IID_PPV_ARGS(result.GetAddressOf())), "Pixel reference buffer"); return result;
|
||||||
}
|
}
|
||||||
|
ResourceAccess shader_access() {
|
||||||
|
ResourceAccess result; result.enhanced = true; result.layout = D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE;
|
||||||
|
result.access = D3D12_BARRIER_ACCESS_SHADER_RESOURCE; return result;
|
||||||
|
}
|
||||||
|
void native_layout(ID3D12GraphicsCommandList* list, ID3D12Resource* texture, D3D12_BARRIER_LAYOUT before, D3D12_BARRIER_LAYOUT after,
|
||||||
|
D3D12_BARRIER_ACCESS accessBefore, D3D12_BARRIER_ACCESS accessAfter) {
|
||||||
|
ComPtr<ID3D12GraphicsCommandList7> newer; dx(list->QueryInterface(IID_PPV_ARGS(newer.GetAddressOf())), "Probe enhanced list");
|
||||||
|
D3D12_TEXTURE_BARRIER barrier{}; barrier.pResource = texture; barrier.LayoutBefore = before; barrier.LayoutAfter = after;
|
||||||
|
barrier.AccessBefore = accessBefore; barrier.AccessAfter = accessAfter; barrier.SyncBefore = barrier.SyncAfter = D3D12_BARRIER_SYNC_ALL;
|
||||||
|
D3D12_BARRIER_GROUP group{}; group.Type = D3D12_BARRIER_TYPE_TEXTURE; group.NumBarriers = 1; group.pTextureBarriers = &barrier; newer->Barrier(1,&group);
|
||||||
|
}
|
||||||
void fixture(uint8_t* row, unsigned y, PixelSpec spec) {
|
void fixture(uint8_t* row, unsigned y, PixelSpec spec) {
|
||||||
for (unsigned x = 0; x < width; ++x) {
|
for (unsigned x = 0; x < width; ++x) {
|
||||||
unsigned i = x + y * width; auto* p = row + x * spec.bytes;
|
unsigned i = x + y * width; auto* p = row + x * spec.bytes;
|
||||||
@@ -163,6 +174,8 @@ int main(int argc, char** argv) {
|
|||||||
ComPtr<IDXGIAdapter1> adapter;
|
ComPtr<IDXGIAdapter1> adapter;
|
||||||
for (UINT i = 0; ; ++i) { dx(factory->EnumAdapters1(i, adapter.ReleaseAndGetAddressOf()), "Pixel adapter"); DXGI_ADAPTER_DESC1 d{}; dx(adapter->GetDesc1(&d), "Pixel adapter desc"); if (!std::memcmp(&d.AdapterLuid, props.luid, sizeof(LUID))) break; }
|
for (UINT i = 0; ; ++i) { dx(factory->EnumAdapters1(i, adapter.ReleaseAndGetAddressOf()), "Pixel adapter"); DXGI_ADAPTER_DESC1 d{}; dx(adapter->GetDesc1(&d), "Pixel adapter desc"); if (!std::memcmp(&d.AdapterLuid, props.luid, sizeof(LUID))) break; }
|
||||||
ComPtr<ID3D12Device> device; dx(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(device.GetAddressOf())), "Pixel D3D12");
|
ComPtr<ID3D12Device> device; dx(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(device.GetAddressOf())), "Pixel D3D12");
|
||||||
|
const bool enhanced = args.interop_mode == "enhanced";
|
||||||
|
if (enhanced) { D3D12_FEATURE_DATA_D3D12_OPTIONS12 support{}; dx(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS12, &support, sizeof(support)), "Enhanced barrier support"); if (!support.EnhancedBarriersSupported) throw std::runtime_error("Enhanced barriers unsupported"); }
|
||||||
ComPtr<ID3D12CommandQueue> queue; D3D12_COMMAND_QUEUE_DESC qd{}; qd.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; dx(device->CreateCommandQueue(&qd, IID_PPV_ARGS(queue.GetAddressOf())), "Pixel queue");
|
ComPtr<ID3D12CommandQueue> queue; D3D12_COMMAND_QUEUE_DESC qd{}; qd.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; dx(device->CreateCommandQueue(&qd, IID_PPV_ARGS(queue.GetAddressOf())), "Pixel queue");
|
||||||
SharedTimeline timeline(external, device.Get()); Shaders shader(device.Get()); auto reference = uav_buffer(device.Get());
|
SharedTimeline timeline(external, device.Get()); Shaders shader(device.Get()); auto reference = uav_buffer(device.Get());
|
||||||
unsigned verified = 0;
|
unsigned verified = 0;
|
||||||
@@ -173,7 +186,10 @@ int main(int argc, char** argv) {
|
|||||||
void* data = nullptr; D3D12_RANGE noRead{}; dx(upload->Map(0, &noRead, &data), "Pixel fixture upload");
|
void* data = nullptr; D3D12_RANGE noRead{}; dx(upload->Map(0, &noRead, &data), "Pixel fixture upload");
|
||||||
std::memset(data, 0x5a, size_t(shared.bytes)); for (unsigned y = 0; y < height; ++y) fixture(static_cast<uint8_t*>(data) + y * shared.footprint.Footprint.RowPitch, y, spec); upload->Unmap(0, nullptr);
|
std::memset(data, 0x5a, size_t(shared.bytes)); for (unsigned y = 0; y < height; ++y) fixture(static_cast<uint8_t*>(data) + y * shared.footprint.Footprint.RowPitch, y, spec); upload->Unmap(0, nullptr);
|
||||||
{ List list(device.Get()); D3D12_TEXTURE_COPY_LOCATION src{}, dst{}; src.pResource = upload.Get(); src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; src.PlacedFootprint = shared.footprint; dst.pResource = input.Get(); dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
{ List list(device.Get()); D3D12_TEXTURE_COPY_LOCATION src{}, dst{}; src.pResource = upload.Get(); src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; src.PlacedFootprint = shared.footprint; dst.pResource = input.Get(); dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||||
transition(list.list.Get(), input.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST); list.list->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr); transition(list.list.Get(), input.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); shared.copy_input(list.list.Get(), input.Get(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); list.submit(queue.Get(), timeline); }
|
transition(list.list.Get(), input.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST); list.list->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
|
||||||
|
transition(list.list.Get(), input.Get(), D3D12_RESOURCE_STATE_COPY_DEST, enhanced ? D3D12_RESOURCE_STATE_COMMON : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
||||||
|
if (enhanced) native_layout(list.list.Get(),input.Get(),D3D12_BARRIER_LAYOUT_COMMON,D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE,D3D12_BARRIER_ACCESS_COMMON,D3D12_BARRIER_ACCESS_SHADER_RESOURCE);
|
||||||
|
shared.copy_input(list.list.Get(), input.Get(), enhanced ? shader_access() : ResourceAccess(D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)); list.submit(queue.Get(), timeline); }
|
||||||
D3D12_DESCRIPTOR_HEAP_DESC hd{}; hd.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; hd.NumDescriptors = 4; hd.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
D3D12_DESCRIPTOR_HEAP_DESC hd{}; hd.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; hd.NumDescriptors = 4; hd.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||||
ComPtr<ID3D12DescriptorHeap> heap; dx(device->CreateDescriptorHeap(&hd, IID_PPV_ARGS(heap.GetAddressOf())), "Pixel descriptors");
|
ComPtr<ID3D12DescriptorHeap> heap; dx(device->CreateDescriptorHeap(&hd, IID_PPV_ARGS(heap.GetAddressOf())), "Pixel descriptors");
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE cpu{}, initial{}; D3D12_GPU_DESCRIPTOR_HANDLE gpu{};
|
D3D12_CPU_DESCRIPTOR_HANDLE cpu{}, initial{}; D3D12_GPU_DESCRIPTOR_HANDLE gpu{};
|
||||||
@@ -218,7 +234,11 @@ int main(int argc, char** argv) {
|
|||||||
program.convert(true, canonical.data, canonical.pitch, shared.mapped, shared.footprint.Footprint.RowPitch, width, height, spec.storage, 3);
|
program.convert(true, canonical.data, canonical.pitch, shared.mapped, shared.footprint.Footprint.RowPitch, width, height, spec.storage, 3);
|
||||||
cpu.ptr = initial.ptr + stride; srv = {}; srv.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srv.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; srv.Buffer.NumElements = count; srv.Buffer.StructureByteStride = 16; device->CreateShaderResourceView(canonicalUpload.Get(), &srv, cpu);
|
cpu.ptr = initial.ptr + stride; srv = {}; srv.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srv.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; srv.Buffer.NumElements = count; srv.Buffer.StructureByteStride = 16; device->CreateShaderResourceView(canonicalUpload.Get(), &srv, cpu);
|
||||||
cpu.ptr += stride; D3D12_UNORDERED_ACCESS_VIEW_DESC uv{}; uv.Format = encodedFormat; uv.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; device->CreateUnorderedAccessView(encoded.Get(), nullptr, &uv, cpu);
|
cpu.ptr += stride; D3D12_UNORDERED_ACCESS_VIEW_DESC uv{}; uv.Format = encodedFormat; uv.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; device->CreateUnorderedAccessView(encoded.Get(), nullptr, &uv, cpu);
|
||||||
{ List list(device.Get()); transition(list.list.Get(), encoded.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); list.list->SetPipelineState(shader.encode.Get()); list.list->SetComputeRootSignature(shader.root.Get()); ID3D12DescriptorHeap* heaps[] = {heap.Get()}; list.list->SetDescriptorHeaps(1, heaps); auto handle = gpu; handle.ptr += stride; list.list->SetComputeRootDescriptorTable(1, handle); handle.ptr += stride; list.list->SetComputeRootDescriptorTable(2, handle); unsigned constants[] = {width,height,0}; list.list->SetComputeRoot32BitConstants(4,3,constants,0); list.list->Dispatch((count+63)/64,1,1); transition(list.list.Get(), encoded.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); shared.copy_output(list.list.Get(), actualTexture.Get(), D3D12_RESOURCE_STATE_COMMON); transition(list.list.Get(), actualTexture.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); list.submit(queue.Get(),timeline); }
|
{ List list(device.Get()); transition(list.list.Get(), encoded.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); list.list->SetPipelineState(shader.encode.Get()); list.list->SetComputeRootSignature(shader.root.Get()); ID3D12DescriptorHeap* heaps[] = {heap.Get()}; list.list->SetDescriptorHeaps(1, heaps); auto handle = gpu; handle.ptr += stride; list.list->SetComputeRootDescriptorTable(1, handle); handle.ptr += stride; list.list->SetComputeRootDescriptorTable(2, handle); unsigned constants[] = {width,height,0}; list.list->SetComputeRoot32BitConstants(4,3,constants,0); list.list->Dispatch((count+63)/64,1,1); transition(list.list.Get(), encoded.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
||||||
|
ResourceAccess state; state.enhanced = enhanced; shared.copy_output(list.list.Get(), actualTexture.Get(), state);
|
||||||
|
if (enhanced) native_layout(list.list.Get(),actualTexture.Get(),D3D12_BARRIER_LAYOUT_COMMON,D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE,D3D12_BARRIER_ACCESS_COMMON,D3D12_BARRIER_ACCESS_SHADER_RESOURCE);
|
||||||
|
else transition(list.list.Get(), actualTexture.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
||||||
|
list.submit(queue.Get(),timeline); }
|
||||||
srv = {}; srv.Format = item.view; srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srv.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srv.Texture2D.MipLevels = 1; device->CreateShaderResourceView(actualTexture.Get(), &srv, initial);
|
srv = {}; srv.Format = item.view; srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srv.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srv.Texture2D.MipLevels = 1; device->CreateShaderResourceView(actualTexture.Get(), &srv, initial);
|
||||||
auto encodedActual = read_reference(device.Get(), queue.Get(), timeline, shader, heap.Get(), gpu, reference.Get(), 4);
|
auto encodedActual = read_reference(device.Get(), queue.Get(), timeline, shader, heap.Get(), gpu, reference.Get(), 4);
|
||||||
srv.Format = encodedFormat; device->CreateShaderResourceView(encoded.Get(), &srv, initial);
|
srv.Format = encodedFormat; device->CreateShaderResourceView(encoded.Get(), &srv, initial);
|
||||||
@@ -228,6 +248,6 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
++verified; std::printf("PASS PIXEL_FORMAT name=%s plane=%u pixels=%u decode_max_abs=%.9g encode=%u\n", item.name,item.plane,count,maxAbs,item.plane==0);
|
++verified; std::printf("PASS PIXEL_FORMAT name=%s plane=%u pixels=%u decode_max_abs=%.9g encode=%u\n", item.name,item.plane,count,maxAbs,item.plane==0);
|
||||||
}
|
}
|
||||||
std::printf("PASS D3D12_GPU_FORMATS architecture=gfx1201 cases=%u iterations=%u width=%u height=%u typed_srv_reference=1 typed_uav_reference=1\n", verified,args.iterations,width,height); return 0;
|
std::printf("PASS D3D12_GPU_FORMATS architecture=gfx1201 cases=%u iterations=%u width=%u height=%u enhanced=%u typed_srv_reference=1 typed_uav_reference=1\n", verified,args.iterations,width,height,enhanced); return 0;
|
||||||
} catch (const std::exception& error) { std::fprintf(stderr,"FAIL D3D12_GPU_FORMATS %s\n",error.what()); loaded_modules(); return 1; }
|
} catch (const std::exception& error) { std::fprintf(stderr,"FAIL D3D12_GPU_FORMATS %s\n",error.what()); loaded_modules(); return 1; }
|
||||||
}
|
}
|
||||||
@@ -106,9 +106,16 @@ API unsigned NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCommandList* list, co
|
|||||||
ID3D12Resource* resource = nullptr; (void)d4r_ngx_get_d3d12_resource(p, names[i], &resource);
|
ID3D12Resource* resource = nullptr; (void)d4r_ngx_get_d3d12_resource(p, names[i], &resource);
|
||||||
snapshot->resources.emplace_back(resource);
|
snapshot->resources.emplace_back(resource);
|
||||||
d4r_ngx_set_d3d12_resource(snapshot->parameters, names[i], resource);
|
d4r_ngx_set_d3d12_resource(snapshot->parameters, names[i], resource);
|
||||||
const auto state = d4r::win::commands::resource_state(list, resource, D3D12_RESOURCE_STATES(
|
const auto state = d4r::win::commands::resource_access(list, resource, d4r::win::ngx_resource_access(p, states[i],
|
||||||
d4r::ngx::uint_value(p, states[i], i == 3 ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)));
|
i == 3 ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE));
|
||||||
d4r_ngx_set_uint(snapshot->parameters, states[i], unsigned(state));
|
if (state.pending_split) throw std::runtime_error("NGX resource has an unfinished split barrier");
|
||||||
|
d4r_ngx_set_uint(snapshot->parameters, states[i], unsigned(state.legacy));
|
||||||
|
const std::string prefix(states[i]);
|
||||||
|
d4r_ngx_set_uint(snapshot->parameters, (prefix + ".Enhanced").c_str(), state.enhanced);
|
||||||
|
d4r_ngx_set_uint(snapshot->parameters, (prefix + ".Layout").c_str(), unsigned(state.layout));
|
||||||
|
d4r_ngx_set_uint(snapshot->parameters, (prefix + ".Access").c_str(), unsigned(state.access));
|
||||||
|
std::printf("D4R_RESOURCE_ACCESS plane=%s enhanced=%u legacy=0x%x layout=%u access=0x%x\n",
|
||||||
|
names[i], state.enhanced, unsigned(state.legacy), unsigned(state.layout), unsigned(state.access));
|
||||||
}
|
}
|
||||||
d4r::win::commands::record_boundary(list, [feature, snapshot](ID3D12CommandQueue* queue) { feature->evaluate_boundary(queue, snapshot->parameters); });
|
d4r::win::commands::record_boundary(list, [feature, snapshot](ID3D12CommandQueue* queue) { feature->evaluate_boundary(queue, snapshot->parameters); });
|
||||||
return 1u;
|
return 1u;
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ struct Args {
|
|||||||
std::string stream_lifetime = "persistent";
|
std::string stream_lifetime = "persistent";
|
||||||
std::string interop_mode = "roundtrip";
|
std::string interop_mode = "roundtrip";
|
||||||
std::string pixel_profile = "baseline";
|
std::string pixel_profile = "baseline";
|
||||||
|
std::string barrier_mode = "legacy";
|
||||||
std::string ngx_core, dlss_dll;
|
std::string ngx_core, dlss_dll;
|
||||||
std::string nvapi_dll;
|
std::string nvapi_dll;
|
||||||
std::string ngx_abi = "driver";
|
std::string ngx_abi = "driver";
|
||||||
@@ -136,6 +137,10 @@ struct Args {
|
|||||||
if (value != "baseline" && value != "packed" && value != "unorm") throw std::runtime_error("pixel-profile must be baseline, packed or unorm");
|
if (value != "baseline" && value != "packed" && value != "unorm") throw std::runtime_error("pixel-profile must be baseline, packed or unorm");
|
||||||
pixel_profile = value;
|
pixel_profile = value;
|
||||||
}
|
}
|
||||||
|
else if (key == "--barrier-mode") {
|
||||||
|
if (value != "legacy" && value != "enhanced") throw std::runtime_error("barrier-mode must be legacy or enhanced");
|
||||||
|
barrier_mode = value;
|
||||||
|
}
|
||||||
else if (key == "--ngx-core") ngx_core = value;
|
else if (key == "--ngx-core") ngx_core = value;
|
||||||
else if (key == "--dlss-dll") dlss_dll = value;
|
else if (key == "--dlss-dll") dlss_dll = value;
|
||||||
else if (key == "--nvapi-dll") nvapi_dll = value;
|
else if (key == "--nvapi-dll") nvapi_dll = value;
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ def generate(source):
|
|||||||
device = re.search(r'typedef struct ID3D12DeviceVtbl \{(.*?)\n\} ID3D12DeviceVtbl;', source, re.S)[1]
|
device = re.search(r'typedef struct ID3D12DeviceVtbl \{(.*?)\n\} ID3D12DeviceVtbl;', source, re.S)[1]
|
||||||
fields = list(dict.fromkeys(re.findall(r'\(STDMETHODCALLTYPE \*(\w+)\)', device)))
|
fields = list(dict.fromkeys(re.findall(r'\(STDMETHODCALLTYPE \*(\w+)\)', device)))
|
||||||
lines.append(f'static constexpr unsigned device_signature_slot = {fields.index("CreateCommandSignature")};')
|
lines.append(f'static constexpr unsigned device_signature_slot = {fields.index("CreateCommandSignature")};')
|
||||||
|
lines.append(f'static constexpr unsigned device_command_list_slot = {fields.index("CreateCommandList")};')
|
||||||
return '\n'.join(lines)
|
return '\n'.join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,16 @@ inline void ngx_check(unsigned result, const char* operation) {
|
|||||||
std::printf("D4R_NGX %s result=0x%08x\n", operation, result);
|
std::printf("D4R_NGX %s result=0x%08x\n", operation, result);
|
||||||
if (result != 1) throw std::runtime_error(std::string(operation) + " NGX=" + std::to_string(result));
|
if (result != 1) throw std::runtime_error(std::string(operation) + " NGX=" + std::to_string(result));
|
||||||
}
|
}
|
||||||
|
inline ResourceAccess ngx_resource_access(void* parameters, const char* name, D3D12_RESOURCE_STATES fallback) {
|
||||||
|
ResourceAccess result(D3D12_RESOURCE_STATES(ngx::uint_value(parameters, name, unsigned(fallback))));
|
||||||
|
const std::string prefix(name);
|
||||||
|
result.enhanced = ngx::uint_value(parameters, (prefix + ".Enhanced").c_str()) != 0;
|
||||||
|
if (result.enhanced) {
|
||||||
|
result.layout = D3D12_BARRIER_LAYOUT(ngx::uint_value(parameters, (prefix + ".Layout").c_str()));
|
||||||
|
result.access = D3D12_BARRIER_ACCESS(ngx::uint_value(parameters, (prefix + ".Access").c_str()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
inline std::filesystem::path pixel_module_path() {
|
inline std::filesystem::path pixel_module_path() {
|
||||||
if (const char* path = std::getenv("D4R_FORMAT_MODULE")) return diag::wide(env_path("D4R_FORMAT_MODULE"));
|
if (const char* path = std::getenv("D4R_FORMAT_MODULE")) return diag::wide(env_path("D4R_FORMAT_MODULE"));
|
||||||
HMODULE module = nullptr;
|
HMODULE module = nullptr;
|
||||||
@@ -251,7 +261,7 @@ private:
|
|||||||
void record_inputs(ID3D12GraphicsCommandList* list, void* parameters) {
|
void record_inputs(ID3D12GraphicsCommandList* list, void* parameters) {
|
||||||
for (unsigned i : {0u, 1u, 2u, 4u}) if (planes_[i].texture) {
|
for (unsigned i : {0u, 1u, 2u, 4u}) if (planes_[i].texture) {
|
||||||
static const char* states[] = {"D4R.Color.State", "D4R.Depth.State", "D4R.Motion.State", "D4R.Output.State", "D4R.Exposure.State"};
|
static const char* states[] = {"D4R.Color.State", "D4R.Depth.State", "D4R.Motion.State", "D4R.Output.State", "D4R.Exposure.State"};
|
||||||
planes_[i].shared->copy_input(list, planes_[i].texture.Get(), D3D12_RESOURCE_STATES(ngx::uint_value(parameters, states[i], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE)));
|
planes_[i].shared->copy_input(list, planes_[i].texture.Get(), ngx_resource_access(parameters, states[i], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void execute_cuda(ID3D12CommandQueue* queue) {
|
void execute_cuda(ID3D12CommandQueue* queue) {
|
||||||
@@ -296,7 +306,7 @@ private:
|
|||||||
std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - begin).count());
|
std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - begin).count());
|
||||||
}
|
}
|
||||||
void record_output(ID3D12GraphicsCommandList* list, void* parameters) {
|
void record_output(ID3D12GraphicsCommandList* list, void* parameters) {
|
||||||
planes_[3].shared->copy_output(list, planes_[3].texture.Get(), D3D12_RESOURCE_STATES(ngx::uint_value(parameters, "D4R.Output.State", D3D12_RESOURCE_STATE_UNORDERED_ACCESS)));
|
planes_[3].shared->copy_output(list, planes_[3].texture.Get(), ngx_resource_access(parameters, "D4R.Output.State", D3D12_RESOURCE_STATE_UNORDERED_ACCESS));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user