Exemplo n.º 1
0
        private Pointer <ID3D12Resource> CreateD3D12Resource()
        {
            _state.ThrowIfDisposedOrDisposing();

            ID3D12Resource *d3d12Resource;

            var bufferDesc = D3D12_RESOURCE_DESC.Buffer(width: Size);
            var iid        = IID_ID3D12Resource;

            var d3d12GraphicsHeap = D3D12GraphicsHeap;
            var d3d12Heap         = d3d12GraphicsHeap.D3D12Heap;

            var d3d12GraphicsDevice = d3d12GraphicsHeap.D3D12GraphicsDevice;
            var d3d12Device         = d3d12GraphicsDevice.D3D12Device;

            ThrowExternalExceptionIfFailed(nameof(ID3D12Device.CreatePlacedResource), d3d12Device->CreatePlacedResource(
                                               d3d12Heap,
                                               Offset,
                                               &bufferDesc,
                                               D3D12ResourceState,
                                               pOptimizedClearValue: null,
                                               &iid,
                                               (void **)&d3d12Resource
                                               ));

            return(d3d12Resource);
        }
Exemplo n.º 2
0
        //public static ulong UpdateSubresources(
        //    [In] ID3D12GraphicsCommandList* pCmdList,
        //    [In] ID3D12Resource* pDestinationResource,
        //    [In] ID3D12Resource* pIntermediate,
        //    ulong IntermediateOffset,
        //    [In] uint FirstSubresource,
        //    [In] uint NumSubresources,
        //    [In] D3D12_SUBRESOURCE_DATA* pSrcData)
        //{
        //    ulong RequiredSize = 0;
        //    ulong MemToAlloc = (ulong) (sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(uint) + sizeof(ulong)) *
        //                       NumSubresources;

        //    if (MemToAlloc > (ulong)(void*)-1) // new
        //    {
        //        return 0;
        //    }

        //    void* pMem = UnsafeNativeMethods.HeapAlloc(UnsafeNativeMethods.GetProcessHeap(), 0, (IntPtr)MemToAlloc);

        //    if (pMem == null)
        //    {
        //        return 0;
        //    }

        //    D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts = (D3D12_PLACED_SUBRESOURCE_FOOTPRINT*) pMem;
        //    ulong* pRowSizesInBytes = (ulong*) (pLayouts + NumSubresources);
        //    uint* pNumRows = (uint*) (pRowSizesInBytes + NumSubresources);

        //    D3D12_RESOURCE_DESC Desc;
        //    pDestinationResource->GetDesc(&Desc);
        //    ID3D12Device* pDevice;
        //    Guid iid = D3D12.IID_ID3D12Device;
        //    pDestinationResource->GetDevice(&iid, (void**) &pDevice);
        //    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts,
        //        pNumRows, pRowSizesInBytes, &RequiredSize);
        //    pDevice->Release();

        //    ulong Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource,
        //        NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);
        //    UnsafeNativeMethods.HeapFree(UnsafeNativeMethods.GetProcessHeap(), 0, pMem);
        //    return Result;
        //}

        //public static ulong UpdateSubresources(
        //    uint MaxSubresources,
        //    [In] ID3D12GraphicsCommandList* pCmdList,
        //    [In] ID3D12Resource* pDestinationResource,
        //    [In] ID3D12Resource* pIntermediate,
        //    ulong IntermediateOffset,
        //    [In] uint FirstSubresource,
        //    [In] uint NumSubresources,
        //    [In] D3D12_SUBRESOURCE_DATA* pSrcData)
        //{
        //    ulong RequiredSize = 0;
        //    D3D12_PLACED_SUBRESOURCE_FOOTPRINT* Layouts
        //        = stackalloc D3D12_PLACED_SUBRESOURCE_FOOTPRINT[(int) MaxSubresources];
        //    uint* NumRows = stackalloc uint[(int) MaxSubresources];
        //    ulong* RowSizesInBytes = stackalloc ulong[(int) MaxSubresources];

        //    D3D12_RESOURCE_DESC Desc;
        //    pDestinationResource->GetDesc(&Desc);
        //    ID3D12Device* pDevice;
        //    Guid iid = D3D12.IID_ID3D12Device;
        //    pDestinationResource->GetDevice(&iid, (void**) &pDevice);
        //    pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts,
        //        NumRows, RowSizesInBytes, &RequiredSize);
        //    pDevice->Release();

        //    return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources,
        //        RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData);
        //}

        //public static ulong UpdateSubresources(
        //    [In] ID3D12GraphicsCommandList* pCmdList,
        //    [In] ID3D12Resource* pDestinationResource,
        //    [In] ID3D12Resource* pIntermediate,
        //    [In] uint FirstSubresource,
        //    [In] uint NumSubresources,
        //    ulong RequiredSize,
        //    [In] D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,
        //    [In] uint* pNumRows,
        //    [In] ulong* pRowSizesInBytes,
        //    [In] D3D12_SUBRESOURCE_DATA* pSrcData)
        //{
        //    // Minor validation
        //    D3D12_RESOURCE_DESC IntermediateDesc;
        //    pIntermediate->GetDesc(&IntermediateDesc);

        //    D3D12_RESOURCE_DESC DestinationDesc;
        //    pDestinationResource->GetDesc(&DestinationDesc);

        //    if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER ||
        //        IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset ||
        //        RequiredSize > (ulong)(void*)(-1) ||
        //        (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
        //         (FirstSubresource != 0 || NumSubresources != 1)))
        //    {
        //        return 0;
        //    }

        //    byte* pData;
        //    HRESULT hr = pIntermediate->Map(0, null, (void**) &pData);
        //    if (FAILED(hr))
        //    {
        //        return 0;
        //    }

        //    for (uint i = 0; i < NumSubresources; ++i)
        //    {
        //        /*
        //           void *pData;
        //           SIZE_T RowPitch;
        //           SIZE_T SlicePitch;
        //         */
        //        if (pRowSizesInBytes[i] > (ulong)(void*)-1) return 0;
        //        D3D12_MEMCPY_DEST DestData = new D3D12_MEMCPY_DEST
        //        {
        //            pData = pData + pLayouts[i].Offset,
        //            RowPitch = (UIntPtr)pLayouts[i].Footprint.RowPitch,
        //            SlicePitch = (UIntPtr)(pLayouts[i].Footprint.RowPitch * pNumRows[i])
        //        };

        //        MemcpySubresource(&DestData, &pSrcData[i], (UIntPtr) pRowSizesInBytes[i], pNumRows[i],
        //            pLayouts[i].Footprint.Depth);
        //    }

        //    pIntermediate->Unmap(0, null);

        //    if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
        //    {
        //        D3D12_BOX SrcBox = CD3DX12_BOX.Create((int) pLayouts[0].Offset,
        //            (int) (pLayouts[0].Offset + pLayouts[0].Footprint.Width));
        //        pCmdList->CopyBufferRegion(
        //            pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);
        //    }
        //    else
        //    {
        //        for (uint i = 0; i < NumSubresources; ++i)
        //        {
        //            D3D12_TEXTURE_COPY_LOCATION Dst =
        //                CD3DX12_TEXTURE_COPY_LOCATION.Create(pDestinationResource, i + FirstSubresource);
        //            D3D12_TEXTURE_COPY_LOCATION Src = CD3DX12_TEXTURE_COPY_LOCATION.Create(pIntermediate, pLayouts[i]);
        //            pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, null);
        //        }
        //    }

        //    return RequiredSize;
        //}

        //public static void MemcpySubresource(
        //    [In] D3D12_MEMCPY_DEST* pDest,
        //    [In] D3D12_SUBRESOURCE_DATA* pSrc,
        //    UIntPtr RowSizeInBytes,
        //    uint NumRows,
        //    uint NumSlices)
        //{
        //    for (uint z = 0; z < NumSlices; ++z)
        //    {
        //        byte* pDestSlice = (byte*)(pDest->pData);
        //        byte* pSrcSlice = (byte*)(pSrc->pData);
        //        if (IntPtr.Size == 4)
        //        {
        //            pDestSlice += (uint)pDest->SlicePitch * z;
        //            pSrcSlice += (uint)pSrc->SlicePitch * z;
        //        }
        //        else
        //        {
        //            pDestSlice += (ulong)pDest->SlicePitch * z;
        //            pSrcSlice += (ulong)pSrc->SlicePitch * z;
        //        }
        //        for (var y = 0u; y < NumRows; ++y)
        //        {
        //            byte* pTempDest = pDestSlice;
        //            byte* pTempSrc = pSrcSlice;

        //            if (IntPtr.Size == 4)
        //            {
        //                pDestSlice += (uint)pDest->RowPitch * y;
        //                pSrcSlice += (uint)pDest->RowPitch * y;
        //            }
        //            else
        //            {
        //                pDestSlice += (ulong)pDest->RowPitch * y;
        //                pSrcSlice += (ulong)pDest->RowPitch * y;
        //            }

        //            Buffer.MemoryCopy(pTempSrc, pTempDest, (long)RowSizeInBytes, (long)RowSizeInBytes);
        //        }
        //    }
        //}

        public static ulong UpdateSubresources(ID3D12GraphicsCommandList *pCmdList, ID3D12Resource *pDestinationResource, ID3D12Resource *pIntermediate, ulong IntermediateOffset, uint FirstSubresource, uint NumSubresources, D3D12_SUBRESOURCE_DATA *pSrcData)
        {
            ulong RequiredSize = 0;
            ulong MemToAlloc   = (ulong)(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(uint) + sizeof(ulong)) * NumSubresources;

            if (MemToAlloc > ((IntPtr.Size == 4) ? uint.MaxValue : ulong.MaxValue))
            {
                return(0);
            }
            void *pMem = Marshal.AllocHGlobal((IntPtr)MemToAlloc).ToPointer();

            if (pMem == null)
            {
                return(0);
            }
            D3D12_PLACED_SUBRESOURCE_FOOTPRINT *pLayouts = (D3D12_PLACED_SUBRESOURCE_FOOTPRINT *)(pMem);
            ulong *pRowSizesInBytes = (ulong *)(pLayouts + NumSubresources);
            uint * pNumRows         = (uint *)(pRowSizesInBytes + NumSubresources);

            D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc();
            ID3D12Device *      pDevice;
            Guid iid = D3D12.IID_ID3D12Device;

            pDestinationResource->GetDevice(&iid, (void **)(&pDevice));
            pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);
            pDevice->Release();

            ulong Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);

            Marshal.FreeHGlobal((IntPtr)pMem);
            return(Result);
        }
Exemplo n.º 3
0
        protected virtual ID3D12Resource *CreateDepthStencil()
        {
            ID3D12Resource *depthStencil;

            var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

            var resourceDesc = D3D12_RESOURCE_DESC.Tex2D(DepthBufferFormat, (uint)Size.Width, (uint)Size.Height, mipLevels: 1);

            resourceDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;

            var clearValue = new D3D12_CLEAR_VALUE(DepthBufferFormat, 1.0f, 0);

            var iid = IID_ID3D12Resource;

            ThrowIfFailed(nameof(ID3D12Device.CreateCommittedResource), D3DDevice->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue, &iid, (void **)&depthStencil));

            var dsvDesc = new D3D12_DEPTH_STENCIL_VIEW_DESC {
                Format        = DepthBufferFormat,
                ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D,
            };

            D3DDevice->CreateDepthStencilView(depthStencil, &dsvDesc, DSVHeap->GetCPUDescriptorHandleForHeapStart());

            return(depthStencil);
        }
Exemplo n.º 4
0
        /// <inheritdoc />
        public override D3D12GraphicsBuffer CreateBuffer(GraphicsBufferKind kind, GraphicsResourceCpuAccess cpuAccess, ulong size, ulong alignment = 0, GraphicsMemoryAllocationFlags allocationFlags = GraphicsMemoryAllocationFlags.None)
        {
            var index = GetBlockCollectionIndex(cpuAccess, 0);

            var resourceDesc                 = D3D12_RESOURCE_DESC.Buffer(size, D3D12_RESOURCE_FLAG_NONE, alignment);
            var resourceAllocationInfo       = Device.D3D12Device->GetResourceAllocationInfo(visibleMask: 0, numResourceDescs: 1, &resourceDesc);
            ref readonly var blockCollection = ref _blockCollections[index];
    protected override void CreateBuffers()
    {
        base.CreateBuffers();
        _constantBuffer = CreateConstantBuffer(out _constantBufferDataBegin);

        ID3D12Resource *CreateConstantBuffer(out byte *constantBufferDataBegin)
        {
            ID3D12Resource *constantBuffer;

            var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
            var bufferDesc     = D3D12_RESOURCE_DESC.Buffer(1024 * 64);

            ThrowIfFailed(D3DDevice->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, pOptimizedClearValue: null, __uuidof <ID3D12Resource>(), (void **)&constantBuffer));

            var cbvDesc = new D3D12_CONSTANT_BUFFER_VIEW_DESC {
                BufferLocation = constantBuffer->GetGPUVirtualAddress(),
                SizeInBytes    = (uint)((sizeof(SceneConstantBuffer) + 255) & ~255) // CB size is required to be 256-byte aligned.
            };

            D3DDevice->CreateConstantBufferView(&cbvDesc, _cbvHeap->GetCPUDescriptorHandleForHeapStart());

            // Map and initialize the constant buffer. We don't unmap this until the
            // app closes. Keeping things mapped for the lifetime of the resource is okay.

            fixed(byte **pConstantBufferDataBegin = &constantBufferDataBegin)
            {
                var readRange = new D3D12_RANGE(); // We do not intend to read from this resource on the CPU.

                ThrowIfFailed(constantBuffer->Map(Subresource: 0, &readRange, (void **)pConstantBufferDataBegin));
                Unsafe.CopyBlock(ref constantBufferDataBegin[0], ref Unsafe.As <SceneConstantBuffer, byte>(ref _constantBufferData), (uint)sizeof(SceneConstantBuffer));
            }

            return(constantBuffer);
        }
    }
