Program Listing for File d3d12-playback-support.h

Return to documentation for file (include\d3d12-playback-support\d3d12-playback-support.h)

/******************************************************************************
© Intel Corporation.

This software and the related documents are Intel copyrighted materials,
and your use of them is governed by the express license under which they
were provided to you ("License"). Unless the License provides otherwise,
you may not use, modify, copy, publish, distribute, disclose or transmit
this software or the related documents without Intel's prior written
permission.


 This software and the related documents are provided as is, with no express
or implied warranties, other than those that are expressly stated in the
License.

******************************************************************************/

#pragma once

#include <d3d12.h>
#include <cstdint>
#include <atomic>
#include <vector>
#include <map>
#include <array>
#include <memory>
#include <string>
#include "concurrent/lock.h"
#include "d3d12-state-tracking/d3d12-object.h"
#include "cross-gpu/d3d12-acceleration-structure-placement-manager.h"
#include "cross-gpu/d3d12-resource-placement-manager.h"

struct GPADispatchTable;

namespace gpa {

namespace raytracing {
namespace directx {
//@brief Class notified by d3d12 raytracing update manager about processed d3d12 handles and active async jobs
class RaytracingArgumentsNotifier
{
public:
    virtual void OnAccelerationStructureGPUVirtualAddress(D3D12_GPU_VIRTUAL_ADDRESS asAddress) = 0;
    virtual void OnResourceViewGPUVirtualAddress(D3D12_GPU_VIRTUAL_ADDRESS resViewAddress) = 0;
    virtual void OnGPUDescriptorTable(D3D12_GPU_DESCRIPTOR_HANDLE handle, D3D12_ROOT_DESCRIPTOR_TABLE1 const& tableDesc) = 0;
    virtual void OnAsyncRaytracingJobRegistration() = 0;
    virtual void OnAsyncRaytracingJobCompletion() = 0;
};
}  // namespace directx
}  // namespace raytracing

namespace utility {
namespace directx {
struct D3D12ShaderIdentifier;
}  // namespace directx
}  // namespace utility

namespace serialization {
struct ResetD3D12CounterOperation;
class RandomAccessSerializer;
}  // namespace serialization

namespace playback {

class ObjectMap;
struct ResetD3D12CounterOperationPlayer;

class D3D12PlaybackSupport
{
    // ResetD3D12CounterOperation should have exclusive access to the atomic counters
    friend gpa::serialization::ResetD3D12CounterOperation;
    friend gpa::playback::ResetD3D12CounterOperationPlayer;

public:
    struct DescriptorHeapDataDX12
    {
        uint32_t uniqueSequentialID = 0;
        uint32_t incrementSize = 0;
        D3D12_DESCRIPTOR_HEAP_TYPE descriptorHeapType = D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;
        D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle{};
        D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle{};
        ID3D12DescriptorHeap* heap = nullptr;
    };

    D3D12PlaybackSupport();
    ~D3D12PlaybackSupport();

    void TranslateD3D12GPUVirtualAddress(D3D12_GPU_VIRTUAL_ADDRESS& address);
    void TranslateD3D12CPUDescriptorHandle(D3D12_CPU_DESCRIPTOR_HANDLE& address);
    void TranslateD3D12GPUDescriptorHandle(D3D12_GPU_DESCRIPTOR_HANDLE& address);
    static bool TranslateD3D12ShaderIdentifier(utility::directx::D3D12ShaderIdentifier& identifier, ID3D12StateObject* stateObj, std::wstring const** ppExportName);

