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); }
//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); }
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); }
/// <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); } }
/// <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) { }
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); }
/// <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) { }
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); }
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,
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); }
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)); }
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)); }
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)); }
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)); }
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)); }
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); }
/// <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); }
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); } }
// 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(); } } }
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); } }
// 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(); } } }
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); }
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(); } } }
/// <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 } }