Exemplo n.º 6
0
 /// <summary>
 /// Create a new upload buffer
 /// </summary>
 /// <param name="device">The device to create the buffer on</param>
 /// <param name="resourceDesc">The resource to create</param>
 /// <param name="state">The initial state of the buffer</param>
 /// <param name="flags">Any other heap flags</param>
 public UploadBuffer(
     ID3D12Device *device,
     D3D12_RESOURCE_DESC resourceDesc,
     D3D12_RESOURCE_STATES state,
     D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE)
     : base(device, resourceDesc, state, D3D12_HEAP_TYPE.D3D12_HEAP_TYPE_UPLOAD, flags)
 {
 }
Exemplo n.º 7
0
        protected virtual ID3D12Resource *CreateVertexBuffer(out D3D12_VERTEX_BUFFER_VIEW vertexBufferView)
        {
            // Define the geometry for a triangle.
            const int TriangleVerticesCount = 3;
            var       triangleVertices      = stackalloc Vertex[TriangleVerticesCount] {
                new Vertex {
                    Position = new Vector3(0.0f, 0.25f * AspectRatio, 0.0f),
                    Color    = new Vector4(1.0f, 0.0f, 0.0f, 1.0f)
                },
                new Vertex {
                    Position = new Vector3(0.25f, -0.25f * AspectRatio, 0.0f),
                    Color    = new Vector4(0.0f, 1.0f, 0.0f, 1.0f)
                },
                new Vertex {
                    Position = new Vector3(-0.25f, -0.25f * AspectRatio, 0.0f),
                    Color    = new Vector4(0.0f, 0.0f, 1.0f, 1.0f)
                },
            };

            var vertexBufferSize = (uint)sizeof(Vertex) * TriangleVerticesCount;

            // Note: using upload heaps to transfer static data like vert buffers is not
            // recommended. Every time the GPU needs it, the upload heap will be marshalled
            // over. Please read up on Default Heap usage. An upload heap is used here for
            // code simplicity and because there are very few verts to actually transfer.
            ID3D12Resource *vertexBuffer;

            var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
            var bufferDesc     = D3D12_RESOURCE_DESC.Buffer(vertexBufferSize);

            var iid = IID_ID3D12Resource;

            ThrowIfFailed(nameof(ID3D12Device.CreateCommittedResource), D3DDevice->CreateCommittedResource(
                              &heapProperties,
                              D3D12_HEAP_FLAG_NONE,
                              &bufferDesc,
                              D3D12_RESOURCE_STATE_GENERIC_READ,
                              pOptimizedClearValue: null,
                              &iid,
                              (void **)&vertexBuffer
                              ));

            // Copy the triangle data to the vertex buffer.
            var readRange = new D3D12_RANGE();

            byte *pVertexDataBegin;

            ThrowIfFailed(nameof(ID3D12Resource.Map), vertexBuffer->Map(Subresource: 0, &readRange, (void **)&pVertexDataBegin));
            Unsafe.CopyBlock(pVertexDataBegin, triangleVertices, vertexBufferSize);
            vertexBuffer->Unmap(0, null);

            // Initialize the vertex buffer view.
            vertexBufferView.BufferLocation = vertexBuffer->GetGPUVirtualAddress();
            vertexBufferView.StrideInBytes  = (uint)sizeof(Vertex);
            vertexBufferView.SizeInBytes    = vertexBufferSize;

            return(vertexBuffer);
        }
Exemplo n.º 8
0
 /// <summary>
 /// Create a new default buffer
 /// </summary>
 /// <param name="device">The device to create the buffer on</param>
 /// <param name="resourceDesc">The resource to create</param>
 /// <param name="state">The initial state of the buffer</param>
 /// <param name="flags">Any other heap flags</param>
 /// <param name="optimizedClearValue">If not <code>null</code>, the optimized clear value for the buffer</param>
 public DefaultResource(
     ID3D12Device *device,
     D3D12_RESOURCE_DESC resourceDesc,
     D3D12_RESOURCE_STATES state,
     D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_NONE,
     D3D12_CLEAR_VALUE?optimizedClearValue = null
     )
     : base(device, resourceDesc, state, D3D12_HEAP_TYPE.D3D12_HEAP_TYPE_DEFAULT, flags, optimizedClearValue)
 {
 }
Exemplo n.º 9
0
        private static bool AreCopyable(GpuResource source, GpuResource destination)
        {
            D3D12_RESOURCE_DESC srcDesc  = source.UnderlyingResource->GetDesc();
            D3D12_RESOURCE_DESC destDesc = destination.UnderlyingResource->GetDesc();

            return(srcDesc.Width == destDesc.Width &&
                   srcDesc.Height == destDesc.Height &&
                   srcDesc.DepthOrArraySize == destDesc.DepthOrArraySize &&
                   srcDesc.Dimension == destDesc.Dimension);
        }
Exemplo n.º 10
0
        private Pointer <ID3D12Resource> CreateD3D12Resource()
        {
            _state.ThrowIfDisposedOrDisposing();

            ID3D12Resource *d3d12Resource;

            var textureDesc = Kind switch {
                GraphicsTextureKind.OneDimensional => D3D12_RESOURCE_DESC.Tex1D(DXGI_FORMAT_R8G8B8A8_UNORM, Width, mipLevels: 1),
                GraphicsTextureKind.TwoDimensional => D3D12_RESOURCE_DESC.Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, Width, Height, mipLevels: 1),
                GraphicsTextureKind.ThreeDimensional => D3D12_RESOURCE_DESC.Tex3D(DXGI_FORMAT_R8G8B8A8_UNORM, Width, Height, Depth, mipLevels: 1),
                _ => default,
Exemplo n.º 11
0
    public static ulong UpdateSubresources(ID3D12GraphicsCommandList *pCmdList, ID3D12Resource *pDestinationResource, ID3D12Resource *pIntermediate, uint FirstSubresource, uint NumSubresources, [NativeTypeName("UINT64")] ulong RequiredSize, [NativeTypeName("const D3D12_PLACED_SUBRESOURCE_FOOTPRINT *")] D3D12_PLACED_SUBRESOURCE_FOOTPRINT *pLayouts, [NativeTypeName("const UINT *")] uint *pNumRows, [NativeTypeName("const UINT64 *")] ulong *pRowSizesInBytes, [NativeTypeName("const D3D12_SUBRESOURCE_DATA *")] D3D12_SUBRESOURCE_DATA *pSrcData)
    {
        D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc();

        D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc();

        if (unchecked (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || RequiredSize > (nuint)(-1)) || (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && (FirstSubresource != 0 || NumSubresources != 1)))
        {
            return(0);
        }

        byte *  pData;
        HRESULT hr = pIntermediate->Map(0, null, (void **)(&pData));

        if ((((HRESULT)(hr)) < 0))
        {
            return(0);
        }

        for (uint i = 0; i < NumSubresources; ++i)
        {
            if (pRowSizesInBytes[i] > unchecked ((nuint)(-1)))
            {
                return(0);
            }

            D3D12_MEMCPY_DEST DestData = new D3D12_MEMCPY_DEST
            {
                pData      = pData + pLayouts[i].Offset,
                RowPitch   = pLayouts[i].Footprint.RowPitch,
                SlicePitch = unchecked ((nuint)(pLayouts[i].Footprint.RowPitch) * (nuint)(pNumRows[i])),
            };

            MemcpySubresource(&DestData, &pSrcData[i], unchecked ((nuint)(pRowSizesInBytes[i])), pNumRows[i], pLayouts[i].Footprint.Depth);
        }

        pIntermediate->Unmap(0, null);
        if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
        {
            pCmdList->CopyBufferRegion(pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);
        }
        else
        {
            for (uint i = 0; i < NumSubresources; ++i)
            {
                D3D12_TEXTURE_COPY_LOCATION Dst = new D3D12_TEXTURE_COPY_LOCATION(pDestinationResource, i + FirstSubresource);
                D3D12_TEXTURE_COPY_LOCATION Src = new D3D12_TEXTURE_COPY_LOCATION(pIntermediate, pLayouts[i]);

                pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, null);
            }
        }

        return(RequiredSize);
    }
Exemplo n.º 12
0
        public virtual D3D12_RESOURCE_ALLOCATION_INFO GetResourceAllocationInfo(
            uint visibleMask,
            uint numResourceDescs,
            ref D3D12_RESOURCE_DESC pResourceDescs
            )
        {
            var fp = GetFunctionPointer(25);

            if (m_GetResourceAllocationInfoFunc == null)
            {
                m_GetResourceAllocationInfoFunc = (GetResourceAllocationInfoFunc)Marshal.GetDelegateForFunctionPointer(fp, typeof(GetResourceAllocationInfoFunc));
            }

            return(m_GetResourceAllocationInfoFunc(m_ptr, visibleMask, numResourceDescs, ref pResourceDescs));
        }
Exemplo n.º 13
0
        public virtual int CreateReservedResource(
            ref D3D12_RESOURCE_DESC pDesc,
            D3D12_RESOURCE_STATES InitialState,
            ref D3D12_CLEAR_VALUE pOptimizedClearValue,
            ref Guid riid,
            out IntPtr ppvResource
            )
        {
            var fp = GetFunctionPointer(30);

            if (m_CreateReservedResourceFunc == null)
            {
                m_CreateReservedResourceFunc = (CreateReservedResourceFunc)Marshal.GetDelegateForFunctionPointer(fp, typeof(CreateReservedResourceFunc));
            }

            return(m_CreateReservedResourceFunc(m_ptr, ref pDesc, InitialState, ref pOptimizedClearValue, ref riid, out ppvResource));
        }
Exemplo n.º 14
0
        public virtual int CreateReservedResource1(
            ref D3D12_RESOURCE_DESC pDesc,
            D3D12_RESOURCE_STATES InitialState,
            ref D3D12_CLEAR_VALUE pOptimizedClearValue,
            ID3D12ProtectedResourceSession pProtectedSession,
            ref Guid riid,
            out IntPtr ppvResource
            )
        {
            var fp = GetFunctionPointer(55);

            if (m_CreateReservedResource1Func == null)
            {
                m_CreateReservedResource1Func = (CreateReservedResource1Func)Marshal.GetDelegateForFunctionPointer(fp, typeof(CreateReservedResource1Func));
            }

            return(m_CreateReservedResource1Func(m_ptr, ref pDesc, InitialState, ref pOptimizedClearValue, pProtectedSession != null ? pProtectedSession.Ptr : IntPtr.Zero, ref riid, out ppvResource));
        }
Exemplo n.º 15
0
        public virtual int CreateCommittedResource(
            ref D3D12_HEAP_PROPERTIES pHeapProperties,
            D3D12_HEAP_FLAGS HeapFlags,
            ref D3D12_RESOURCE_DESC pDesc,
            D3D12_RESOURCE_STATES InitialResourceState,
            ref D3D12_CLEAR_VALUE pOptimizedClearValue,
            ref Guid riidResource,
            out IntPtr ppvResource
            )
        {
            var fp = GetFunctionPointer(27);

            if (m_CreateCommittedResourceFunc == null)
            {
                m_CreateCommittedResourceFunc = (CreateCommittedResourceFunc)Marshal.GetDelegateForFunctionPointer(fp, typeof(CreateCommittedResourceFunc));
            }

            return(m_CreateCommittedResourceFunc(m_ptr, ref pHeapProperties, HeapFlags, ref pDesc, InitialResourceState, ref pOptimizedClearValue, ref riidResource, out ppvResource));
        }