    void OnGetGPUVirtualAddress(ID3D12Resource* resource, uint64_t captureTimeValue, GPADispatchTable const*& table);
    void OnCreateOrAddToStateObject(ID3D12StateObject* stateObject, D3D12_STATE_OBJECT_DESC const* pDesc, ID3D12StateObject* stateObjectToGrowFrom);
    void OnGetShaderIdentifier(ID3D12StateObjectProperties* properties, LPCWSTR pExportName, void* captureTimeIdentifier, GPADispatchTable const*& table);
    std::map<gpa::utility::directx::D3D12ShaderIdentifier, gpa::utility::directx::D3D12ShaderIdentifier> const& GetReverseShaderMapping(ID3D12StateObject* stateObj);
    void ApplySubcaptureReverseShaderMapping(ID3D12StateObject* stateObject, std::map<gpa::utility::directx::D3D12ShaderIdentifier, gpa::utility::directx::D3D12ShaderIdentifier> const& revMapping);
    static void EnumerateKnownShaderMapping(ID3D12StateObject* stateObject, std::function<void(gpa::utility::directx::D3D12ShaderIdentifier captureTime, gpa::utility::directx::D3D12ShaderIdentifier playbackTime, std::wstring const* exportName)> cb);
    static size_t GetKnownShaderMappingCount(ID3D12StateObject* stateObject);
    static uint64_t GetLastMappingUpdateTimestamp(ID3D12StateObject* stateObj);
    static void OnGetShaderIdentifier(ID3D12StateObject* stateObject, ID3D12StateObjectProperties* properties, LPCWSTR pExportName, void* captureTimeIdentifier, GPADispatchTable const*& table);

    void OnPreCreateDescriptorHeap(uint64_t captureDeviceKey);
    void OnPostCreateDescriptorHeap(ID3D12DescriptorHeap* heap);
    void OnGetDescriptorHandleIncrementSize(uint64_t captureDeviceKey, D3D12_DESCRIPTOR_HEAP_TYPE descriptorHeapType, uint32_t captureIncrementSize);
    void OnGetCPUDescriptorHandleForHeapStart(ID3D12DescriptorHeap* heap, D3D12_CPU_DESCRIPTOR_HANDLE* captureTimeValue, GPADispatchTable const*& table);
    void OnGetGPUDescriptorHandleForHeapStart(ID3D12DescriptorHeap* heap, D3D12_GPU_DESCRIPTOR_HANDLE* captureTimeValue, GPADispatchTable const*& table);

    void OnSetEventOnCompletion(ID3D12Fence* fence, UINT64 value, HANDLE* hEvent,
                                ObjectMap* objMap);

    std::map<uint64_t, D3D12_GPU_VIRTUAL_ADDRESS_RANGE>& GetGpuVirtualAddressMap();
    uint64_t GetGpuVirtualAddressMapUpdateTimestamp();
    utility::directx::D3D12ShaderIdentifier const* GetCaptureD3D12ShaderIdentifier(utility::directx::D3D12ShaderIdentifier const& playbackIdentifier, ID3D12StateObject* stateObj) const;

    std::map<uint64_t, DescriptorHeapDataDX12*>& GetDescriptorHeapByCaptureAddressMap();
    uint64_t GetDescriptorHeapByCaptureAddressMapUpdateTimestamp();
    std::vector<DescriptorHeapDataDX12*>& GetDescriptorHeapByIndexVec();
    void EnumerateKnownStateObjects(std::function<void(ID3D12StateObject*)> callback);
    std::map<ID3D12DescriptorHeap*, uint64_t>& GetCaptureDeviceKeyByHeap();
    std::map<std::pair<uint64_t, D3D12_DESCRIPTOR_HEAP_TYPE>, uint32_t>& GetCaptureDescriptorIncrementSizeByHeapTypeMap();

    void Clear();

    void RegisterRaytracingArgumentsNotifier(raytracing::directx::RaytracingArgumentsNotifier* notifier);
    raytracing::directx::RaytracingArgumentsNotifier* GetRegisteredRaytracingArgumentsNotifier();
    void UnregisterRaytracingArgumentsNotifier();

    bool UseOldRaytracingPatching() const;
    void EnableOldRaytracingPatching();

    bool PrintPlaybackSizeMismatchMessages() const;
    void MutePlaybackSizeMismatchMessages();

