Fix game startup resource lifetime and D32S8 depth-plane interop
This commit is contained in:
1 parent
19d859e43d
commit
5d33bddcd0
17 files changed
+539
-11
No files matched your search
@@ -16,7 +16,9 @@ bool installed = false;
|
||||
struct Event { UINT metadata; std::vector<uint8_t> data; };
|
||||
using State = std::function<void(ID3D12GraphicsCommandList*)>;
|
||||
struct TrackedResource {
|
||||
ComPtr<ID3D12Resource> owner;
|
||||
// D3D12 command lists do not retain resource references. The caller keeps
|
||||
// them alive through submission/completion. An extra tracking reference
|
||||
// would keep swap-chain buffers alive and make ResizeBuffers fail.
|
||||
ResourceAccess state;
|
||||
};
|
||||
using ResourceStates = std::unordered_map<ID3D12Resource*, TrackedResource>;
|
||||
@@ -26,9 +28,9 @@ void publish_states(const ResourceStates& states) {
|
||||
// Buffers/simultaneous-access textures have automatic legacy state
|
||||
// decay at ExecuteCommandLists completion. Only ordinary textures
|
||||
// retain these explicit transitions across submission boundaries.
|
||||
const auto desc = resource_desc(entry.second.owner.Get());
|
||||
const auto desc = resource_desc(entry.first);
|
||||
if (desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER || (desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS)) continue;
|
||||
dx(entry.second.owner->SetPrivateData(submitted_access_tag, sizeof(ResourceAccess), &entry.second.state), "Publish submitted texture access");
|
||||
dx(entry.first->SetPrivateData(submitted_access_tag, sizeof(ResourceAccess), &entry.second.state), "Publish submitted texture access");
|
||||
}
|
||||
}
|
||||
struct Segment {
|
||||
@@ -206,7 +208,6 @@ void STDMETHODCALLTYPE hook_ResourceBarrier(ID3D12GraphicsCommandList* self, UIN
|
||||
if (barriers[i].Type == D3D12_RESOURCE_BARRIER_TYPE_TRANSITION &&
|
||||
(barriers[i].Transition.Subresource == 0 || barriers[i].Transition.Subresource == D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES)) {
|
||||
auto& tracked = access.recording->resource_states[barriers[i].Transition.pResource];
|
||||
tracked.owner = retain(barriers[i].Transition.pResource);
|
||||
auto& state = tracked.state;
|
||||
state = ResourceAccess(barriers[i].Transition.StateAfter);
|
||||
state.pending_split = barriers[i].Flags == D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY;
|
||||
@@ -221,7 +222,7 @@ void STDMETHODCALLTYPE hook_Barrier(ID3D12GraphicsCommandList* self, UINT32 barr
|
||||
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& tracked = access.recording->resource_states[barrier.pResource]; tracked.owner = retain(barrier.pResource);
|
||||
auto& tracked = access.recording->resource_states[barrier.pResource];
|
||||
auto& state = tracked.state; state.enhanced = true; state.inherited = false;
|
||||
state.layout = barrier.LayoutAfter; state.access = barrier.AccessAfter; state.sync = barrier.SyncAfter;
|
||||
state.pending_split = barrier.SyncAfter == D3D12_BARRIER_SYNC_SPLIT;
|
||||
|
||||
@@ -161,6 +161,23 @@ int main(int argc, char** argv) {
|
||||
using Live = unsigned long long(*)();
|
||||
const bool no_hooks = std::getenv("D4R_COMMAND_PROBE_NO_HOOKS") != nullptr;
|
||||
if (!no_hooks && shim.symbol<Install>("d4r_D3D12_InstallCommandBackend")(device.Get()) != 1) throw std::runtime_error("Command backend installation failed");
|
||||
{
|
||||
ComPtr<IDXGIFactory2> newerFactory; dx(factory->QueryInterface(IID_PPV_ARGS(newerFactory.GetAddressOf())), "Resize regression factory");
|
||||
DXGI_SWAP_CHAIN_DESC1 desc{}; desc.Width = desc.Height = 64;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.SampleDesc.Count = 1;
|
||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; desc.BufferCount = 2;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
|
||||
ComPtr<IDXGISwapChain1> chain;
|
||||
dx(newerFactory->CreateSwapChainForComposition(queue.Get(), &desc, nullptr, chain.GetAddressOf()), "Resize regression swap chain");
|
||||
ComPtr<ID3D12Resource> backBuffer; dx(chain->GetBuffer(0, IID_PPV_ARGS(backBuffer.GetAddressOf())), "Resize regression back buffer");
|
||||
NativeList recorded(device.Get());
|
||||
transition(recorded.list.Get(), backBuffer.Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
transition(recorded.list.Get(), backBuffer.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
|
||||
recorded.submit(device.Get(), queue.Get()); backBuffer.Reset();
|
||||
// The submitted list remains alive and unreset during resize.
|
||||
dx(chain->ResizeBuffers(2, 96, 64, DXGI_FORMAT_UNKNOWN, 0), "ResizeBuffers with retained submitted list");
|
||||
std::printf("D3D12_RESIZE_REGRESSION submitted_list_alive=1 old_back_buffer_released=1\n");
|
||||
}
|
||||
auto record = shim.symbol<Record>("d4r_D3D12_RecordDiagnosticBoundary");
|
||||
auto live = shim.symbol<Live>("d4r_D3D12_LiveRecordings");
|
||||
const bool root_indirect = args.interop_mode == "indirect-root-reset";
|
||||
|
||||
@@ -86,6 +86,7 @@ int main(int argc, char** argv) {
|
||||
i == 2 ? DXGI_FORMAT_R32G32B32A32_FLOAT : i == 4 ? DXGI_FORMAT_R16_FLOAT : DXGI_FORMAT_R32_FLOAT;
|
||||
if (args.pixel_profile == "unorm") desc.Format = i == 3 ? DXGI_FORMAT_B8G8R8A8_UNORM :
|
||||
i == 2 ? DXGI_FORMAT_R16G16_SNORM : i == 4 ? DXGI_FORMAT_R32G32B32A32_FLOAT : desc.Format;
|
||||
if (args.pixel_profile == "depth-stencil" && i == 1) { desc.Format = DXGI_FORMAT_R32G8X24_TYPELESS; desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; }
|
||||
if (i == 3) desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||
D3D12_HEAP_PROPERTIES heap{}; heap.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heap.CreationNodeMask = heap.VisibleNodeMask = 1;
|
||||
@@ -214,7 +215,10 @@ int main(int argc, char** argv) {
|
||||
using Requirements = unsigned(*)(IDXGIAdapter*,const d4r::ngx::FeatureDiscoveryInfo*,d4r::ngx::FeatureRequirement*);
|
||||
check(shim.symbol<Requirements>("NVSDK_NGX_D3D12_GetFeatureRequirements")(adapter.Get(),&discovery,&requirements),"D3D12 feature requirements");
|
||||
if (requirements.FeatureSupported != 0) throw std::runtime_error("D3D12 DLSS requirements unsupported");
|
||||
if (args.ngx_abi == "project") {
|
||||
if (args.ngx_abi == "project-legacy") {
|
||||
using ProjectInit = unsigned(*)(const char*,int,const char*,const wchar_t*,ID3D12Device*,const void*,unsigned);
|
||||
check(shim.symbol<ProjectInit>("NVSDK_NGX_D3D12_Init_with_ProjectID")("24480451-f00d-face-1304-0308dabad187",0,"1.0",directory.c_str(),device.Get(),nullptr,0x15),"D3D12 legacy project Init");
|
||||
} else if (args.ngx_abi == "project") {
|
||||
using ProjectInit = unsigned(*)(const char*,int,const char*,const wchar_t*,ID3D12Device*,unsigned,const void*);
|
||||
check(shim.symbol<ProjectInit>("NVSDK_NGX_D3D12_Init_ProjectID")("24480451-f00d-face-1304-0308dabad187",0,"1.0",directory.c_str(),device.Get(),0x15,nullptr),"D3D12 project Init");
|
||||
} else check(shim.symbol<Init>("NVSDK_NGX_D3D12_Init_Ext")(241534723ull, directory.c_str(), device.Get(), 0x15, nullptr), "D3D12 Init");
|
||||
|
||||
@@ -115,6 +115,13 @@ public:
|
||||
SharedPlane(ExternalApi& api, ID3D12Device* device, const D3D12_RESOURCE_DESC& texture) : api_(api) {
|
||||
UINT rows = 0; UINT64 rowBytes = 0;
|
||||
device->GetCopyableFootprints(&texture, 0, 1, 0, &footprint, &rows, &rowBytes, &bytes);
|
||||
if (texture.Format == DXGI_FORMAT_R32G8X24_TYPELESS || texture.Format == DXGI_FORMAT_D32_FLOAT_S8X24_UINT || texture.Format == DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS) {
|
||||
// D3D12 exposes D32S8 as separate depth/stencil copy planes. Only
|
||||
// subresource 0 (R32 depth) belongs to NGX; never copy interleaved
|
||||
// 64-bit texels or touch the stencil plane.
|
||||
if ((footprint.Footprint.Format != DXGI_FORMAT_R32_FLOAT && footprint.Footprint.Format != DXGI_FORMAT_R32_TYPELESS) || rowBytes != texture.Width * 4)
|
||||
throw std::runtime_error("Unexpected D32S8 depth-plane copy footprint");
|
||||
}
|
||||
if (!bytes || bytes == UINT64_MAX || !footprint.Footprint.RowPitch)
|
||||
throw std::runtime_error("Invalid shared texture footprint");
|
||||
buffer = make_buffer(device, bytes, D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_SHARED, D3D12_RESOURCE_STATE_COMMON);
|
||||
|
||||
@@ -25,6 +25,7 @@ const Case cases[] = {
|
||||
{DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, 1, "depth-r32f"},
|
||||
{DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, 1, "depth-r16unorm"},
|
||||
{DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 1, "depth24"},
|
||||
{DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 1, "depth32-stencil8-plane0"},
|
||||
{DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_FLOAT, 4, "exposure-r16f"},
|
||||
{DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, 4, "exposure-r32f"},
|
||||
{DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, 4, "exposure-rgba16f"},
|
||||
@@ -46,6 +47,7 @@ ComPtr<ID3D12Resource> make_texture(ID3D12Device* device, DXGI_FORMAT fmt, bool
|
||||
D3D12_RESOURCE_DESC desc{}; desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
desc.Width = width; desc.Height = height; desc.DepthOrArraySize = desc.MipLevels = desc.SampleDesc.Count = 1;
|
||||
desc.Format = fmt; desc.Flags = uav ? D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS : D3D12_RESOURCE_FLAG_NONE;
|
||||
if (fmt == DXGI_FORMAT_R32G8X24_TYPELESS) desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||
D3D12_HEAP_PROPERTIES heap{}; heap.Type = D3D12_HEAP_TYPE_DEFAULT; heap.CreationNodeMask = heap.VisibleNodeMask = 1;
|
||||
ComPtr<ID3D12Resource> result;
|
||||
dx(device->CreateCommittedResource(&heap, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COMMON,
|
||||
@@ -182,6 +184,7 @@ int main(int argc, char** argv) {
|
||||
for (unsigned iteration = 0; iteration < args.iterations; ++iteration) for (const auto& item : cases) {
|
||||
PixelSpec spec = pixel_spec(item.plane, item.resource); if (!pixel_supported(item.plane, spec.storage)) throw std::runtime_error("Unsupported fixture plane");
|
||||
auto input = make_texture(device.Get(), item.resource); SharedPlane shared(external, device.Get(), resource_desc(input.Get()));
|
||||
std::printf("PIXEL_FOOTPRINT format=%s plane0_format=%u pitch=%u storage_bytes=%u\n", item.name, shared.footprint.Footprint.Format, shared.footprint.Footprint.RowPitch, spec.bytes);
|
||||
auto upload = make_buffer(device.Get(), shared.bytes, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_NONE, D3D12_RESOURCE_STATE_GENERIC_READ);
|
||||
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);
|
||||
|
||||
@@ -13,6 +13,13 @@ std::unordered_map<Handle*, std::shared_ptr<d4r::win::Feature>> features;
|
||||
std::unordered_map<void*, bool> parameters;
|
||||
constexpr unsigned failure = 0xBAD00002, invalid = 0xBAD00005;
|
||||
unsigned call(const std::function<unsigned()>& fn) noexcept {
|
||||
static std::once_flag diagnosticOutput;
|
||||
std::call_once(diagnosticOutput, [] {
|
||||
if (std::getenv("D4R_DIAG_DIR")) {
|
||||
std::setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
std::setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
}
|
||||
});
|
||||
try { return fn(); }
|
||||
catch (const std::exception& error) {
|
||||
std::fprintf(stderr, "D4R_WINDOWS_FAILURE %s\n", error.what()); return failure;
|
||||
|
||||
@@ -142,7 +142,7 @@ struct Args {
|
||||
else if (key == "--stream-lifetime") stream_lifetime = value;
|
||||
else if (key == "--interop-mode") interop_mode = value;
|
||||
else if (key == "--pixel-profile") {
|
||||
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" && value != "depth-stencil") throw std::runtime_error("Invalid pixel-profile");
|
||||
pixel_profile = value;
|
||||
}
|
||||
else if (key == "--barrier-mode") {
|
||||
|
||||
@@ -26,6 +26,9 @@ inline PixelSpec pixel_spec(unsigned plane, DXGI_FORMAT format) {
|
||||
case DXGI_FORMAT_R16G16_UNORM: return {rg16unorm, 4, false};
|
||||
case DXGI_FORMAT_R32_FLOAT: case DXGI_FORMAT_R32_TYPELESS: case DXGI_FORMAT_D32_FLOAT:
|
||||
return {r32f, 4, plane == depth || plane == exposure};
|
||||
case DXGI_FORMAT_R32G8X24_TYPELESS: case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
|
||||
if (plane != depth) throw std::runtime_error("Depth/stencil resources are supported only for the depth input");
|
||||
return {r32f, 4, true}; // D3D12 subresource 0 is the R32 depth plane.
|
||||
case DXGI_FORMAT_R16_FLOAT: return {r16f, 2, false};
|
||||
case DXGI_FORMAT_D24_UNORM_S8_UINT: case DXGI_FORMAT_R24G8_TYPELESS: case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
|
||||
return {depth24, 4, false};
|
||||
|
||||
Reference in new issue
Block a user