Exemplo n.º 16
0
        public virtual int CreatePlacedResource(
            ID3D12Heap pHeap,
            ulong HeapOffset,
            ref D3D12_RESOURCE_DESC pDesc,
            D3D12_RESOURCE_STATES InitialState,
            ref D3D12_CLEAR_VALUE pOptimizedClearValue,
            ref Guid riid,
            out IntPtr ppvResource
            )
        {
            var fp = GetFunctionPointer(29);

            if (m_CreatePlacedResourceFunc == null)
            {
                m_CreatePlacedResourceFunc = (CreatePlacedResourceFunc)Marshal.GetDelegateForFunctionPointer(fp, typeof(CreatePlacedResourceFunc));
            }

            return(m_CreatePlacedResourceFunc(m_ptr, pHeap != null ? pHeap.Ptr : IntPtr.Zero, HeapOffset, ref pDesc, InitialState, ref pOptimizedClearValue, ref riid, out ppvResource));
        }
Exemplo n.º 17
0
        public virtual void GetCopyableFootprints(
            ref D3D12_RESOURCE_DESC pResourceDesc,
            uint FirstSubresource,
            uint NumSubresources,
            ulong BaseOffset,
            out D3D12_PLACED_SUBRESOURCE_FOOTPRINT pLayouts,
            out uint pNumRows,
            out ulong pRowSizeInBytes,
            out ulong pTotalBytes
            )
        {
            var fp = GetFunctionPointer(38);

            if (m_GetCopyableFootprintsFunc == null)
            {
                m_GetCopyableFootprintsFunc = (GetCopyableFootprintsFunc)Marshal.GetDelegateForFunctionPointer(fp, typeof(GetCopyableFootprintsFunc));
            }

            m_GetCopyableFootprintsFunc(m_ptr, ref pResourceDesc, FirstSubresource, NumSubresources, BaseOffset, out pLayouts, out pNumRows, out pRowSizeInBytes, out pTotalBytes);
        }
Exemplo n.º 18
0
    /// <summary>
    /// Applies the actual resize logic that was scheduled from <see cref="OnResize"/>.
    /// </summary>
    private unsafe void ApplyResize()
    {
        this.d3D12CommandQueue.Get()->Signal(this.d3D12Fence.Get(), this.nextD3D12FenceValue);

        // Wait for the fence again to ensure there are no pending operations
        this.d3D12Fence.Get()->SetEventOnCompletion(this.nextD3D12FenceValue, default);

        this.nextD3D12FenceValue++;

        // Dispose the old buffers before resizing the buffer
        this.d3D12Resource0.Dispose();
        this.d3D12Resource1.Dispose();

        // Resize the swap chain buffers
        this.dxgiSwapChain1.Get()->ResizeBuffers(0, 0, 0, DXGI_FORMAT.DXGI_FORMAT_UNKNOWN, 0);

        // Get the index of the initial back buffer
        using (ComPtr <IDXGISwapChain3> dxgiSwapChain3 = default)
        {
            _ = this.dxgiSwapChain1.CopyTo(dxgiSwapChain3.GetAddressOf());

            this.currentBufferIndex = dxgiSwapChain3.Get()->GetCurrentBackBufferIndex();
        }

        // Retrieve the back buffers for the swap chain
        fixed(ID3D12Resource **d3D12Resource0 = this.d3D12Resource0)
        fixed(ID3D12Resource **d3D12Resource1 = this.d3D12Resource1)
        {
            _ = dxgiSwapChain1.Get()->GetBuffer(0, Windows.__uuidof <ID3D12Resource>(), (void **)d3D12Resource0);
            _ = dxgiSwapChain1.Get()->GetBuffer(1, Windows.__uuidof <ID3D12Resource>(), (void **)d3D12Resource1);
        }

        this.texture?.Dispose();

        D3D12_RESOURCE_DESC d3D12Resource0Description = this.d3D12Resource0.Get()->GetDesc();

        // Create the 2D texture to use to generate frames to display
        this.texture = GraphicsDevice.Default.AllocateReadWriteTexture2D <Rgba32, float4>(
            (int)d3D12Resource0Description.Width,
            (int)d3D12Resource0Description.Height);
    }
    protected override ID3D12Resource *CreateDepthStencil()
    {
        ID3D12Resource *depthStencil;

        var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

        var resourceDesc = D3D12_RESOURCE_DESC.Tex2D(DepthBufferFormat, (uint)Size.Width, (uint)Size.Height, 1, 1, _msaaDesc.Count, _msaaDesc.Quality);

        resourceDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;

        var clearValue = new D3D12_CLEAR_VALUE(DepthBufferFormat, 1.0f, 0);

        ThrowIfFailed(D3DDevice->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue, __uuidof <ID3D12Resource>(), (void **)&depthStencil));

        var dsvDesc = new D3D12_DEPTH_STENCIL_VIEW_DESC {
            Format        = DepthBufferFormat,
            ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMS
        };

        D3DDevice->CreateDepthStencilView(depthStencil, &dsvDesc, DSVHeap->GetCPUDescriptorHandleForHeapStart());

        return(depthStencil);
    }
Exemplo n.º 20
0
        private Pointer <ID3D12Resource> CreateD3D12Resource()
        {
            _state.ThrowIfDisposedOrDisposing();

            ID3D12Resource *d3d12Resource;

            var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
            var bufferDesc     = D3D12_RESOURCE_DESC.Buffer(width: Size);

            var iid = IID_ID3D12Resource;

            ThrowExternalExceptionIfFailed(nameof(ID3D12Device.CreateCommittedResource), D3D12GraphicsDevice.D3D12Device->CreateCommittedResource(
                                               &heapProperties,
                                               D3D12_HEAP_FLAG_NONE,
                                               &bufferDesc,
                                               D3D12_RESOURCE_STATE_GENERIC_READ,
                                               pOptimizedClearValue: null,
                                               &iid,
                                               (void **)&d3d12Resource
                                               ));

            return(d3d12Resource);
        }
    protected override void CreateWindowSizeDependentResources()
    {
        _msaaRenderTargets = CreateMSAARenderTargets();
        base.CreateWindowSizeDependentResources();

        ID3D12Resource *[] CreateMSAARenderTargets()
        {
            var msaaRenderTargets = new ID3D12Resource *[FrameCount];

            var desc = new D3D12_RESOURCE_DESC {
                Height           = (uint)Size.Height,
                Width            = (uint)Size.Width,
                DepthOrArraySize = 1,
                SampleDesc       = _msaaDesc,
                Dimension        = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
                Flags            = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
                Format           = BackBufferFormat,
                MipLevels        = 1
            };

            var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

            var clearColor = BackgroundColor;
            var clearValue = new D3D12_CLEAR_VALUE(BackBufferFormat, (float *)&clearColor);

            var iid = __uuidof <ID3D12Resource>();

            for (var i = 0u; i < FrameCount; i++)
            {
                ID3D12Resource *msaaRenderTarget;
                ThrowIfFailed(D3DDevice->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_RENDER_TARGET, &clearValue, iid, (void **)&msaaRenderTarget));
                msaaRenderTargets[i] = msaaRenderTarget;
            }

            return(msaaRenderTargets);
        }
    }
Exemplo n.º 22
0
        // Load the sample assets.
        private void LoadAssets()
        {
            Guid      iid;
            ID3DBlob *signature    = null;
            ID3DBlob *error        = null;
            ID3DBlob *vertexShader = null;
            ID3DBlob *pixelShader  = null;

            try
            {
                // Create an empty root signature.
                {
                    var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC {
                        Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT
                    };

                    ThrowIfFailed(nameof(D3D12SerializeRootSignature), D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));

                    fixed(ID3D12RootSignature **rootSignature = &_rootSignature)
                    {
                        iid = IID_ID3D12RootSignature;
                        ThrowIfFailed(nameof(ID3D12Device.CreateRootSignature), _device->CreateRootSignature(nodeMask: 0, signature->GetBufferPointer(), signature->GetBufferSize(), &iid, (void **)rootSignature));
                    }
                }

                // Create the pipeline state, which includes compiling and loading shaders.
                {
                    var compileFlags = 0u;

#if DEBUG
                    // Enable better shader debugging with the graphics debugging tools.
                    compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
                    fixed(char *fileName = GetAssetFullPath(@"D3D12\Assets\Shaders\HelloTriangle.hlsl"))
                    {
                        var entryPoint = 0x00006E69614D5356;    // VSMain
                        var target     = 0x0000305F355F7376;    // vs_5_0

                        ThrowIfFailed(nameof(D3DCompileFromFile), D3DCompileFromFile((ushort *)fileName, pDefines: null, pInclude: null, (sbyte *)&entryPoint, (sbyte *)&target, compileFlags, Flags2: 0, &vertexShader, ppErrorMsgs: null));

                        entryPoint = 0x00006E69614D5350;        // PSMain
                        target     = 0x0000305F355F7370;        // ps_5_0
                        ThrowIfFailed(nameof(D3DCompileFromFile), D3DCompileFromFile((ushort *)fileName, pDefines: null, pInclude: null, (sbyte *)&entryPoint, (sbyte *)&target, compileFlags, Flags2: 0, &pixelShader, ppErrorMsgs: null));
                    }

                    // Define the vertex input layout.
                    const int InputElementDescsCount = 2;

                    var semanticName0 = stackalloc ulong[2] {
                        0x4E4F495449534F50,     // POSITION
                        0x0000000000000000,
                    };

                    var semanticName1 = stackalloc ulong[1] {
                        0x000000524F4C4F43,     // COLOR
                    };

                    var inputElementDescs = stackalloc D3D12_INPUT_ELEMENT_DESC[InputElementDescsCount] {
                        new D3D12_INPUT_ELEMENT_DESC {
                            SemanticName   = (sbyte *)semanticName0,
                            Format         = DXGI_FORMAT_R32G32B32_FLOAT,
                            InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
                        },
                        new D3D12_INPUT_ELEMENT_DESC {
                            SemanticName      = (sbyte *)semanticName1,
                            Format            = DXGI_FORMAT_R32G32B32A32_FLOAT,
                            AlignedByteOffset = 12,
                            InputSlotClass    = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
                        },
                    };

                    // Describe and create the graphics pipeline state object (PSO).
                    var psoDesc = new D3D12_GRAPHICS_PIPELINE_STATE_DESC {
                        InputLayout = new D3D12_INPUT_LAYOUT_DESC {
                            pInputElementDescs = inputElementDescs,
                            NumElements        = InputElementDescsCount,
                        },
                        pRootSignature        = _rootSignature,
                        VS                    = new D3D12_SHADER_BYTECODE(vertexShader),
                        PS                    = new D3D12_SHADER_BYTECODE(pixelShader),
                        RasterizerState       = D3D12_RASTERIZER_DESC.DEFAULT,
                        BlendState            = D3D12_BLEND_DESC.DEFAULT,
                        DepthStencilState     = D3D12_DEPTH_STENCIL_DESC.DEFAULT,
                        SampleMask            = uint.MaxValue,
                        PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
                        NumRenderTargets      = 1,
                        SampleDesc            = new DXGI_SAMPLE_DESC(count: 1, quality: 0),
                    };
                    psoDesc.DepthStencilState.DepthEnable = FALSE;
                    psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;

                    fixed(ID3D12PipelineState **pipelineState = &_pipelineState)
                    {
                        iid = IID_ID3D12PipelineState;
                        ThrowIfFailed(nameof(ID3D12Device.CreateGraphicsPipelineState), _device->CreateGraphicsPipelineState(&psoDesc, &iid, (void **)pipelineState));
                    }
                }

                // Create the command list.
                fixed(ID3D12GraphicsCommandList **commandList = &_commandList)
                {
                    iid = IID_ID3D12GraphicsCommandList;
                    ThrowIfFailed(nameof(ID3D12Device.CreateCommandList), _device->CreateCommandList(nodeMask: 0, D3D12_COMMAND_LIST_TYPE_DIRECT, _commandAllocator, _pipelineState, &iid, (void **)commandList));
                }

                // Command lists are created in the recording state, but there is nothing
                // to record yet. The main loop expects it to be closed, so close it now.
                ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Close), _commandList->Close());

                // Create the vertex buffer.
                {
                    // Define the geometry for a triangle.
                    const int TriangleVerticesCount = 3;
                    var       triangleVertices      = stackalloc Vertex[TriangleVerticesCount] {
                        new Vertex {
                            Position = new Vector3(0.0f, 0.25f * AspectRatio, 0.0f),
                            Color    = new Vector4(1.0f, 0.0f, 0.0f, 1.0f)
                        },
                        new Vertex {
                            Position = new Vector3(0.25f, -0.25f * AspectRatio, 0.0f),
                            Color    = new Vector4(0.0f, 1.0f, 0.0f, 1.0f)
                        },
                        new Vertex {
                            Position = new Vector3(-0.25f, -0.25f * AspectRatio, 0.0f),
                            Color    = new Vector4(0.0f, 0.0f, 1.0f, 1.0f)
                        },
                    };

                    var vertexBufferSize = (uint)sizeof(Vertex) * TriangleVerticesCount;

                    // Note: using upload heaps to transfer static data like vert buffers is not
                    // recommended. Every time the GPU needs it, the upload heap will be marshalled
                    // over. Please read up on Default Heap usage. An upload heap is used here for
                    // code simplicity and because there are very few verts to actually transfer.
                    fixed(ID3D12Resource **vertexBuffer = &_vertexBuffer)
                    {
                        var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
                        var bufferDesc     = D3D12_RESOURCE_DESC.Buffer(vertexBufferSize);

                        iid = IID_ID3D12Resource;
                        ThrowIfFailed(nameof(ID3D12Device.CreateCommittedResource), _device->CreateCommittedResource(
                                          &heapProperties,
                                          D3D12_HEAP_FLAG_NONE,
                                          &bufferDesc,
                                          D3D12_RESOURCE_STATE_GENERIC_READ,
                                          pOptimizedClearValue: null,
                                          &iid,
                                          (void **)vertexBuffer
                                          ));
                    }

                    // Copy the triangle data to the vertex buffer.
                    var readRange = new D3D12_RANGE();

                    byte *pVertexDataBegin;
                    ThrowIfFailed(nameof(ID3D12Resource.Map), _vertexBuffer->Map(Subresource: 0, &readRange, (void **)&pVertexDataBegin));
                    Unsafe.CopyBlock(pVertexDataBegin, triangleVertices, vertexBufferSize);
                    _vertexBuffer->Unmap(0, null);

                    // Initialize the vertex buffer view.
                    _vertexBufferView.BufferLocation = _vertexBuffer->GetGPUVirtualAddress();
                    _vertexBufferView.StrideInBytes  = (uint)sizeof(Vertex);
                    _vertexBufferView.SizeInBytes    = vertexBufferSize;
                }

                // Create and record the bundle.
                {
                    fixed(ID3D12GraphicsCommandList **ppBundle = &_bundle)
                    {
                        iid = IID_ID3D12GraphicsCommandList;
                        ThrowIfFailed(nameof(ID3D12Device.CreateCommandList), _device->CreateCommandList(nodeMask: 0, D3D12_COMMAND_LIST_TYPE_BUNDLE, _bundleAllocator, _pipelineState, &iid, (void **)ppBundle));
                    }

                    _bundle->SetGraphicsRootSignature(_rootSignature);
                    _bundle->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

                    fixed(D3D12_VERTEX_BUFFER_VIEW *vertexBufferView = &_vertexBufferView)
                    {
                        _bundle->IASetVertexBuffers(StartSlot: 0, 1, vertexBufferView);
                    }

                    _bundle->DrawInstanced(3, 1, 0, 0);
                    ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Close), _bundle->Close());
                }

                // Create synchronization objects and wait until assets have been uploaded to the GPU.
                {
                    fixed(ID3D12Fence **fence = &_fence)
                    {
                        iid = IID_ID3D12Fence;
                        ThrowIfFailed(nameof(ID3D12Device.CreateFence), _device->CreateFence(0, D3D12_FENCE_FLAG_NONE, &iid, (void **)fence));
                        _fenceValue = 1;
                    }

                    // Create an event handle to use for frame synchronization.
                    _fenceEvent = CreateEventW(lpEventAttributes: null, bManualReset: FALSE, bInitialState: FALSE, lpName: null);
                    if (_fenceEvent == null)
                    {
                        var hr = Marshal.GetHRForLastWin32Error();
                        Marshal.ThrowExceptionForHR(hr);
                    }

                    // Wait for the command list to execute; we are reusing the same command
                    // list in our main loop but for now, we just want to wait for setup to
                    // complete before continuing.
                    WaitForPreviousFrame();
                }
            }
            finally
            {
                if (signature != null)
                {
                    signature->Release();
                }

                if (error != null)
                {
                    error->Release();
                }

                if (vertexShader != null)
                {
                    vertexShader->Release();
                }

                if (pixelShader != null)
                {
                    pixelShader->Release();
                }
            }
        }
