Program Listing for File d3d12-graphicscommandlist.h

Return to documentation for file (include\d3d12-state-tracking\d3d12-graphicscommandlist.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-object.h"
#include "d3d12-descriptorheap.h"  // DX12Descriptor
#include "d3d12-commandallocator.h"
#include "d3d12-commandlist-debug.h"
#include "concurrent/critical-section.h"

#include <vector>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <memory>
#include <set>
#include <d3d12.h>

#include <array>

namespace gpa {
namespace serialization {
class StructDataManager;
}  // namespace serialization
namespace d3d12_state_tracker {

enum DX12DescriptorType;
struct DX12Descriptor;

enum PipelineType {
    PipelineTypeCompute,
    PipelineTypeGraphics,
};

size_t const kMaxContants = 64;

struct RootParamRecord
{
    D3D12_ROOT_PARAMETER_TYPE type;
    union
    {
        struct
        {
            D3D12_GPU_VIRTUAL_ADDRESS bufferLocation;
        } descriptor;
        struct
        {
            D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor;
        } descriptorTable;
        struct
        {
            uint32_t srcData[kMaxContants];
            uint32_t numValues;
        } constants;
    };
};

struct ResourceBindingInfo
{
    bool hasDescriptor;  //<! Use descriptor if true, use bareResource otherwise
    union
    {
        DX12Descriptor *descriptor = nullptr;  // If the resource was bound because of Set..RootDescriptorTable, this will be populated
        struct                                 // If the resource was bound with ID3D12GraphicsCommanList::Set..Root..View, this will be populated
        {
            DX12DescriptorType type = D3D12_DESCRIPTOR_TYPE_EMPTY;
            ID3D12Resource *resource = nullptr;
            uint32_t offset = 0;
        } bareBinding;
    };
};

struct CopyAccelerationStructureInfo
{
    D3D12_GPU_VIRTUAL_ADDRESS destAccelerationStructureData;
    D3D12_GPU_VIRTUAL_ADDRESS sourceAccelerationStructureData;
    D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE mode;
};

struct CopyBufferInfo
{
    ID3D12Resource *destResource = nullptr;
    uint64_t destOffset = 0;
    ID3D12Resource *srcResource = nullptr;
    uint64_t srcOffset = 0;
    uint64_t numBytes = 0;
};

template<typename ArgumentsType>
struct Command
{
    uint32_t index;
    ArgumentsType arguments;

    Command(uint32_t index, ArgumentsType arguments)
        : index(index)
        , arguments(arguments)
    {
    }
};

using BuildASCommand = Command<D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC const *>;
using CopyASCommand = Command<CopyAccelerationStructureInfo>;
using DispatchRaysCommand = Command<D3D12_DISPATCH_RAYS_DESC>;
using CopyBufferCommand = Command<CopyBufferInfo>;
using CopyBufferCommands = std::vector<CopyBufferCommand>;
using ReferencedDescriptorHeaptoDescriptorMap = std::unordered_map<ID3D12DescriptorHeap *, std::vector<std::pair<SIZE_T, DX12Descriptor>>>;

using RootSignatureRecord = std::array<std::unordered_map<uint32_t, RootParamRecord>, 2>;

class D3D12GraphicsCommandListState : public D3D12ObjectState
{
public:
    static constexpr GUID sGUID = {0xe2d63967, 0xb577, 0x4054, {0xa8, 0x1d, 0xb6, 0x5e, 0xad, 0xfe, 0x87, 0x78}};

    using ScissorRects = std::vector<D3D12_RECT>;
    using Viewports = std::vector<D3D12_VIEWPORT>;
    using DescriptorHeaps = std::vector<ID3D12DescriptorHeap *>;
    using RenderTargets = std::vector<D3D12_CPU_DESCRIPTOR_HANDLE>;
    using IndexBuffer = std::vector<D3D12_INDEX_BUFFER_VIEW>;
    using VertexBuffers = std::map<UINT, D3D12_VERTEX_BUFFER_VIEW>;
    using DepthStencil = D3D12_CPU_DESCRIPTOR_HANDLE;
    using Topology = D3D12_PRIMITIVE_TOPOLOGY;
    using StreamOutTargets = std::map<UINT, D3D12_STREAM_OUTPUT_BUFFER_VIEW>;

private:
    const uint32_t mNodeMask;
    const D3D12_COMMAND_LIST_TYPE mType;

    gpa::concurrent::CriticalSection mCriticalSection;
    uint32_t mCommandIndex = 0;

    ID3D12CommandAllocator *mCommandAllocator;
    ID3D12PipelineState *mPipelineState = nullptr;                 // TODO: replace with a weak_ptr to the state object
    std::map<uint32_t, ID3D12StateObject *> mStateObjectsHistory;  // TODO: replace with a weak_ptr to the state object
    ID3D12StateObject *mStateObject = nullptr;
    ID3D12RootSignature *mRootSignature[2] = {};

    std::unordered_map<ID3D12Resource *, std::vector<D3D12_RESOURCE_STATES>> mPendingStateTransitions;
    std::unordered_set<ID3D12Resource *> mPendingDirtyResources;

    struct EnhancedBarrier
    {
        EnhancedBarrier(D3D12_TEXTURE_BARRIER barrier)
        {
            mType = D3D12_BARRIER_TYPE_TEXTURE;
            mTextureBarrier = barrier;
        }
        EnhancedBarrier(D3D12_BUFFER_BARRIER barrier)
        {
            mType = D3D12_BARRIER_TYPE_BUFFER;
            mBufferBarrier = barrier;
        }
        D3D12_BARRIER_TYPE mType;
        union
        {
            D3D12_TEXTURE_BARRIER mTextureBarrier;
            D3D12_BUFFER_BARRIER mBufferBarrier;
        };
    };
    std::unordered_map<ID3D12Resource *, std::vector<EnhancedBarrier>> mPendingEnhancedTransitions;

    RootSignatureRecord mRootBindingState;

    std::vector<std::unique_ptr<serialization::StructDataManager>> mAllBuildASDescDataManagers;
    std::vector<Command<serialization::StructDataManager const *>> mCurrentBuildASDescDataManagers;
    std::vector<DispatchRaysCommand> mDispatchRaysDescs;
    CopyBufferCommands mPendingCopyBuffers;
    std::vector<CopyASCommand> mPendingCopyAccelerationStructures;

    DescriptorHeaps mDescriptorHeaps;

    // IA state
    IndexBuffer mIndexBuffer;
    VertexBuffers mVertexBuffers;

    bool mTopologySet = false;
    Topology mTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;

    // OM state
    bool mStencilRefSet = false;
    uint32_t mStencilRef{0};

    RenderTargets mRenderTargetsRuntime;       //<! Runtime ready rendertarget CPU Descriptor Heap handles
    RenderTargets mRenderTargetsUntranslated;  //<! Untranslated handles - use this value, if the call containing this value will go through d3d12-state-tracking layer
    DepthStencil mDepthRuntime{0};             //<! Runtime ready depthstencil CPU Descriptor Heap handle
    DepthStencil mDepthUntranslated{0};        //<! Untranslated handle - use this value, if the call containing this value will go through d3d12-state-tracking layer

    enum class BlendFactorState {
        NOT_SET,
        SET_NULL,
        SET
    };
    BlendFactorState mBlendFactorState = BlendFactorState::NOT_SET;
    FLOAT mBlendFactor[4]{};

    bool mDepthBoundSet = false;
    FLOAT mDepthBounds[2]{0.0, 1.0};

    // RS state
    ScissorRects mScissorRects;
    Viewports mViewports;

    // SO
    StreamOutTargets mSOTargets;

    // Query
    std::set<std::tuple<ID3D12QueryHeap *, D3D12_QUERY_TYPE, uint32_t>> mQueries;
    struct PredicationState
    {
        bool set = false;
        ID3D12Resource *pBuffer;
        uint64_t alignedBufferOffset;
        D3D12_PREDICATION_OP operation;
    };
    PredicationState mPredication{};

    struct SamplePositionsState
    {
        bool set = false;
        UINT numSamplesPerPixel;
        UINT numPixels;
        std::vector<D3D12_SAMPLE_POSITION> samplePositions;
    };
    SamplePositionsState mSamplePositions{};

    bool mViewInstanceMaskSet = false;
    uint32_t mViewInstanceMask = 0;

    ID3D12ProtectedResourceSession *mProtectedResourceSession = nullptr;

    struct RenderPass
    {
        bool set = false;
        std::vector<D3D12_RENDER_PASS_RENDER_TARGET_DESC> renderTargets;
        D3D12_RENDER_PASS_DEPTH_STENCIL_DESC depthStencil;
        bool depthStencilSet = false;
        D3D12_RENDER_PASS_FLAGS flags;
    };
    RenderPass mRenderPass{};

    struct ShadingRate
    {
        bool set = false;
        D3D12_SHADING_RATE baseShadingRate;
        bool combinersSet = false;
        D3D12_SHADING_RATE_COMBINER combiners[D3D12_RS_SET_SHADING_RATE_COMBINER_COUNT];
    };
    ShadingRate mShadingRate{};

    struct ShadingRateImage
    {
        bool set = false;
        bool setToNull = false;
        ID3D12Resource *shadingRateImage = nullptr;
    };
    ShadingRateImage mShadingRateImage{};

    size_t mRtvIncrementSize{0};

    bool mIsRecording = false;

    std::unique_ptr<D3D12GraphicsCommandListExtendedState> mExtendedState = nullptr;

    ReferencedDescriptorHeaptoDescriptorMap mReferencedRenderTargetDescriptors;

public:
    D3D12GraphicsCommandListState(ID3D12GraphicsCommandList *pList, UINT nodeMask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *pCommandAllocator, ID3D12PipelineState *pInitialState);
    D3D12GraphicsCommandListState(D3D12GraphicsCommandListState const &) = delete;
    D3D12GraphicsCommandListState &operator=(D3D12GraphicsCommandListState const &) = delete;
    ~D3D12GraphicsCommandListState() override;

    GUID GetGUID() override;

    D3D12GraphicsCommandListExtendedState *GetExtendedState();
    void InitializeExtendedState();

    void OnResourceBarrier(UINT NumBarriers, const D3D12_RESOURCE_BARRIER *pBarriers);
    void OnReset(ID3D12CommandAllocator *allocator, ID3D12PipelineState *pipelineState);
    void OnClose();
    void OnSetPipelineState(ID3D12PipelineState *pipelineState);
    void OnSetPipelineState1(ID3D12StateObject *stateObject);
    void OnClearState(ID3D12PipelineState *stateObject);

    void OnSetComputeRootSignature(ID3D12RootSignature *rootSignature);
    void OnSetGraphicsRootSignature(ID3D12RootSignature *rootSignature);
    void OnSetComputeRootDescriptorTable(UINT RootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor);
    void OnSetGraphicsRootDescriptorTable(UINT RootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor);
    void OnSetComputeRoot32BitConstant(UINT RootParameterIndex, UINT SrcData, UINT DestOffsetIn32BitValues);
    void OnSetGraphicsRoot32BitConstant(UINT RootParameterIndex, UINT SrcData, UINT DestOffsetIn32BitValues);
    void OnSetComputeRoot32BitConstants(UINT RootParameterIndex, UINT Num32BitValuesToSet, const void *pSrcData, UINT DestOffsetIn32BitValues);
    void OnSetGraphicsRoot32BitConstants(UINT RootParameterIndex, UINT Num32BitValuesToSet, const void *pSrcData, UINT DestOffsetIn32BitValues);
    void OnSetComputeRootConstantBufferView(UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);
    void OnSetGraphicsRootConstantBufferView(UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);
    void OnSetComputeRootShaderResourceView(UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);
    void OnSetGraphicsRootShaderResourceView(UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);
    void OnSetComputeRootUnorderedAccessView(UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);
    void OnSetGraphicsRootUnorderedAccessView(UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);

    void OnIASetIndexBuffer(const D3D12_INDEX_BUFFER_VIEW *pView);
    void OnIASetPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY PrimitiveTopology);
    void OnIASetVertexBuffers(UINT StartSlot, UINT NumViews, const D3D12_VERTEX_BUFFER_VIEW *pViews);

    void OnOMSetBlendFactor(const FLOAT BlendFactor[4]);
    void OnOMSetRenderTargets(
        UINT NumRenderTargetDescriptors,
        const D3D12_CPU_DESCRIPTOR_HANDLE *pRenderTargetDescriptors,
        BOOL RTsSingleHandleToDescriptorRange,
        const D3D12_CPU_DESCRIPTOR_HANDLE *pDepthStencilDescriptor,
        bool runtimeCPUDescriptorHandles);
    void OnOMSetStencilRef(UINT StencilRef);
    void OnOMSetDepthBounds(FLOAT Min, FLOAT Max);

    void OnSOSetTargets(UINT StartSlot, UINT NumViews, const D3D12_STREAM_OUTPUT_BUFFER_VIEW *pViews);

    void OnRSSetScissorRects(UINT NumRects, const D3D12_RECT *pRects);
    void OnRSSetViewports(UINT NumViewports, const D3D12_VIEWPORT *pViewports);
    void OnSetDescriptorHeaps(UINT NumDescriptorHeaps, ID3D12DescriptorHeap *const *ppDescriptorHeaps);

    void OnAllocatorReset(ID3D12CommandAllocator *allocator);
    void OnExecute(ID3D12CommandQueue *queue);
    void OnExecuteBundle(ID3D12GraphicsCommandList *pCommandList);
    void OnResourceUpdate(ID3D12Resource *resource);
    void OnCopyBufferRegion(ID3D12Resource *pDstBuffer, UINT64 DstOffset, ID3D12Resource *pSrcBuffer, UINT64 SrcOffset, UINT64 NumBytes);
    void OnCopyResource(ID3D12Resource *pDstResource, ID3D12Resource *pSrcResource);

    void OnCopyRaytracingAccelerationStructure(D3D12_GPU_VIRTUAL_ADDRESS DestAccelerationStructureData, D3D12_GPU_VIRTUAL_ADDRESS SourceAccelerationStructureData, D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE Mode);
    void OnBuildRaytracingAccelerationStructure(const D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC &desc);
    void OnDispatchRays(const D3D12_DISPATCH_RAYS_DESC &desc);

    void OnBeginQuery(ID3D12QueryHeap *pQueryHeap, D3D12_QUERY_TYPE Type, UINT Index);
    void OnEndQuery(ID3D12QueryHeap *pQueryHeap, D3D12_QUERY_TYPE Type, UINT Index);
    void OnSetPredication(ID3D12Resource *pBuffer, UINT64 AlignedBufferOffset, D3D12_PREDICATION_OP Operation);

    void OnSetSamplePositions(UINT NumSamplesPerPixel, UINT NumPixels, D3D12_SAMPLE_POSITION *pSamplePositions);
    void OnSetViewInstanceMask(UINT Mask);

    void OnSetProtectedResourceSession(ID3D12ProtectedResourceSession *pProtectedResourceSession);

    void OnBeginRenderPass(UINT NumRenderTargets, const D3D12_RENDER_PASS_RENDER_TARGET_DESC *pRenderTargets, const D3D12_RENDER_PASS_DEPTH_STENCIL_DESC *pDepthStencil, D3D12_RENDER_PASS_FLAGS Flags);
    void OnEndRenderPass();

    void OnRSSetShadingRate(D3D12_SHADING_RATE baseShadingRate, const D3D12_SHADING_RATE_COMBINER *combiners);

    void OnRSSetShadingRateImage(ID3D12Resource *shadingRateImage);

#ifdef __ID3D12GraphicsCommandList7_INTERFACE_DEFINED__
    void OnBarrier(UINT32 NumBarrierGroups, const D3D12_BARRIER_GROUP *pBarrierGroups);
#endif

    bool IsRecording() const;
    uint32_t GetNodeMask() const;
    ID3D12PipelineState *GetPipelineState() const;
    ID3D12StateObject *GetRaytracingState() const;
    ID3D12CommandAllocator *GetCommandAllocator() const;
    ID3D12RootSignature *GetCurrentRootSignature(PipelineType const pipelineType) const;
    ID3D12StateObject *GetStateObjectAtCommand(uint32_t commandIndex) const;
    std::vector<BuildASCommand> GetRaytracingASDescs() const;
    std::vector<DispatchRaysCommand> const &GetDispatchRaysDescs() const;
    CopyBufferCommands const &GetCopyBufferCommands() const;
    std::vector<CopyASCommand> const &GetCopyAccelerationStructures() const;
    std::vector<D3D12_RESOURCE_STATES> const *GetPendingResourceState(ID3D12Resource *resource) const;
    std::vector<EnhancedBarrier> const *GetPendingEnhancedState(ID3D12Resource *resource) const;
    std::vector<ID3D12DescriptorHeap *> GetDescriptorHeaps() const;
    VertexBuffers const &GetVertexBuffers() const;
    IndexBuffer const &GetIndexBuffer() const;
    Viewports const &GetViewports() const;
    ScissorRects const &GetScissorRects() const;
    StreamOutTargets const &GetStreamOutTargets() const;
    uint32_t GetStencilRef() const;
    std::vector<float> GetDepthBounds() const;
    Topology GetTopology() const;
    std::unordered_map<uint32_t, RootParamRecord> const &GetRootSignatureRecord(PipelineType pipelineType) const;
    RenderTargets const &GetRenderTargets(bool requestUntranslatedHandle) const;
    DepthStencil const &GetDepthStencil(bool requestUntranslatedHandle) const;
    ReferencedDescriptorHeaptoDescriptorMap const &GetReferencedRenderTargetDescriptors() const;

    void EnumerateCurrentBindings(PipelineType pipelineType, std::function<bool(uint32_t shaderRegister, uint32_t registerSpace, ResourceBindingInfo resourceBindingInfo, D3D12_SHADER_VISIBILITY visibility, bool belongsToUnboundedRange)> callback);

    void RestoreState(ID3D12GraphicsCommandList *cmdList, bool useUntranslated = false);
    void RestoreComputeBindings(ID3D12GraphicsCommandList *cmdList);
    void RestoreComputeState(ID3D12GraphicsCommandList *cmdList);
    void RestoreGraphicsState(ID3D12GraphicsCommandList *cmdList, bool restoreCommon = true, bool useUntranslated = false);

    uint32_t NextCommandIndex();
    uint32_t CurrentCommandIndex();

private:
    inline void OnSetRootResourceView(PipelineType pipelineType, D3D12_ROOT_PARAMETER_TYPE viewType, UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation);
    inline void OnSetRootDescriptorTable(PipelineType pipelineType, UINT RootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor);
    inline void OnSetRoot32BitConstants(PipelineType pipelineType, UINT RootParameterIndex, UINT Num32BitValuesToSet, const void *pSrcData, UINT DestOffsetIn32BitValues);
    inline void OnSetRootSignature(PipelineType pipelineType);
    bool BelongsToCurrentlySetDescriptorHeaps(D3D12_GPU_DESCRIPTOR_HANDLE handle);

    void UpdateReferencedDescriptorsHistory(D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle);

    void UnregisterFromCurrentAllocator();
};

}  // namespace d3d12_state_tracker
}  // namespace gpa