    // Suboptimal cross platform related
    void RegisterAccelerationStructureReplacement(D3D12_GPU_VIRTUAL_ADDRESS org, D3D12_GPU_VIRTUAL_ADDRESS replacement);
    void UnregisterAccelerationStructureReplacement(D3D12_GPU_VIRTUAL_ADDRESS org);
    void TranslateD3D12GPUVirtualAddressSkipASReplacement(D3D12_GPU_VIRTUAL_ADDRESS& address);

    std::map<D3D12_GPU_VIRTUAL_ADDRESS, D3D12_GPU_VIRTUAL_ADDRESS> const& D3D12PlaybackSupport::GetGpuVirtualAddressASReplacementMap() const;
    uint64_t D3D12PlaybackSupport::GetGpuVirtualAddressASReplacementMapUpdateTimestamp() const;
    // End of suboptimal

    // Optimal cross platform related
    cross_gpu::playback::D3D12ResourcePlacementManager* GetOrCreateResourcePlacementManager(cross_gpu::TObjectKey deviceKey);
    cross_gpu::playback::D3D12AccelerationStructurePlacementManager* GetAccelerationStructurePlacementManager();
    // End of optimal

private:
    bool TranslateAccelerationStructureGPUVirtualAddress(D3D12_GPU_VIRTUAL_ADDRESS& address);
    void TranslateD3D12GPUVirtualAddressInternal(D3D12_GPU_VIRTUAL_ADDRESS& address, bool skipASreplacementMap);

    struct HandleTypeAndValue
    {
        bool isCPUHandle;
        D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle;
        D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle;
    };
    void OnGetDescriptorHandleForHeapStart(ID3D12DescriptorHeap* heap, HandleTypeAndValue captureTimeValue, GPADispatchTable const*& table);
    uint64_t TranslateDescriptorHandleOffset(DescriptorHeapDataDX12& heapData, uint64_t captureHandleOffset);

    uint64_t mCurrentCaptureDeviceKey = 0;
    std::map<ID3D12DescriptorHeap*, uint64_t> mCaptureDeviceKeyByHeap;
    std::map<std::pair<uint64_t, D3D12_DESCRIPTOR_HEAP_TYPE>, uint32_t> mCaptureDescriptorIncrementSizeByHeapType{};
    std::map<ID3D12DescriptorHeap*, DescriptorHeapDataDX12> mDescriptorHeapsMap;
    std::vector<DescriptorHeapDataDX12*> mDescriptorHeapByIndex;

    RWLock mDescriptorHeapByCaptureAddressLock;
    std::map<uint64_t, DescriptorHeapDataDX12*> mDescriptorHeapByCaptureAddress;
    uint64_t mDescriptorHeapByCaptureAddressUpdateTimestamp = 0;
    RWLock mResourceByCaptureAddressLock;

    std::map<uint64_t, D3D12_GPU_VIRTUAL_ADDRESS_RANGE> mResourceByCaptureAddress;
    uint64_t mResourceByCaptureAddressUpdateTimestamp = 0;
    std::map<D3D12_GPU_VIRTUAL_ADDRESS, uint64_t> mHeapVirtualAddressToHeapKey;

    std::map<ID3D12StateObject*, d3d12_state_tracker::WeakPtr<ID3D12StateObject>> mKnownStateObjects;

    cross_gpu::playback::D3D12ResourcePlacementManagers mResourcePlacementManagers;
    cross_gpu::playback::D3D12AccelerationStructurePlacementManager mAccelerationStructurePlacementManager;

    raytracing::directx::RaytracingArgumentsNotifier* mRegisteredNotifier = nullptr;

    bool sUseOldRaytracingPatching = false;

    RWLock mAccelerationStructureReplacementsLock;
    std::map<D3D12_GPU_VIRTUAL_ADDRESS, D3D12_GPU_VIRTUAL_ADDRESS> mAccelerationStructureReplacements;  // For suboptimal x-platform solution
    uint64_t mAccelerationStructureReplacementsUpdateTimestamp = 0;

    bool mPrintPlaybackSizeMismatchMessages = true;
};

}  // namespace playback
}  // namespace gpa