Exemplo n.º 23
0
    protected override void CreateAssets()
    {
        using ComPtr <ID3D12Resource> textureUploadHeap = null;

        _texture = CreateTexture();
        base.CreateAssets();

        ID3D12Resource *CreateTexture()
        {
            // Describe and create a Texture2D.
            var textureDesc = new D3D12_RESOURCE_DESC {
                MipLevels        = 1,
                Format           = DXGI_FORMAT_R8G8B8A8_UNORM,
                Width            = TextureWidth,
                Height           = TextureHeight,
                Flags            = D3D12_RESOURCE_FLAG_NONE,
                DepthOrArraySize = 1,
                SampleDesc       = new DXGI_SAMPLE_DESC {
                    Count   = 1,
                    Quality = 0,
                },
                Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
            };

            ID3D12Resource *texture;
            var             iid = __uuidof <ID3D12Resource>();

            var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

            ThrowIfFailed(D3DDevice->CreateCommittedResource(
                              &heapProperties,
                              D3D12_HEAP_FLAG_NONE,
                              &textureDesc,
                              D3D12_RESOURCE_STATE_COPY_DEST,
                              pOptimizedClearValue: null,
                              iid,
                              (void **)&texture
                              ));

            var uploadBufferSize = GetRequiredIntermediateSize(texture, 0, 1);

            // Create the GPU upload buffer.
            heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
            var bufferDesc = D3D12_RESOURCE_DESC.Buffer(uploadBufferSize);

            ThrowIfFailed(D3DDevice->CreateCommittedResource(
                              &heapProperties,
                              D3D12_HEAP_FLAG_NONE,
                              &bufferDesc,
                              D3D12_RESOURCE_STATE_GENERIC_READ,
                              pOptimizedClearValue: null,
                              iid,
                              (void **)textureUploadHeap.GetAddressOf()
                              ));

            // Copy data to the intermediate upload heap and then schedule a copy
            // from the upload heap to the Texture2D.
            var textureData = GenerateTextureData();
            var rowPitch    = TextureWidth * TexturePixelSize;
            var slicePitch  = rowPitch * TextureHeight;
            D3D12_SUBRESOURCE_DATA textureSubresourceData;

            fixed(byte *pTextureData = &textureData[0])
            {
                textureSubresourceData = new D3D12_SUBRESOURCE_DATA {
                    pData      = (void *)pTextureData,
                    RowPitch   = (nint)rowPitch,
                    SlicePitch = (nint)slicePitch,
                };
            }

            _ = UpdateSubresources(GraphicsCommandList, texture, textureUploadHeap, 0, 0, 1, &textureSubresourceData);
            var barrier = D3D12_RESOURCE_BARRIER.InitTransition(texture, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);

            GraphicsCommandList->ResourceBarrier(1, &barrier);

            // Describe and create a SRV for the texture.
            var srvDesc = new D3D12_SHADER_RESOURCE_VIEW_DESC {
                Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
                Format        = textureDesc.Format,
                ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D,
            };

            srvDesc.Anonymous.Texture2D.MipLevels = 1;

            D3DDevice->CreateShaderResourceView(texture, &srvDesc, _srvHeap->GetCPUDescriptorHandleForHeapStart());

            return(texture);
        }

        byte[] GenerateTextureData()
        {
            const uint RowPitch    = TextureWidth * TexturePixelSize;
            const uint CellPitch   = RowPitch >> 3;      // The width of a cell in the checkboard texture.
            const uint CellHeight  = TextureWidth >> 3;  // The height of a cell in the checkerboard texture.
            const uint TextureSize = RowPitch * TextureHeight;

            var data = new byte[TextureSize];

            fixed(byte *pData = &data[0])
            {
                for (uint n = 0; n < TextureSize; n += TexturePixelSize)
                {
                    var x = n % RowPitch;
                    var y = n / RowPitch;
                    var i = x / CellPitch;
                    var j = y / CellHeight;

                    if (i % 2 == j % 2)
                    {
                        pData[n]     = 0x00;    // R
                        pData[n + 1] = 0x00;    // G
                        pData[n + 2] = 0x00;    // B
                        pData[n + 3] = 0xff;    // A
                    }
                    else
                    {
                        pData[n]     = 0xff;    // R
                        pData[n + 1] = 0xff;    // G
                        pData[n + 2] = 0xff;    // B
                        pData[n + 3] = 0xff;    // A
                    }
                }
            }

            return(data);
        }
    }
Exemplo n.º 24
0
        // Load the sample assets.
        private void LoadAssets()
        {
            Guid      iid;
            ID3DBlob *signature    = null;
            ID3DBlob *error        = null;
            ID3DBlob *vertexShader = null;
            ID3DBlob *pixelShader  = null;

            try
            {
                // Create the root signature.
                {
                    var featureData = new D3D12_FEATURE_DATA_ROOT_SIGNATURE {
                        // This is the highest version the sample supports. If CheckFeatureSupport succeeds, the HighestVersion returned will not be greater than this.
                        HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1
                    };

                    if (FAILED(_device->CheckFeatureSupport(D3D12_FEATURE_ROOT_SIGNATURE, &featureData, (uint)sizeof(D3D12_FEATURE))))
                    {
                        featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0;
                    }

                    const int RangesCount = 1;
                    var       ranges      = stackalloc D3D12_DESCRIPTOR_RANGE1[RangesCount];
                    ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC);

                    const int RootParametersCount = 1;
                    var       rootParameters      = stackalloc D3D12_ROOT_PARAMETER1[RootParametersCount];
                    rootParameters[0].InitAsDescriptorTable(1, ranges, D3D12_SHADER_VISIBILITY_PIXEL);

                    var sampler = new D3D12_STATIC_SAMPLER_DESC {
                        Filter           = D3D12_FILTER.D3D12_FILTER_MIN_MAG_MIP_POINT,
                        AddressU         = D3D12_TEXTURE_ADDRESS_MODE_BORDER,
                        AddressV         = D3D12_TEXTURE_ADDRESS_MODE_BORDER,
                        AddressW         = D3D12_TEXTURE_ADDRESS_MODE_BORDER,
                        MipLODBias       = 0,
                        MaxAnisotropy    = 0,
                        ComparisonFunc   = D3D12_COMPARISON_FUNC_NEVER,
                        BorderColor      = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK,
                        MinLOD           = 0.0f,
                        MaxLOD           = D3D12_FLOAT32_MAX,
                        ShaderRegister   = 0,
                        RegisterSpace    = 0,
                        ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL,
                    };

                    var rootSignatureDesc = new D3D12_VERSIONED_ROOT_SIGNATURE_DESC();
                    rootSignatureDesc.Init_1_1(RootParametersCount, rootParameters, 1, &sampler, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);

                    ThrowIfFailed(nameof(D3D12SerializeVersionedRootSignature), D3D12SerializeVersionedRootSignature(
                                      &rootSignatureDesc, featureData.HighestVersion, &signature, &error));

                    fixed(ID3D12RootSignature **rootSignature = &_rootSignature)
                    {
                        iid = IID_ID3D12RootSignature;
                        ThrowIfFailed(nameof(ID3D12Device.CreateRootSignature), _device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), &iid, (void **)rootSignature));
                    }
                }

                // Create the pipeline state, which includes compiling and loading shaders.
                {
                    var compileFlags = 0u;

#if DEBUG
                    // Enable better shader debugging with the graphics debugging tools.
                    compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
                    fixed(char *fileName = GetAssetFullPath(@"D3D12\Assets\Shaders\HelloTexture.hlsl"))
                    {
                        var entryPoint = 0x00006E69614D5356;    // VSMain
                        var target     = 0x0000305F355F7376;    // vs_5_0

                        ThrowIfFailed(nameof(D3DCompileFromFile), D3DCompileFromFile((ushort *)fileName, pDefines: null, pInclude: null, (sbyte *)&entryPoint, (sbyte *)&target, compileFlags, Flags2: 0, &vertexShader, ppErrorMsgs: null));

                        entryPoint = 0x00006E69614D5350;        // PSMain
                        target     = 0x0000305F355F7370;        // ps_5_0
                        ThrowIfFailed(nameof(D3DCompileFromFile), D3DCompileFromFile((ushort *)fileName, pDefines: null, pInclude: null, (sbyte *)&entryPoint, (sbyte *)&target, compileFlags, Flags2: 0, &pixelShader, ppErrorMsgs: null));
                    }

                    // Define the vertex input layout.
                    const int InputElementDescsCount = 2;

                    var semanticName0 = stackalloc ulong[2] {
                        0x4E4F495449534F50,     // POSITION
                        0x0000000000000000,
                    };

                    var semanticName1 = stackalloc ulong[2] {
                        0x44524F4F43584554,     // TEXCOORD
                        0x0000000000000000,
                    };

                    var inputElementDescs = stackalloc D3D12_INPUT_ELEMENT_DESC[InputElementDescsCount] {
                        new D3D12_INPUT_ELEMENT_DESC {
                            SemanticName   = (sbyte *)semanticName0,
                            Format         = DXGI_FORMAT_R32G32B32_FLOAT,
                            InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
                        },
                        new D3D12_INPUT_ELEMENT_DESC {
                            SemanticName      = (sbyte *)semanticName1,
                            Format            = DXGI_FORMAT_R32G32_FLOAT,
                            AlignedByteOffset = 12,
                            InputSlotClass    = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
                        },
                    };

                    // Describe and create the graphics pipeline state object (PSO).
                    var psoDesc = new D3D12_GRAPHICS_PIPELINE_STATE_DESC {
                        InputLayout = new D3D12_INPUT_LAYOUT_DESC {
                            pInputElementDescs = inputElementDescs,
                            NumElements        = InputElementDescsCount,
                        },
                        pRootSignature    = _rootSignature,
                        VS                = new D3D12_SHADER_BYTECODE(vertexShader),
                        PS                = new D3D12_SHADER_BYTECODE(pixelShader),
                        RasterizerState   = D3D12_RASTERIZER_DESC.DEFAULT,
                        BlendState        = D3D12_BLEND_DESC.DEFAULT,
                        DepthStencilState = new D3D12_DEPTH_STENCIL_DESC {
                            DepthEnable   = FALSE,
                            StencilEnable = FALSE,
                        },
                        SampleMask            = uint.MaxValue,
                        PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
                        NumRenderTargets      = 1,
                        SampleDesc            = new DXGI_SAMPLE_DESC(count: 1, quality: 0),
                    };
                    psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;

                    fixed(ID3D12PipelineState **pipelineState = &_pipelineState)
                    {
                        iid = IID_ID3D12PipelineState;
                        ThrowIfFailed(nameof(ID3D12Device.CreateGraphicsPipelineState), _device->CreateGraphicsPipelineState(&psoDesc, &iid, (void **)pipelineState));
                    }
                }

                // Create the command list.
                fixed(ID3D12GraphicsCommandList **commandList = &_commandList)
                {
                    iid = IID_ID3D12GraphicsCommandList;
                    ThrowIfFailed(nameof(ID3D12Device.CreateCommandList), _device->CreateCommandList(nodeMask: 0, D3D12_COMMAND_LIST_TYPE_DIRECT, _commandAllocator, _pipelineState, &iid, (void **)commandList));
                }

                // Create the vertex buffer.
                {
                    // Define the geometry for a triangle.
                    const int TriangleVerticesCount = 3;
                    var       triangleVertices      = stackalloc Vertex[TriangleVerticesCount] {
                        new Vertex {
                            Position = new Vector3(0.0f, 0.25f * AspectRatio, 0.0f),
                            UV       = new Vector2(0.5f, 0.0f)
                        },
                        new Vertex {
                            Position = new Vector3(0.25f, -0.25f * AspectRatio, 0.0f),
                            UV       = new Vector2(1.0f, 1.0f)
                        },
                        new Vertex {
                            Position = new Vector3(-0.25f, -0.25f * AspectRatio, 0.0f),
                            UV       = new Vector2(0.0f, 1.0f)
                        },
                    };

                    var vertexBufferSize = (uint)sizeof(Vertex) * TriangleVerticesCount;

                    // Note: using upload heaps to transfer static data like vert buffers is not
                    // recommended. Every time the GPU needs it, the upload heap will be marshalled
                    // over. Please read up on Default Heap usage. An upload heap is used here for
                    // code simplicity and because there are very few verts to actually transfer.
                    fixed(ID3D12Resource **vertexBuffer = &_vertexBuffer)
                    {
                        var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
                        var bufferDesc     = D3D12_RESOURCE_DESC.Buffer(vertexBufferSize);

                        iid = IID_ID3D12Resource;
                        ThrowIfFailed(nameof(ID3D12Device.CreateCommittedResource), _device->CreateCommittedResource(
                                          &heapProperties,
                                          D3D12_HEAP_FLAG_NONE,
                                          &bufferDesc,
                                          D3D12_RESOURCE_STATE_GENERIC_READ,
                                          pOptimizedClearValue: null,
                                          &iid,
                                          (void **)vertexBuffer
                                          ));
                    }

                    // Copy the triangle data to the vertex buffer.
                    var   readRange = new D3D12_RANGE();
                    byte *pVertexDataBegin;
                    ThrowIfFailed(nameof(ID3D12Resource.Map), _vertexBuffer->Map(Subresource: 0, &readRange, (void **)&pVertexDataBegin));
                    Unsafe.CopyBlock(pVertexDataBegin, triangleVertices, vertexBufferSize);
                    _vertexBuffer->Unmap(0, null);

                    // Initialize the vertex buffer view.
                    _vertexBufferView.BufferLocation = _vertexBuffer->GetGPUVirtualAddress();
                    _vertexBufferView.StrideInBytes  = (uint)sizeof(Vertex);
                    _vertexBufferView.SizeInBytes    = vertexBufferSize;
                }

                // Note: textureUploadHeap needs to stay in scope until
                // the command list that references it has finished executing on the GPU.
                // We will flush the GPU at the end of this method to ensure the resource is not
                // prematurely destroyed.
                ID3D12Resource *textureUploadHeap;

                // Create the texture.
                {
                    // Describe and create a Texture2D.
                    var textureDesc = new D3D12_RESOURCE_DESC {
                        MipLevels        = 1,
                        Format           = DXGI_FORMAT_R8G8B8A8_UNORM,
                        Width            = TextureWidth,
                        Height           = TextureHeight,
                        Flags            = D3D12_RESOURCE_FLAG_NONE,
                        DepthOrArraySize = 1,
                        SampleDesc       = new DXGI_SAMPLE_DESC {
                            Count   = 1,
                            Quality = 0,
                        },
                        Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
                    };

                    fixed(ID3D12Resource **pTexture = &_texture)
                    {
                        var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

                        iid = IID_ID3D12Resource;
                        ThrowIfFailed(nameof(ID3D12Device.CreateCommittedResource), _device->CreateCommittedResource(
                                          &heapProperties,
                                          D3D12_HEAP_FLAG_NONE,
                                          &textureDesc,
                                          D3D12_RESOURCE_STATE_COPY_DEST,
                                          pOptimizedClearValue: null,
                                          &iid,
                                          (void **)pTexture
                                          ));

                        var uploadBufferSize = GetRequiredIntermediateSize(_texture, 0, 1);

                        // Create the GPU upload buffer.
                        heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
                        var bufferDesc = D3D12_RESOURCE_DESC.Buffer(uploadBufferSize);

                        ThrowIfFailed(nameof(ID3D12Device.CreateCommittedResource), _device->CreateCommittedResource(
                                          &heapProperties,
                                          D3D12_HEAP_FLAG_NONE,
                                          &bufferDesc,
                                          D3D12_RESOURCE_STATE_GENERIC_READ,
                                          pOptimizedClearValue: null,
                                          &iid,
                                          (void **)&textureUploadHeap
                                          ));
                    }

                    // Copy data to the intermediate upload heap and then schedule a copy
                    // from the upload heap to the Texture2D.
                    var texture    = GenerateTextureData();
                    var rowPitch   = TextureWidth * TexturePixelSize;
                    var slicePitch = rowPitch * TextureHeight;
                    D3D12_SUBRESOURCE_DATA textureData;
                    fixed(byte *pTexture = &texture[0])
                    {
                        textureData = new D3D12_SUBRESOURCE_DATA {
                            pData      = (void *)pTexture,
                            RowPitch   = (nint)rowPitch,
                            SlicePitch = (nint)slicePitch,
                        };
                    }
                    UpdateSubresources(_commandList, _texture, textureUploadHeap, 0, 0, 1, &textureData);
                    var barrier = D3D12_RESOURCE_BARRIER.InitTransition(_texture, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
                    _commandList->ResourceBarrier(1, &barrier);

                    // Describe and create a SRV for the texture.
                    var srvDesc = new D3D12_SHADER_RESOURCE_VIEW_DESC {
                        Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
                        Format        = textureDesc.Format,
                        ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D,
                    };
                    srvDesc.Anonymous.Texture2D.MipLevels = 1;

                    _device->CreateShaderResourceView(_texture, &srvDesc, _srvHeap->GetCPUDescriptorHandleForHeapStart());
                }

                // Close the command list and execute it to begin the initial GPU setup.
                ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Close), _commandList->Close());

                const int CommandListsCount = 1;
                var       ppCommandLists    = stackalloc ID3D12CommandList *[CommandListsCount] {
                    (ID3D12CommandList *)_commandList,
                };
                _commandQueue->ExecuteCommandLists(CommandListsCount, ppCommandLists);

                // Create synchronization objects and wait until assets have been uploaded to the GPU.
                {
                    fixed(ID3D12Fence **fence = &_fence)
                    {
                        iid = IID_ID3D12Fence;
                        ThrowIfFailed(nameof(ID3D12Device.CreateFence), _device->CreateFence(0, D3D12_FENCE_FLAG_NONE, &iid, (void **)fence));
                        _fenceValue = 1;
                    }

                    // Create an event handle to use for frame synchronization.
                    _fenceEvent = CreateEventW(lpEventAttributes: null, bManualReset: FALSE, bInitialState: FALSE, lpName: null);
                    if (_fenceEvent == null)
                    {
                        var hr = Marshal.GetHRForLastWin32Error();
                        Marshal.ThrowExceptionForHR(hr);
                    }

                    // Wait for the command list to execute; we are reusing the same command
                    // list in our main loop but for now, we just want to wait for setup to
                    // complete before continuing.
                    WaitForPreviousFrame();
                }
            }
            finally
            {
                if (signature != null)
                {
                    signature->Release();
                }

                if (error != null)
                {
                    error->Release();
                }

                if (vertexShader != null)
                {
                    vertexShader->Release();
                }

                if (pixelShader != null)
                {
                    pixelShader->Release();
                }
            }
        }
Exemplo n.º 25
0
        public static ulong UpdateSubresources(ID3D12GraphicsCommandList *pCmdList, ID3D12Resource *pDestinationResource, ID3D12Resource *pIntermediate, uint FirstSubresource, uint NumSubresources, ulong RequiredSize, D3D12_PLACED_SUBRESOURCE_FOOTPRINT *pLayouts, uint *pNumRows, ulong *pRowSizesInBytes, D3D12_SUBRESOURCE_DATA *pSrcData)
        {
            // Minor validation
            D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc();
            D3D12_RESOURCE_DESC DestinationDesc  = pDestinationResource->GetDesc();

            if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_BUFFER ||
                IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset ||
                RequiredSize > ((IntPtr.Size == 4) ? uint.MaxValue : ulong.MaxValue) ||
                (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_BUFFER &&
                 (FirstSubresource != 0 || NumSubresources != 1)))
            {
                return(0);
            }

            byte *pData;
            int   hr = pIntermediate->Map(0, null, (void **)(&pData));

            if (TerraFX.Interop.Windows.FAILED(hr))
            {
                return(0);
            }

            for (var i = 0u; i < NumSubresources; ++i)
            {
                if (pRowSizesInBytes[i] > ((IntPtr.Size == 4) ? uint.MaxValue : ulong.MaxValue))
                {
                    return(0);
                }
                var DestData = new D3D12_MEMCPY_DEST
                {
                    pData      = pData + pLayouts[i].Offset,
                    RowPitch   = (UIntPtr)(pLayouts[i].Footprint.RowPitch),
                    SlicePitch = (UIntPtr)(pLayouts[i].Footprint.RowPitch * pNumRows[i])
                };
                MemcpySubresource(&DestData, &pSrcData[i], (UIntPtr)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth);
            }
            pIntermediate->Unmap(0, null);

            if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_BUFFER)
            {
                var SrcBox = new D3D12_BOX
                {
                    left   = (uint)pLayouts[0].Offset,
                    top    = 0,
                    front  = 0,
                    right  = (uint)pLayouts[0].Offset + pLayouts[0].Footprint.Width,
                    bottom = 1,
                    back   = 1
                };
                pCmdList->CopyBufferRegion(
                    pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);
            }
            else
            {
                for (var i = 0u; i < NumSubresources; ++i)
                {
                    var Dst = new D3D12_TEXTURE_COPY_LOCATION
                    {
                        pResource = pDestinationResource,
                        Type      = D3D12_TEXTURE_COPY_TYPE.D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
                        Anonymous = new D3D12_TEXTURE_COPY_LOCATION._Anonymous_e__Union
                        {
                            SubresourceIndex = i + FirstSubresource
                        }
                    };
                    var Src = new D3D12_TEXTURE_COPY_LOCATION
                    {
                        pResource = pIntermediate,
                        Type      = D3D12_TEXTURE_COPY_TYPE.D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
                        Anonymous = new D3D12_TEXTURE_COPY_LOCATION._Anonymous_e__Union
                        {
                            PlacedFootprint = pLayouts[i]
                        }
                    };
                    pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, null);
                }
            }
            return(RequiredSize);
        }
Exemplo n.º 26
0
        public void CreateWindowSizeDependentResources()
        {
            WaitForGpu();

            for (int n = 0; n < FrameCount; n++)
            {
                DirectXHelper.ReleaseCom(_renderTargets[n]);
                _renderTargets[n] = null;
                _fenceValues[n]   = _fenceValues[_currentFrame];
            }

            UpdateRenderTargetSize();

            DXGI_MODE_ROTATION displayRotation = ComputeDisplayRotation();

            bool swapDimensions =
                displayRotation == DXGI_MODE_ROTATION.DXGI_MODE_ROTATION_ROTATE90 ||
                displayRotation == DXGI_MODE_ROTATION.DXGI_MODE_ROTATION_ROTATE270;

            _d3dRenderTargetSize.Width  = swapDimensions ? _outputSize.Height : _outputSize.Width;
            _d3dRenderTargetSize.Height = swapDimensions ? _outputSize.Width : _outputSize.Height;

            uint backBufferWidth  = (uint)Math.Round(_d3dRenderTargetSize.Width, MidpointRounding.AwayFromZero);
            uint backBufferHeight = (uint)Math.Round(_d3dRenderTargetSize.Height, MidpointRounding.AwayFromZero);

            if (_swapChain != null)
            {
                HRESULT hr = _swapChain.Ptr->ResizeBuffers(FrameCount, backBufferWidth, backBufferHeight, _backBufferFormat,
                                                           0);

                if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
                {
                    _deviceRemoved = true;

                    return;
                }
                else
                {
                    DirectXHelper.ThrowIfFailed(hr);
                }
            }
            else
            {
                DXGI_SCALING scaling = DisplayMetrics.SupportHighResolutions
                    ? DXGI_SCALING.DXGI_SCALING_NONE
                    : DXGI_SCALING.DXGI_SCALING_STRETCH;

                DXGI_SWAP_CHAIN_DESC1 swapChainDesc;

                swapChainDesc.Width              = backBufferWidth;
                swapChainDesc.Height             = backBufferHeight;
                swapChainDesc.Format             = _backBufferFormat;
                swapChainDesc.Stereo             = 0;
                swapChainDesc.SampleDesc.Count   = 1;
                swapChainDesc.SampleDesc.Quality = 0;
                swapChainDesc.BufferUsage        = DXGI.DXGI_USAGE_RENDER_TARGET_OUTPUT;
                swapChainDesc.BufferCount        = FrameCount;
                swapChainDesc.SwapEffect         = DXGI_SWAP_EFFECT.DXGI_SWAP_EFFECT_FLIP_DISCARD;
                swapChainDesc.Flags              = 0;
                swapChainDesc.Scaling            = scaling;
                swapChainDesc.AlphaMode          = DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_IGNORE;

                {
                    using ComPtr <IDXGISwapChain1> swapChain = null;
                    IntPtr pWindow = Marshal.GetIUnknownForObject(_window);
                    DirectXHelper.ThrowIfFailed(
                        _dxgiFactory.Ptr->CreateSwapChainForCoreWindow(
                            _commandQueue,
                            (IUnknown *)pWindow,
                            &swapChainDesc,
                            null,
                            swapChain.GetAddressOf()));

                    IDXGISwapChain3 *swapChain3;
                    Guid             iid = DXGI.IID_IDXGISwapChain3;
                    DirectXHelper.ThrowIfFailed(swapChain.Ptr->QueryInterface(&iid, (void **)&swapChain3));
                    _swapChain = swapChain3;
                }
            }

            switch (displayRotation)
            {
            case DXGI_MODE_ROTATION.DXGI_MODE_ROTATION_IDENTITY:
                _orientationTransform3D = ScreenRotation.Rotation0;
                break;

            case DXGI_MODE_ROTATION.DXGI_MODE_ROTATION_ROTATE90:
                _orientationTransform3D = ScreenRotation.Rotation270;
                break;

            case DXGI_MODE_ROTATION.DXGI_MODE_ROTATION_ROTATE180:
                _orientationTransform3D = ScreenRotation.Rotation180;
                break;

            case DXGI_MODE_ROTATION.DXGI_MODE_ROTATION_ROTATE270:
                _orientationTransform3D = ScreenRotation.Rotation90;
                break;
            }

            DirectXHelper.ThrowIfFailed(_swapChain.Ptr->SetRotation(displayRotation));

            {
                _currentFrame = (int)_swapChain.Ptr->GetCurrentBackBufferIndex();
                D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = _rtvHeap.Ptr->GetCPUDescriptorHandleForHeapStart();

                fixed(void *pBuffer = & _renderTargets)
                {
                    var p = (ID3D12Resource **)pBuffer;

                    Guid iid = D3D12.IID_ID3D12Resource;

                    for (var n = 0; n < FrameCount; n++)
                    {
                        DirectXHelper.ThrowIfFailed(_swapChain.Ptr->GetBuffer((uint)n, &iid, (void **)&p[n]));
                        _d3dDevice.Ptr->CreateRenderTargetView(
                            _renderTargets[n],
                            null,
                            rtvDescriptor);

                        rtvDescriptor.Offset((int)_rtvDescriptorSize);

                        DirectXHelper.NameObject(_renderTargets[n], $"{nameof(_renderTargets)}[{n}]"); // _renderTargets[n]
                    }
                }
            }

            {
                D3D12_HEAP_PROPERTIES depthHeapProperties = CD3DX12_HEAP_PROPERTIES.Create(D3D12_HEAP_TYPE.D3D12_HEAP_TYPE_DEFAULT);

                D3D12_RESOURCE_DESC depthResourceDesc =
                    CD3DX12_RESOURCE_DESC.Tex2D(_depthBufferFormat, backBufferWidth, backBufferHeight, 1, 1);

                depthResourceDesc.Flags |= D3D12_RESOURCE_FLAGS.D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;

                D3D12_CLEAR_VALUE depthOptimizedClearValue = CD3DX12_CLEAR_VALUE.Create(_depthBufferFormat, 1, 0);

                fixed(ID3D12Resource **p = _depthStencil)
                {
                    Guid iid = D3D12.IID_ID3D12Resource;

                    DirectXHelper.ThrowIfFailed(_d3dDevice.Ptr->CreateCommittedResource(
                                                    &depthHeapProperties,
                                                    D3D12_HEAP_FLAGS.D3D12_HEAP_FLAG_NONE,
                                                    &depthResourceDesc,
                                                    D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_DEPTH_WRITE,
                                                    &depthOptimizedClearValue,
                                                    &iid,
                                                    (void **)p
                                                    ));

                    DirectXHelper.NameObject(_depthStencil, nameof(_depthStencil));

                    D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = default;

                    dsvDesc.Format        = _depthBufferFormat;
                    dsvDesc.ViewDimension = D3D12_DSV_DIMENSION.D3D12_DSV_DIMENSION_TEXTURE2D;
                    dsvDesc.Flags         = D3D12_DSV_FLAGS.D3D12_DSV_FLAG_NONE;
                    D3D12_CPU_DESCRIPTOR_HANDLE handle = _dsvHeap.Ptr->GetCPUDescriptorHandleForHeapStart();

                    _d3dDevice.Ptr->CreateDepthStencilView(_depthStencil.Ptr, &dsvDesc, handle);
                }
            }

            // 0.0f, 0.0f, m_d3dRenderTargetSize.Width, m_d3dRenderTargetSize.Height, 0.0f, 1.0f
            _screenViewport = new D3D12_VIEWPORT
            {
                TopLeftX = 0,
                TopLeftY = 0,
                Width    = (float)_d3dRenderTargetSize.Width,
                Height   = (float)_d3dRenderTargetSize.Height,
                MinDepth = 0,
                MaxDepth = 1
            };
        }
        // Load the sample assets.
        private void LoadAssets()
        {
            Guid      iid;
            ID3DBlob *signature    = null;
            ID3DBlob *error        = null;
            ID3DBlob *vertexShader = null;
            ID3DBlob *pixelShader  = null;

            try
            {
                // Create a root signature consisting of a descriptor table with a single CBV.
                {
                    var featureData = new D3D12_FEATURE_DATA_ROOT_SIGNATURE {
                        // This is the highest version the sample supports. If CheckFeatureSupport succeeds, the HighestVersion returned will not be greater than this.
                        HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1
                    };

                    if (FAILED(_device->CheckFeatureSupport(D3D12_FEATURE_ROOT_SIGNATURE, &featureData, (uint)sizeof(D3D12_FEATURE_DATA_ROOT_SIGNATURE))))
                    {
                        featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0;
                    }

                    const int RangesCount         = 1;
                    var       ranges              = stackalloc D3D12_DESCRIPTOR_RANGE1[RangesCount];
                    const int RootParametersCount = 1;
                    var       rootParameters      = stackalloc D3D12_ROOT_PARAMETER1[RootParametersCount];

                    ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC);
                    rootParameters[0].InitAsDescriptorTable(RangesCount, ranges, D3D12_SHADER_VISIBILITY_VERTEX);

                    // Allow input layout and deny unnecessary access to certain pipeline stages.
                    var rootSignatureFlags =
                        D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
                        D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
                        D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
                        D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |
                        D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;

                    var rootSignatureDesc = new D3D12_VERSIONED_ROOT_SIGNATURE_DESC();
                    rootSignatureDesc.Init_1_1(RootParametersCount, rootParameters, 0, null, rootSignatureFlags);

                    ThrowIfFailed(nameof(D3D12SerializeRootSignature), D3D12SerializeVersionedRootSignature(&rootSignatureDesc, featureData.HighestVersion, &signature, &error));

                    fixed(ID3D12RootSignature **rootSignature = &_rootSignature)
                    {
                        iid = IID_ID3D12RootSignature;
                        ThrowIfFailed(nameof(ID3D12Device.CreateRootSignature), _device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), &iid, (void **)rootSignature));
                    }
                }

                // Create the pipeline state, which includes compiling and loading shaders.
                {
                    var compileFlags = 0u;

#if DEBUG
                    // Enable better shader debugging with the graphics debugging tools.
                    compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
                    fixed(char *fileName = GetAssetFullPath(@"D3D12\Assets\Shaders\HelloConstBuffer.hlsl"))
                    {
                        var entryPoint = 0x00006E69614D5356;    // VSMain
                        var target     = 0x0000305F355F7376;    // vs_5_0

                        ThrowIfFailed(nameof(D3DCompileFromFile), D3DCompileFromFile((ushort *)fileName, pDefines: null, pInclude: null, (sbyte *)&entryPoint, (sbyte *)&target, compileFlags, Flags2: 0, &vertexShader, ppErrorMsgs: null));

                        entryPoint = 0x00006E69614D5350;        // PSMain
                        target     = 0x0000305F355F7370;        // ps_5_0
                        ThrowIfFailed(nameof(D3DCompileFromFile), D3DCompileFromFile((ushort *)fileName, pDefines: null, pInclude: null, (sbyte *)&entryPoint, (sbyte *)&target, compileFlags, Flags2: 0, &pixelShader, ppErrorMsgs: null));
                    }

                    // Define the vertex input layout.
                    const int InputElementDescsCount = 2;

                    var semanticName0 = stackalloc ulong[2] {
                        0x4E4F495449534F50,     // POSITION
                        0x0000000000000000,
                    };

                    var semanticName1 = stackalloc ulong[1] {
                        0x000000524F4C4F43,     // COLOR
                    };

                    var inputElementDescs = stackalloc D3D12_INPUT_ELEMENT_DESC[InputElementDescsCount] {
                        new D3D12_INPUT_ELEMENT_DESC {
                            SemanticName   = (sbyte *)semanticName0,
                            Format         = DXGI_FORMAT_R32G32B32_FLOAT,
                            InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
                        },
                        new D3D12_INPUT_ELEMENT_DESC {
                            SemanticName      = (sbyte *)semanticName1,
                            Format            = DXGI_FORMAT_R32G32B32A32_FLOAT,
                            AlignedByteOffset = 12,
                            InputSlotClass    = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,
                        },
                    };

                    // Describe and create the graphics pipeline state object (PSO).
                    var psoDesc = new D3D12_GRAPHICS_PIPELINE_STATE_DESC {
                        InputLayout = new D3D12_INPUT_LAYOUT_DESC {
                            pInputElementDescs = inputElementDescs,
                            NumElements        = InputElementDescsCount,
                        },
                        pRootSignature        = _rootSignature,
                        VS                    = new D3D12_SHADER_BYTECODE(vertexShader),
                        PS                    = new D3D12_SHADER_BYTECODE(pixelShader),
                        RasterizerState       = D3D12_RASTERIZER_DESC.DEFAULT,
                        BlendState            = D3D12_BLEND_DESC.DEFAULT,
                        DepthStencilState     = D3D12_DEPTH_STENCIL_DESC.DEFAULT,
                        SampleMask            = uint.MaxValue,
                        PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
                        NumRenderTargets      = 1,
                        SampleDesc            = new DXGI_SAMPLE_DESC(count: 1, quality: 0),
                    };
                    psoDesc.DepthStencilState.DepthEnable = FALSE;
                    psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;

                    fixed(ID3D12PipelineState **pipelineState = &_pipelineState)
                    {
                        iid = IID_ID3D12PipelineState;
                        ThrowIfFailed(nameof(ID3D12Device.CreateGraphicsPipelineState), _device->CreateGraphicsPipelineState(&psoDesc, &iid, (void **)pipelineState));
                    }
                }

                // Create the command list.
                fixed(ID3D12GraphicsCommandList **commandList = &_commandList)
                {
                    iid = IID_ID3D12GraphicsCommandList;
                    ThrowIfFailed(nameof(ID3D12Device.CreateCommandList), _device->CreateCommandList(nodeMask: 0, D3D12_COMMAND_LIST_TYPE_DIRECT, _commandAllocator, _pipelineState, &iid, (void **)commandList));
                }

                // Command lists are created in the recording state, but there is nothing
                // to record yet. The main loop expects it to be closed, so close it now.
                ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Close), _commandList->Close());

                // Create the vertex buffer.
                {
                    // Define the geometry for a triangle.
                    const int TriangleVerticesCount = 3;
                    var       triangleVertices      = stackalloc Vertex[TriangleVerticesCount] {
                        new Vertex {
                            Position = new Vector3(0.0f, 0.25f * AspectRatio, 0.0f),
                            Color    = new Vector4(1.0f, 0.0f, 0.0f, 1.0f)
                        },
                        new Vertex {
                            Position = new Vector3(0.25f, -0.25f * AspectRatio, 0.0f),
                            Color    = new Vector4(0.0f, 1.0f, 0.0f, 1.0f)
                        },
                        new Vertex {
                            Position = new Vector3(-0.25f, -0.25f * AspectRatio, 0.0f),
                            Color    = new Vector4(0.0f, 0.0f, 1.0f, 1.0f)
                        },
                    };

                    var vertexBufferSize = (uint)sizeof(Vertex) * TriangleVerticesCount;

                    // Note: using upload heaps to transfer static data like vert buffers is not
                    // recommended. Every time the GPU needs it, the upload heap will be marshalled
                    // over. Please read up on Default Heap usage. An upload heap is used here for
                    // code simplicity and because there are very few verts to actually transfer.
                    fixed(ID3D12Resource **vertexBuffer = &_vertexBuffer)
                    {
                        var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
                        var bufferDesc     = D3D12_RESOURCE_DESC.Buffer(vertexBufferSize);

                        iid = IID_ID3D12Resource;
                        ThrowIfFailed(nameof(ID3D12Device.CreateCommittedResource), _device->CreateCommittedResource(
                                          &heapProperties,
                                          D3D12_HEAP_FLAG_NONE,
                                          &bufferDesc,
                                          D3D12_RESOURCE_STATE_GENERIC_READ,
                                          pOptimizedClearValue: null,
                                          &iid,
                                          (void **)vertexBuffer
                                          ));
                    }

                    // Copy the triangle data to the vertex buffer.
                    var readRange = new D3D12_RANGE();

                    byte *pVertexDataBegin;
                    ThrowIfFailed(nameof(ID3D12Resource.Map), _vertexBuffer->Map(Subresource: 0, &readRange, (void **)&pVertexDataBegin));
                    Unsafe.CopyBlock(pVertexDataBegin, triangleVertices, vertexBufferSize);
                    _vertexBuffer->Unmap(0, null);

                    // Initialize the vertex buffer view.
                    _vertexBufferView.BufferLocation = _vertexBuffer->GetGPUVirtualAddress();
                    _vertexBufferView.StrideInBytes  = (uint)sizeof(Vertex);
                    _vertexBufferView.SizeInBytes    = vertexBufferSize;
                }

                // Create the constant buffer.
                {
                    fixed(ID3D12Resource **pConstantBuffer = &_constantBuffer)
                    {
                        var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
                        var bufferDesc     = D3D12_RESOURCE_DESC.Buffer(1024 * 64);

                        iid = IID_ID3D12Resource;
                        ThrowIfFailed(nameof(ID3D12Device.CreateCommittedResource), _device->CreateCommittedResource(
                                          &heapProperties,
                                          D3D12_HEAP_FLAG_NONE,
                                          &bufferDesc,
                                          D3D12_RESOURCE_STATE_GENERIC_READ,
                                          pOptimizedClearValue: null,
                                          &iid,
                                          (void **)pConstantBuffer));
                    }

                    // Describe and create a constant buffer view.
                    var cbvDesc = new D3D12_CONSTANT_BUFFER_VIEW_DESC {
                        BufferLocation = _constantBuffer->GetGPUVirtualAddress(),
                        SizeInBytes    = (uint)((sizeof(SceneConstantBuffer) + 255) & ~255) // CB size is required to be 256-byte aligned.
                    };

                    _device->CreateConstantBufferView(&cbvDesc, _cbvHeap->GetCPUDescriptorHandleForHeapStart());

                    // Map and initialize the constant buffer. We don't unmap this until the
                    // app closes. Keeping things mapped for the lifetime of the resource is okay.
                    var readRange = new D3D12_RANGE(); // We do not intend to read from this resource on the CPU.

                    fixed(byte **ppCbvDataBegin = &_pCbvDataBegin)
                    {
                        ThrowIfFailed(nameof(ID3D12Resource.Map), _constantBuffer->Map(Subresource: 0, &readRange, (void **)ppCbvDataBegin));
                        Unsafe.CopyBlock(ref _pCbvDataBegin[0], ref Unsafe.As <SceneConstantBuffer, byte>(ref _constantBufferData), (uint)sizeof(SceneConstantBuffer));
                    }

                    // Create synchronization objects and wait until assets have been uploaded to the GPU.
                    {
                        fixed(ID3D12Fence **fence = &_fence)
                        {
                            iid = IID_ID3D12Fence;
                            ThrowIfFailed(nameof(ID3D12Device.CreateFence), _device->CreateFence(0, D3D12_FENCE_FLAG_NONE, &iid, (void **)fence));
                            _fenceValue = 1;
                        }

                        // Create an event handle to use for frame synchronization.
                        _fenceEvent = CreateEventW(lpEventAttributes: null, bManualReset: FALSE, bInitialState: FALSE, lpName: null);
                        if (_fenceEvent == null)
                        {
                            var hr = Marshal.GetHRForLastWin32Error();
                            Marshal.ThrowExceptionForHR(hr);
                        }

                        // Wait for the command list to execute; we are reusing the same command
                        // list in our main loop but for now, we just want to wait for setup to
                        // complete before continuing.
                        WaitForPreviousFrame();
                    }
                }
            }
            finally
            {
                if (signature != null)
                {
                    signature->Release();
                }

                if (error != null)
                {
                    error->Release();
                }

                if (vertexShader != null)
                {
                    vertexShader->Release();
                }

                if (pixelShader != null)
                {
                    pixelShader->Release();
                }
            }
        }
        // Load the rendering pipeline dependencies.
        private void LoadPipeline()
        {
            Guid             iid;
            ID3D12Debug *    debugController = null;
            IDXGIFactory4 *  factory         = null;
            IDXGIAdapter *   adapter         = null;
            IDXGISwapChain1 *swapChain       = null;

            try
            {
                var dxgiFactoryFlags = 0u;

#if DEBUG
                // Enable the debug layer (requires the Graphics Tools "optional feature").
                // NOTE: Enabling the debug layer after device creation will invalidate the active device.
                {
                    iid = IID_ID3D12Debug;
                    if (SUCCEEDED(D3D12GetDebugInterface(&iid, (void **)&debugController)))
                    {
                        debugController->EnableDebugLayer();

                        // Enable additional debug layers.
                        dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
                    }
                }
#endif

                iid = IID_IDXGIFactory4;
                ThrowIfFailed(nameof(CreateDXGIFactory2), CreateDXGIFactory2(dxgiFactoryFlags, &iid, (void **)&factory));

                if (UseWarpDevice)
                {
                    iid = IID_IDXGIAdapter;
                    ThrowIfFailed(nameof(IDXGIFactory4.EnumWarpAdapter), factory->EnumWarpAdapter(&iid, (void **)&adapter));
                }
                else
                {
                    adapter = GetHardwareAdapter((IDXGIFactory1 *)factory);
                }

                fixed(ID3D12Device **device = &_device)
                {
                    iid = IID_ID3D12Device;
                    ThrowIfFailed(nameof(D3D12CreateDevice), D3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_11_0, &iid, (void **)device));
                }

                // Describe and create the command queue.
                var queueDesc = new D3D12_COMMAND_QUEUE_DESC();

                fixed(ID3D12CommandQueue **commandQueue = &_commandQueue)
                {
                    iid = IID_ID3D12CommandQueue;
                    ThrowIfFailed(nameof(ID3D12Device.CreateCommandQueue), _device->CreateCommandQueue(&queueDesc, &iid, (void **)commandQueue));
                }

                // Describe and create the swap chain.
                var swapChainDesc = new DXGI_SWAP_CHAIN_DESC1 {
                    BufferCount = FrameCount,
                    Width       = Width,
                    Height      = Height,
                    Format      = DXGI_FORMAT_B8G8R8A8_UNORM,
                    BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
                    SwapEffect  = DXGI_SWAP_EFFECT_FLIP_DISCARD,

                    // The swap chain could do multisampling for you in older versions of Direct3D
                    // You might see this in tutorials for D3D11
                    // This is no longer supported, so the swapchain has no multisampling itself
                    SampleDesc = new DXGI_SAMPLE_DESC(count: 1, quality: 0),
                };

                ThrowIfFailed(nameof(IDXGIFactory4.CreateSwapChainForHwnd), factory->CreateSwapChainForHwnd(
                                  (IUnknown *)_commandQueue, // Swap chain needs the queue so that it can force a flush on it.
                                  Win32Application.Hwnd,
                                  &swapChainDesc,
                                  pFullscreenDesc: null,
                                  pRestrictToOutput: null,
                                  &swapChain
                                  ));

                // This sample does not support fullscreen transitions.
                ThrowIfFailed(nameof(IDXGIFactory4.MakeWindowAssociation), factory->MakeWindowAssociation(Win32Application.Hwnd, DXGI_MWA_NO_ALT_ENTER));

                fixed(IDXGISwapChain3 **swapChain3 = &_swapChain)
                {
                    iid = IID_IDXGISwapChain3;
                    ThrowIfFailed(nameof(IDXGISwapChain1.QueryInterface), swapChain->QueryInterface(&iid, (void **)swapChain3));
                    _frameIndex = _swapChain->GetCurrentBackBufferIndex();
                }

                // Check MSAA support
                CheckMultiSamplingSupport();

                // Create descriptor heaps.
                {
                    // Describe and create a render target view (RTV) descriptor heap.
                    var rtvHeapDesc = new D3D12_DESCRIPTOR_HEAP_DESC {
                        NumDescriptors = 1, // We only have 1 render target
                        Type           = D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
                    };

                    fixed(ID3D12DescriptorHeap **rtvHeap = &_rtvHeap)
                    {
                        iid = IID_ID3D12DescriptorHeap;
                        ThrowIfFailed(nameof(ID3D12Device.CreateDescriptorHeap), _device->CreateDescriptorHeap(&rtvHeapDesc, &iid, (void **)rtvHeap));
                    }

                    _rtvDescriptorSize = _device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
                }

                // Create the render target
                // We do not use the back buffer as that cannot be multisampled
                {
                    var desc = new D3D12_RESOURCE_DESC {
                        Height           = Height,
                        Width            = Width,
                        DepthOrArraySize = 1,
                        Alignment        = 0,
                        SampleDesc       = _msaaDesc,
                        Dimension        = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
                        Flags            = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
                        Format           = DXGI_FORMAT_B8G8R8A8_UNORM,
                        Layout           = D3D12_TEXTURE_LAYOUT_UNKNOWN,
                        MipLevels        = 1
                    };

                    var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

                    var clearColor = stackalloc float[4] {
                        0.0f, 0.2f, 0.4f, 1.0f
                    };
                    var clearVal = new D3D12_CLEAR_VALUE(DXGI_FORMAT_B8G8R8A8_UNORM, clearColor);

                    ID3D12Resource *multisampledRenderTarget;
                    iid = IID_ID3D12Resource;
                    ThrowIfFailed(nameof(ID3D12Device.CreateCommittedResource), _device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_RENDER_TARGET, &clearVal, &iid, (void **)&multisampledRenderTarget));
                    _multiSampledRenderTarget = multisampledRenderTarget;
                }

                // Create the render target for the multisampled render target
                {
                    var rtvHandle = _rtvHeap->GetCPUDescriptorHandleForHeapStart();
                    _device->CreateRenderTargetView(_multiSampledRenderTarget, pDesc: null, rtvHandle);
                }

                // Create frame resources.
                {
                    iid = IID_ID3D12Resource;

                    for (var n = 0u; n < FrameCount; n++)
                    {
                        ID3D12Resource *renderTarget;
                        {
                            ThrowIfFailed(nameof(IDXGISwapChain3.GetBuffer), _swapChain->GetBuffer(n, &iid, (void **)&renderTarget));
                        }
                        _renderTargets[unchecked ((int)n)] = renderTarget;
                    }
                }

                fixed(ID3D12CommandAllocator **commandAllocator = &_commandAllocator)
                {
                    iid = IID_ID3D12CommandAllocator;
                    ThrowIfFailed(nameof(ID3D12Device.CreateRenderTargetView), _device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, &iid, (void **)commandAllocator));
                }
            }
            finally
            {
                if (debugController != null)
                {
                    debugController->Release();
                }

                if (factory != null)
                {
                    factory->Release();
                }

                if (adapter != null)
                {
                    adapter->Release();
                }

                if (swapChain != null)
                {
                    swapChain->Release();
                }
            }
        }
Exemplo n.º 29
0
 /// <summary>
 /// Creates a new <see cref="GpuResourceFormat"/> from a <see cref="D3D12_RESOURCE_DESC"/>
 /// </summary>
 public GpuResourceFormat(D3D12_RESOURCE_DESC d3d12ResourceDesc)
 {
     D3D12ResourceDesc = d3d12ResourceDesc;
 }
        private unsafe void CreateAssets()
        {
            ID3D12Device *d3dDevice = _deviceResources.D3DDevice;

            Guid iid;

            {
                iid = D3D12.IID_ID3D12GraphicsCommandList;
                ID3D12GraphicsCommandList *commandList;
                ThrowIfFailed(d3dDevice->CreateCommandList(
                                  0,
                                  D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_DIRECT,
                                  _deviceResources.CommandAllocator,
                                  _pipelineState.Ptr,
                                  &iid,
                                  (void **)&commandList));

                _commandList = commandList;
                DX.NameD3D12Object(_commandList.Ptr, nameof(_commandList));
            }

            // Cube vertices. Each vertex has a position and a color.
            const uint           vertexPositionColorCount = 8;
            VertexPositionColor *cubeVertices             = stackalloc VertexPositionColor[(int)vertexPositionColorCount]
            {
                new VertexPositionColor {
                    pos = new Vector3(-0.5f, -0.5f, -0.5f), color = new Vector3(0.0f, 0.0f, 0.0f)
                },
                new VertexPositionColor {
                    pos = new Vector3(-0.5f, -0.5f, 0.5f), color = new Vector3(0.0f, 0.0f, 1.0f)
                },
                new VertexPositionColor {
                    pos = new Vector3(-0.5f, 0.5f, -0.5f), color = new Vector3(0.0f, 1.0f, 0.0f)
                },
                new VertexPositionColor {
                    pos = new Vector3(-0.5f, 0.5f, 0.5f), color = new Vector3(0.0f, 1.0f, 1.0f)
                },
                new VertexPositionColor {
                    pos = new Vector3(0.5f, -0.5f, -0.5f), color = new Vector3(1.0f, 0.0f, 0.0f)
                },
                new VertexPositionColor {
                    pos = new Vector3(0.5f, -0.5f, 0.5f), color = new Vector3(1.0f, 0.0f, 1.0f)
                },
                new VertexPositionColor {
                    pos = new Vector3(0.5f, 0.5f, -0.5f), color = new Vector3(1.0f, 1.0f, 0.0f)
                },
                new VertexPositionColor {
                    pos = new Vector3(0.5f, 0.5f, 0.5f), color = new Vector3(1.0f, 1.0f, 1.0f)
                }
            };

            Debug.Assert(sizeof(VertexPositionColor) == Marshal.SizeOf <VertexPositionColor>());
            uint vertexBufferSize = (uint)sizeof(VertexPositionColor) * vertexPositionColorCount;

            using ComPtr <ID3D12Resource> vertexBufferUpload = default;

            D3D12_HEAP_PROPERTIES defaultHeapProperties =
                CD3DX12_HEAP_PROPERTIES.Create(D3D12_HEAP_TYPE.D3D12_HEAP_TYPE_DEFAULT);

            D3D12_RESOURCE_DESC vertexBufferDesc = CD3DX12_RESOURCE_DESC.Buffer(vertexBufferSize);

            {
                iid = D3D12.IID_ID3D12Resource;
                ID3D12Resource *vertexBuffer;
                ThrowIfFailed(d3dDevice->CreateCommittedResource(
                                  &defaultHeapProperties,
                                  D3D12_HEAP_FLAGS.D3D12_HEAP_FLAG_NONE,
                                  &vertexBufferDesc,
                                  D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST,
                                  null,
                                  &iid,
                                  (void **)&vertexBuffer));

                _vertexBuffer = vertexBuffer;
            }

            iid = D3D12.IID_ID3D12Resource;
            D3D12_HEAP_PROPERTIES uploadHeapProperties =
                CD3DX12_HEAP_PROPERTIES.Create(D3D12_HEAP_TYPE.D3D12_HEAP_TYPE_UPLOAD);

            ThrowIfFailed(d3dDevice->CreateCommittedResource(
                              &uploadHeapProperties,
                              D3D12_HEAP_FLAGS.D3D12_HEAP_FLAG_NONE,
                              &vertexBufferDesc,
                              D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_GENERIC_READ,
                              null,
                              &iid,
                              (void **)vertexBufferUpload.GetAddressOf()));

            DX.NameD3D12Object(_vertexBuffer.Ptr, nameof(_vertexBuffer));

            {
                D3D12_SUBRESOURCE_DATA vertexData;
                vertexData.pData      = (byte *)cubeVertices;
                vertexData.RowPitch   = (IntPtr)vertexBufferSize;
                vertexData.SlicePitch = vertexData.RowPitch;

                Functions.UpdateSubresources(
                    _commandList.Ptr,
                    _vertexBuffer.Ptr,
                    vertexBufferUpload.Ptr,
                    0, 0, 1,
                    &vertexData);

                D3D12_RESOURCE_BARRIER vertexBufferResourceBarrier =
                    CD3DX12_RESOURCE_BARRIER.Transition(_vertexBuffer.Ptr,
                                                        D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST,
                                                        D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);

                _commandList.Ptr->ResourceBarrier(1, &vertexBufferResourceBarrier);
            }

            const int cubeIndicesCount = 36;
            ushort *  cubeIndices      = stackalloc ushort[cubeIndicesCount]
            {
                0,
                2,
                1, // -x
                1,
                2,
                3,

                4,
                5,
                6, // +x
                5,
                7,
                6,

                0,
                1,
                5, // -y
                0,
                5,
                4,

                2,
                6,
                7, // +y
                2,
                7,
                3,

                0,
                4,
                6, // -z
                0,
                6,
                2,

                1,
                3,
                7, // +z
                1,
                7,
                5,
            };
            const uint indexBufferSize = sizeof(ushort) * cubeIndicesCount;

            using var indexBufferUpload = new ComPtr <ID3D12Resource>();

            D3D12_RESOURCE_DESC indexBufferDesc = CD3DX12_RESOURCE_DESC.Buffer(indexBufferSize);

            {
                iid = D3D12.IID_ID3D12Resource;
                ID3D12Resource *indexBuffer;
                ThrowIfFailed(d3dDevice->CreateCommittedResource(
                                  &defaultHeapProperties,
                                  D3D12_HEAP_FLAGS.D3D12_HEAP_FLAG_NONE,
                                  &indexBufferDesc,
                                  D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST,
                                  null,
                                  &iid,
                                  (void **)&indexBuffer));
                _indexBuffer = indexBuffer;
            }

            iid = D3D12.IID_ID3D12Resource;
            ThrowIfFailed(d3dDevice->CreateCommittedResource(
                              &uploadHeapProperties,
                              D3D12_HEAP_FLAGS.D3D12_HEAP_FLAG_NONE,
                              &indexBufferDesc,
                              D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_GENERIC_READ,
                              null,
                              &iid,
                              (void **)indexBufferUpload.GetAddressOf()));

            DX.NameD3D12Object(_indexBuffer.Ptr, nameof(_indexBuffer));

            {
                D3D12_SUBRESOURCE_DATA indexData;
                indexData.pData      = (byte *)cubeIndices;
                indexData.RowPitch   = (IntPtr)indexBufferSize;
                indexData.SlicePitch = indexData.RowPitch;

                Functions.UpdateSubresources(
                    _commandList.Ptr,
                    _indexBuffer.Ptr,
                    indexBufferUpload.Ptr,
                    0, 0, 1,
                    &indexData);

                D3D12_RESOURCE_BARRIER indexBufferResourceBarrier =
                    CD3DX12_RESOURCE_BARRIER.Transition(_indexBuffer.Ptr,
                                                        D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST,
                                                        D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_INDEX_BUFFER);

                _commandList.Ptr->ResourceBarrier(1, &indexBufferResourceBarrier);
            }

            {
                D3D12_DESCRIPTOR_HEAP_DESC heapDesc;
                heapDesc.NumDescriptors = DeviceResources.FrameCount;
                heapDesc.Type           = D3D12_DESCRIPTOR_HEAP_TYPE.D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
                heapDesc.Flags          = D3D12_DESCRIPTOR_HEAP_FLAGS.D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;

                {
                    ID3D12DescriptorHeap *cbvHeap;
                    iid = D3D12.IID_ID3D12DescriptorHeap;
                    ThrowIfFailed(d3dDevice->CreateDescriptorHeap(&heapDesc, &iid, (void **)&cbvHeap));
                    _cbvHeap = cbvHeap;
                    DX.NameD3D12Object(_cbvHeap.Ptr, nameof(_cbvHeap));
                }
            }

            D3D12_RESOURCE_DESC constantBufferDesc = CD3DX12_RESOURCE_DESC.Buffer(
                DeviceResources.FrameCount * AlignedConstantBufferSize);

            {
                iid = D3D12.IID_ID3D12Resource;
                ID3D12Resource *constantBuffer;
                ThrowIfFailed(d3dDevice->CreateCommittedResource(
                                  &uploadHeapProperties,
                                  D3D12_HEAP_FLAGS.D3D12_HEAP_FLAG_NONE,
                                  &constantBufferDesc,
                                  D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_GENERIC_READ,
                                  null,
                                  &iid,
                                  (void **)&constantBuffer));
                _constantBuffer = constantBuffer;

                DX.NameD3D12Object(_constantBuffer.Ptr, nameof(_constantBuffer));
            }

            D3D12_GPU_VIRTUAL_ADDRESS   cbvGpuAddress = _constantBuffer.Ptr->GetGPUVirtualAddress();
            D3D12_CPU_DESCRIPTOR_HANDLE cbvCpuHandle  = _cbvHeap.Ptr->GetCPUDescriptorHandleForHeapStart();

            _cbvDescriptorSize =
                d3dDevice->GetDescriptorHandleIncrementSize(
                    D3D12_DESCRIPTOR_HEAP_TYPE.D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);

            for (var i = 0; i < DeviceResources.FrameCount; i++)
            {
                D3D12_CONSTANT_BUFFER_VIEW_DESC desc;
                desc.BufferLocation = cbvGpuAddress;
                desc.SizeInBytes    = AlignedConstantBufferSize;
                d3dDevice->CreateConstantBufferView(&desc, cbvCpuHandle);
                cbvGpuAddress += desc.SizeInBytes;
                cbvCpuHandle.Offset((int)_cbvDescriptorSize);
            }

            D3D12_RANGE readRange = CD3DX12_RANGE.Create((UIntPtr)0, (UIntPtr)0);

            fixed(byte **p = &_mappedConstantBuffer)
            {
                ThrowIfFailed(_constantBuffer.Ptr->Map(0, &readRange, (void **)p));
                Unsafe.InitBlockUnaligned(_mappedConstantBuffer, 0, DeviceResources.FrameCount * AlignedConstantBufferSize);
            }

            ThrowIfFailed(_commandList.Ptr->Close());
            const int           ppCommandListCount = 1;
            ID3D12CommandList **ppCommandLists     = stackalloc ID3D12CommandList *[ppCommandListCount]
            {
                (ID3D12CommandList *)_commandList.Ptr
            };

            _deviceResources.CommandQueue->ExecuteCommandLists(ppCommandListCount, ppCommandLists);

            _vertexBufferView.BufferLocation = _vertexBuffer.Ptr->GetGPUVirtualAddress();
            _vertexBufferView.StrideInBytes  = (uint)sizeof(VertexPositionColor);
            _vertexBufferView.SizeInBytes    = vertexBufferSize;

            _indexBufferView.BufferLocation = _indexBuffer.Ptr->GetGPUVirtualAddress();
            _indexBufferView.SizeInBytes    = indexBufferSize;
            _indexBufferView.Format         = DXGI_FORMAT.DXGI_FORMAT_R16_UINT;

            _deviceResources.WaitForGpu();
        }

        #endregion
    }
}